Seite wählen

NETWAYS Blog

Cluster-Quelladresse ändern mit Pacemaker

Heute möchte ich gerne eine Möglichkeit vorstellen die Quelladresse eines Clusters mit Pacemaker zu ändern.
Es gibt bereits ein vorgefertiges OCF-Resource-Agent-Skript namens IPsrcaddr, dieses hat allerdings im Test bei mir nicht zuverlässig funktioniert, sodass ich mich entschied einen eigenen Resource-Agent zu implementieren:

#!/bin/bash
#
# Resource script for source adresses
#
# Description:  This script removes and adds source addresses.
#
# Author:       Carsten Wolfrum 
# License:      GNU General Public License (GPL)
# Copyright:    (C) NETWAYS GmbH
#
# OCF parameters:
# OCF_RESKEY_srcip
# OCF_RESKEY_interface
#
##########################################################################
# Initialization:
. ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs
##########################################################################
SRCIP=$OCF_RESKEY_srcip
INTERFACE=$OCF_RESKEY_interface
usage() {
  cat <<-!
usage: $0 {start|stop|status|monitor|validate-all|meta-data}
action:
        start           sets new source IP
        stop            sets main IP as source
        status          return running if the new source IP is set, not running if main IP is set
        methods         return the set of commands we support
        monitor         return TRUE if the IP address is the default outgoing address.
        meta-data       show meta data message
        validate-all    validate the instance parameters
	!
  exit $OCF_ERR_ARGS
}
meta_data()
{
cat <


1.0

This script removes and adds source addresses.

This script removes and adds source addresses.



The new source address.

The new source address.



The interface the new source address is bound on.

The interface the new source address is bound on.










END
exit $OCF_SUCCESS
}
validate_all()
{
	INTERFACETEST=$(ip a list dev $INTERFACE)
	if [ "$?" != 0 ]; then
		echo -n $INTERFACETEST
		exit $OCF_ERR_CONFIGURED
	fi
	IPTEST=$(ip a list dev $INTERFACE | grep $SRCIP)
	if [ "$?" != 0 ]; then
		echo "IP $SRCIP is not configured on interface $INTERFACE!"
		exit $OCF_ERR_CONFIGURED
	fi
        return $OCF_SUCCESS
}
monitor()
{
	SRCTEST=$(ip route | grep $INTERFACE | grep src | grep $SRCIP)
	if [ "$?" != 0 ]; then
		return $OCF_NOT_RUNNING
	fi
	return $OCF_SUCCESS
}
status()
{
	monitor
}
start()
{
	SUBNET=$(ip route | grep $INTERFACE | grep link | grep src | cut -d " " -f 1)
	DEFAULTGW=$(ip route |grep default | cut -d " " -f 3)
	ip route replace $SUBNET dev $INTERFACE src $SRCIP
	ip route replace default via $DEFAULTGW dev $INTERFACE src $SRCIP
}
stop()
{
	MAINIP=$(ip a list $INTERFACE | grep inet | head -1 | cut -d " " -f 6 | cut -d "/" -f 1)
	SUBNET=$(ip route | grep $INTERFACE | grep link | grep src | cut -d " " -f 1)
	DEFAULTGW=$(ip route |grep default | cut -d " " -f 3)
	ip route replace $SUBNET dev $INTERFACE src $MAINIP
	ip route replace default via $DEFAULTGW dev $INTERFACE
}
case $1 in
        start)
                validate_all
                start
                ;;
        stop)
                validate_all
                stop
                ;;
        status)
                status
                ;;
        monitor)
                monitor
                ;;
        validate-all)
                validate_all
                ;;
        meta-data)
                meta_data
                ;;
        notify|promote|demote)
                exit $OCF_ERR_UNIMPLEMENTED
                ;;
        usage)  usage
                exit $OCF_SUCCESS
                ;;
        *)      usage
                exit $OCF_ERR_UNIMPLEMENTED
                ;;
esac

Dieser Resource-Agent kann z.B. dazu verwendet werden um die Quell-IP von Icinga-Checks zu setzen. Dies hat den Vorteil z.B. im Falle eines 2-Knoten-Cluster nicht beide IPs in Firewall/NRPE-Daemons eintragen zu müssen, es kann dann die Cluster-IP verwendet werden.
Der Resource-Agent muss als ausführbare Datei z.B. namens IPsrcaddr2 in ein Unterverzeichnis von /usr/lib/ocf/resource.d abgelegt werden, z.B. in /usr/lib/ocf/resource.d/custom. Die Konfiguration in Corosync/Pacemaker erfolgt dann mittels:
# crm configure primitive cluster-ip-src ocf:custom:IPsrcaddr2 srcip="QUELLIP" interface="INTERFACE_DER_QUELLIP"
Beim Schwenk auf den aktiven Knoten wird dann die angegebene IP als Quell-IP für ausgehende Verbindungen benutzt, beim Schwenk von diesem Knoten wird wieder die erste konfiguierte IP des angegebenen Interfaces als Quell-IP benutzt.

IPv6-Autokonfiguration mit radvd

IPv6 beherrscht ein Feature namens Stateless Address Autoconfiguration, dieses dient dazu Clients zustandlos dynamische IPv6-Adressen zuzuweisen.
Dies geschieht unter Linux mittels des Daemons radvd, welcher auf dem für das Netz zuständigen Router betrieben wird und Router Advertisments versendet.
Größter Nachteil bei der Verwendung von Stateless Address Autoconfiguration ist derzeit noch dass keine Informationen zu z.B. DNS-Servern und NTP-Servern übergeben werden können, dies muss derzeit noch zusätzlich z.B. über einen DHCPv6-Server realisiert werden.
Die Konfiguration von radvd selbst ist relativ einfach und soll hier am Beispiel des Site-lokalen Netzes fec0:0:0:0::/64 erläutert werden:

  1. IPv6-Routing aktivieren:
    in /etc/sysctl.conf:
    net.ipv6.conf.all.forwarding=1
    sysctl.conf neu einlesen:
    # sysctl -p

  2. radvd installieren, z.B. unter Debian mittels:
    # aptitude install radvd
  3. /etc/radvd.conf editieren:
    interface eth0 {
      AdvSendAdvert on;
      prefix fec0:0:0:0::/64
      {
        AdvOnLink on;
        AdvAutonomous on;
      };
    };
  4. radvd starten:
    # /etc/init.d/radvd start

radvd ist somit fertig konfiguiert und wird das Netz an der Schnittstelle eth0 für die Autokonfiguration von Clients bekanntgeben.

Windows-Monitoring mit check_wmi_plus

Heute stelle ich eine Alternative zu NSClient++ vor: check_wmi_plus.
check_wmi_plus erlaubt agentloses (d.h. es ist kein seperater Dienst auf dem Windows-Server zu installieren) Monitoring von Windows-Maschinen bei (fast) gleicher Standard-Funktionalität wie NSClient++, die jeweiligen Checks wurden auch inklusive Performance-Daten implementiert.
Dabei sind allerdings einige Fallstricke zu beachten, die ich hier erläutern werde.
Das Checkplugin selbst ist nach Installationsanleitung zu installieren, der WMI-Client für Linux (wmic) ist entweder aus Distributionspaketen zu installieren oder aus dem Quelltext, falls kein Paket vorliegt (z.B. Debian).
Anschließend ist auf dem zu überwachenden Windows-Server ein Benutzer anzulegen und wie folgt Rechte zu setzen:

  • benötigte Windows-Gruppen: Distributed Com-Benutzer, Ereignisprotokolleser, Leistungsprotokollbenutzer, Leistungsüberwachungsbenutzer
  • im MMC-Snapin WMI-Steuerung dem Benutzer die Rechte Methoden ausführen, Konto aktivieren und Remoteaktivierung auf den Teilbaum ROOT\CIMV2 setzen:

Zum Überwachen von Services sind noch 2 weitere Schritte im Windows-CLI (cmd.exe) notwendig:

  • Generelle Rechte für das Abfragen von Services für Remote freigeben:
    sc sdset SCMANAGER D:(A;;CCLCRPRC;;;AU)(A;;CCLCRPRC;;;IU)(A;;CCLCRPRC;;;SU)(A;;CCLCRPWPRC;;;SY)(A;;KA;;;BA)S:(AU;FA;KA;;;WD)(AU;OIIOFA;GA;;;WD)
  • mittels SubInACL Rechte auf Services freigeben:
    subinacl /service \\server\* /grant=domain\user=QSI

Abschließend ist noch zu Überprüfen ob der WMI-Dienst gestartet ist und ob die Windows-Firewall eventuell den WMI-Dienst blockiert.
Die nun nutzbaren Checks sind hier dokumentiert.

ODBC-Datenbankzugriff mit Powershell

Es gibt manchmal Situationen, in denen man eine Datenbank abfragen muss, der ODBC-Treiber allerdings nur für Windows verfügbar ist und auch keine zusätzliche Skriptsprache installiert werden soll.
Hierfür bietet sich Microsofts objektorientierte Powershell an, mittels derer ein Datenbankzugriff über ODBC relativ einfach zu bewerkstelligen ist. Die Powershell hat außerdem den Vorteil bei aktuellen Windows-Versionen wie z.B. Windows Server 2008 R2 und Windows 7 bereits vorinstalliert zu sein.
Anbei ein kurzes Beispielskript, das exemplarisch eine Verbindung zu einer MSSQL-Datenbank aufbaut, einen Query ausführt und das Ergebnis von selbigem anzeigt:

#DSN angeben, dabei sind _SERVERNAME_, _DATABASE_, _DBUSER_ und _DBPASSWORD_ jeweils zu ersetzen
$DBDSN="Driver={SQL Server};Server=_SERVERNAME_;Database=_DATABASE_;UID=_DBUSER_;PWD=_DBPASSWORD_;"
#Datenbankverbindungsobjekt instanzieren
$DBConnection=New-Object System.Data.Odbc.OdbcConnection
#DSN im Objekt setzen
$DBConnection.ConnectionString=$DBDSN
#Datenbankverbindung öffnen
$DBConnection.Open()
#Datenbankbefehlsobjekt instanzieren
$DBCommand=New-Object System.Data.Odbc.OdbcCommand
#Datenbankverbindung in Befehlsobjekt setzen
$DBCommand.Connection=$DBConnection
#Query angeben, dabei muss _QUERY_ durch das gewünschte Query ersetzt werden
$DBCommand.CommandText="_QUERY_"
#Ein Reader-Objekt erzeugen
$DBResult=$DBCommand.ExecuteReader()
#Anzahl der Rows zählen
#DBCounter=$DBResult.FieldCount
#Rows durchiterieren
while ($DBResult.Read()) {
	for ($i = 0; $i -lt $DBCounter; $i++) {
		#Rows formatiert ausgeben
		@{ $DBResult.GetName($i) = $DBResult.GetValue($i); }
	}
}
#Datenbankverbindung schließen
DBConnection.Close()

Das Skript ist in einer Datei mit .ps1-Endung zu speichern, anschließend muss noch die ExecutionPolicy auf RemoteSigned gesetzt werden, da sonst unsignierte Skripte auch lokal nicht ausgeführt werden dürfen:

PS C:\> Set-ExecutionPolicy RemoteSigned

Anschließend kann das Skript wie folgt aufgerufen werden:

PS C:\> .\odbc-test.ps1

Das Skript erzeugt in unserem Fall z.B. folgende Ausgabe:

Name Value
---- -----
Test Testvalue

Das ganze kann z.B. sehr gut dazu benutzt werden um Icinga-Plugins für Windows zu entwickeln, die einen lokalen ODBC-Treiber verwenden und per NSClient++ aufgerufen werden. Hierzu bietet es sich dann an das Skript mit entsprechenden Parametern zu erweitern und das Skript Exit Codes zurückliefern zu lassen. NSClient++ selbst bietet in seiner Standardkonfiguration bereits Beispiele, wie Powershell-Skripte anzusprechen sind.