Hyper-V Failover Cluster – Geplanter Shutdown bei Stromausfall mit USV

Wer ein Microsoft Failover Cluster betreibt, hat bestimmt auch eine USV im Einsatz. Diese soll verhindern, dass die Knoten bei einem kleinen Spannungsabfall nicht sofort ausgehen, dass die Server keine Überspannung abbekommen und das bei einem längeren Ausfall die Systeme kontrolliert herunterfahren.

Da ich gerade für mein eigenes Azure Stack HCI Cluster, abgesichert über eine Eaton USV, solch ein Skript schreibe, sollt ihr auch daran teilhaben und vielleicht noch das ein oder andere lernen, wie ein Cluster die Ressourcen verwaltet und steuert.

Die verschiedenen Möglichkeiten

Wenn es zu einem Stromausfall kommt, und die Failover Cluster Knoten sollen kontrolliert heruntergefahren werden, gibt es mehrere Möglichkeiten. Je nach Art und Weise gibt es gewisse Vor- bzw. Nachteile, die ich hier gerne ein wenig näher erläutern möchte.

Na dann fahr halt einfach runter…

In den Standard-Einstellungen der meisten USV-Agenten ist es so, dass ein Server nach einer gewissen Zeit (120 Sekunden bei Eaton) heruntergefahren wird.

Grundsätzlich ja eine ganz nette Sache, wäre da nicht das Failover Cluster. In den Eigenschaften des Clusters gibt es einen Wert DrainOnShutdown.

Diese Einstellung bewirkt, dass ein Cluster-Knoten bei einem Shutdown versucht, die aktuell auf ihm ausgeführten VMs mittels Livemigration bzw. Schnellmigration auf andere Knoten zu verschieben, bevor der Server dann final heruntergefahren wird.

Im schlimmsten Fall führt diese Einstellung dazu, dass sich beide Knoten (oder alle Knoten bei mehr als zwei Systemen) gegenseitig die VMs zuschieben, obwohl sie sich gerade beide jeweils im Shutdown-Prozess befinden. Das verlängert die Zeit für das Herunterfahren künstlich und führt auch zu keinem brauchbaren Ergebnis. Daher sollte diese Art von Shutdown vermieden werden durch die USV.

Shutdown aller VMs

Damit die Knoten keine Livemigration machen, wäre ein Shutdown der virtuellen Systeme sinnvoll. Jetzt sollte man bei einem Failover Cluster aber darauf achten, dass man die VMs über das Failover Cluster herunterfährt, und nicht lokal.

Der Shutdown einer VM lokal wäre über ein

Stop-VM

möglich. Da aber die Rolle im Failover Cluster vorhanden ist, und die VM häufig auf einem beliebigen Knoten laufen kann, muss an dieser Stelle angesetzt werden. Hierbei ist es wichtig, dass man zum einen den korrekten Namen ausfindig macht (OwnerGroup statt Name) und zum anderen den Shutdown-Prozess nur für die VMs ausführt, die auch auf dem jeweiligen Knoten aktiv laufen.

$info = hostname
$VMs = Get-ClusterResource | ? ResourceType -eq "Virtual Machine" | select OwnerGroup, OwnerNode

Write-Host -ForegroundColor Green "VMs auf diesem Knoten, die heruntergefahren werden:"
Write-Host -ForegroundColor Green "###################################################"
foreach ($VM in $VMs) {
    if ($VM.OwnerNode -eq $info) {
        Write-Host $VM.OwnerGroup
        Stop-VM -Name $VM.OwnerGroup -Force
    }
}

Das kleine Skript liest in Zeile 1 den aktuellen Hostnamen aus. Danach werden alle Ressourcen im Cluster gespeichert, die eine Ressource “Virtual Machine” sind. Damit wir nicht alles speichern müssen, selektiere ich die Ausgabe auf OwnerGroup (Der Name der VM) und den aktuellen OwnerNode.
Nun werden alle Ressourcen in der Variable $VMs in einer Schleife abgearbeitet, und wenn sie auf dem lokalen Knoten laufen, werden Sie heruntergefahren. Damit ein Shutdown einer angemeldeten VM auch dann passiert, wenn noch aktiv Benutzer angemeldet sind (Terminal Server, geschlossene Sitzungen usw…), wird der Parameter -force mitgeliefert.

Shutdown des Failover Cluster

Wenn nun alle VMs ausgeschaltet bzw. heruntergefahren sind, können wir nun das Failover Cluster herunterfahren. Dies geschieht über den Befehl

Stop-Cluster

An dieser Stelle haben wir nun ein kleines Problem. Welcher Knoten fährt das Cluster herunter? Macht es jeder, kann es sein dass die anderen Systeme im Cluster noch nicht fertig sind mit dem Shutdown-Vorgang der VMs und das wir diesen Prozess dadurch aktiv stören. Um diesem Szenario vorzubeugen, gibt es mehrere Möglichkeiten.

Eine dieser Möglichkeiten könnte sein, dass immer der erste Knoten im Cluster den Shutdown-Prozess durchführt. Dies wäre aber nicht möglich, wenn sich der Knoten in Wartung befindet und keine Befehle im Cluster absetzen kann. Das ist also keine gute Lösung.

Ich habe mir an dieser Stelle die folgende Lösung überlegt: Ich prüfe, welcher Server im Cluster die Cluster-Ressource (IP, Name, …) betreibt. Da dies nur möglich ist, wenn der Knoten online und aktiv ist, muss dieser Server zwangsläufig in der Lage sein, das Cluster zu beenden.
Weiterhin prüfe ich den Status der VMs. Sind noch VMs online (z.B. weil der Shutdown-Vorgang auf dem Partner-System noch dauert), wartet der Server eine kurze Zeit und prüft den Zustand wieder. Dies wird so lange gemacht, bis alle VMs ausgeschaltet sind und das Cluster gefahrlos beendet werden kann.

$info = hostname
$ClusterOwnerNode = Get-ClusterResource | ? ResourceType -eq "IP Address" | select OwnerNode
if ($info -match $ClusterOwnerNode.OwnerNode)
{
    Write-Host -ForegroundColor Green "Dieser Knoten ist der aktuelle Master und leitet den Shutdown-Prozess ein"
    

        do
        {
            $VMs = Get-ClusterResource | ? ResourceType -eq "Virtual Machine"
            if ($VMs.State -match "Online")
            {
                Write-Host -ForegroundColor Green "Mindestens eine VM noch online, warten"
                sleep 5
            }
        }
        until ($VMs.State -notmatch "Online")
        
    Write-Host -ForegroundColor Green "Alles aus, Shutdown vom Cluster kann durchgeführt werden"
    Stop-Cluster
}

Die andere Möglichkeit: VMs im Cluster automatisch herunterfahren

Ein Failover Cluster speichert normalerweise alle VMs, die es betreibt, wenn es beendet wird. Dies wird über die Eigenschaften der Cluster-VM-Ressource geregelt, die man sich per PowerShell anzeigen lassen kann. Wichtig ist hierbei, dass die Eigenschaft nicht direkt in der Ressource selbst angezeigt wird, sondern in den Cluster-Parametern. Diese werden nach der Filterung auf eine spezifische VM nochmal explizit abgefragt:

Get-ClusterResource | ? OwnerGroup -eq "VMName" | Get-ClusterParameter

Hier können wir den Wert OfflineAction sehen. Dieser steht in den Standard-Einstellungen auf 1. Gesetzt werden können die Werte 0 bis 3.

WertEinstellung
0Die VM wird hart abgeschaltet
1Die VM wird gespeichert
2Die VM wird über das Gast-OS heruntergefahren
3Die VM wird über das Gast-OS heruntergefahren inkl. Zwang

Setzen wir diesen Wert nun auf 2 statt auf 1, werden alle VMs bei dem Stop des Clusters automatisch heruntergefahren. Wäre auch eine Möglichkeit, diese Anforderung hier zu lösen, ich verbleibe aber an dieser Stelle bei meinem Skript und benutze dies, um meine virtuellen Systeme planmäßig herunterzufahren.

Da diese Eigenschaft immer pro VM gesetzt wird, muss bei der Erstellung einer neuen VM auch darauf geachtet werden, dass die Eigenschaft gesetzt wird. Wird dies nicht gemacht, hat die VM im Cluster wieder die Eigenschaft 1 und wird gespeichert. Hier wäre z.B. ein geplanter Task hilfreich, der in regelmäßigen Abständen für alle VMs den gewünschten Wert per PowerShell setzt.

Das komplette Shutdown-Skript

Damit nun auf jedem Cluster Knoten ein einziges Skript ausgeführt wird, welches sämtliche Aufgaben bei einem Shutdown regelt, wird auf meinem beiden S2D Knoten das folgende Skript implementiert:

### Skript zum automatischen Shutdown eines Failover
### Clusters durch eine USV (In meinem Fall Eaton)
### 11.11.2020 - Helau :)
### Letztes Update - 12.08.2024
### Jan Kappen - j.kappen@building-networks.de
#
# Shutdown der VMs, die auf diesem Knoten betrieben werden
$info = hostname
$VMs = Get-ClusterResource | ? ResourceType -eq "Virtual Machine" | select OwnerGroup, OwnerNode

Write-Host -ForegroundColor Green "VMs auf diesem Knoten, die heruntergefahren werden:"
Write-Host -ForegroundColor Green "###################################################"
foreach ($VM in $VMs) {
    if ($VM.OwnerNode -eq $info) {
        Write-Host $VM.OwnerGroup
        Stop-VM -Name $VM.OwnerGroup -Force
    }
}

# Cluster herunterfahren auf dem aktuellen Besitzer der Cluster-IP
$ClusterOwnerNode = Get-ClusterResource | ? ResourceType -eq "IP Address" | select OwnerNode
if ($info -match $ClusterOwnerNode.OwnerNode)
{
    Write-Host -ForegroundColor Green "Dieser Knoten ist der aktuelle Master und leitet den Shutdown-Prozess ein"
        do
        {
            $VMs = Get-ClusterResource | ? ResourceType -eq "Virtual Machine"
            if ($VMs.State -match "Online")
            {
                Write-Host -ForegroundColor Green "Mindestens eine VM noch online, warten auf"
                sleep 5
            }
        }
        until (($VMs.State | where {$_ -eq "Online"} | Measure-Object | select -ExpandProperty Count) -eq 0)
    Write-Host -ForegroundColor Green "Alles aus, Shutdown vom Cluster kann durchgeführt werden"
    sleep 30
    Stop-Cluster -Confirm:$false -Force
}

# Lokalen Server herunterfahren
sleep 60
Stop-Computer -ComputerName localhost -Force

Nun muss das ganze noch in den Agenten der USV eingebunden werden. Da ich in meinem Fall nur ein Batch-Skript hinterlegen kann, rufe ich einfach innerhalb des Batch-Skripts eine PowerShell auf, die dann als Skript meine oben aufgeführte Datei ausführt.

Einbinden in den Eaton IPP Agenten

In den Eigenschaften des Eaton IPP setze ich nun eine .bat-Datei, die folgenden Inhalt hat:

C:\windows\system32\WindowsPowerShell\v1.0\Powershell.exe -executionpolicy remotesigned -File  C:\script\eaton_shutdown_powershell.ps1

Damit wird dann mein Shutdown-Skript innerhalb der PowerShell aufgerufen, in dann den schon gezeigten Inhalt hat.

Testen, testen, testen!

Die schönsten Skripte bringen nichts, wenn sich irgendwo ein Fehler eingeschlichen hat und die durchgeführte Änderung nicht greift. Daher gilt: Wenn der USV-Agent installiert und konfiguriert ist, schnappt euch eine geplante Wartung und testet die Installation. Kappt die Stromverbindung der USV, stoppt die Zeit und beobachtet, ob alles wie geplant klappt oder ob es irgendwo einen Engpass gibt oder ob im schlimmsten Fall überhaupt nichts passieren würde.

Weiterhin sollte in regelmäßigen Abständen die Laufzeit der USV geprüft werden. Häufig werden solche Einrichtungen wie hier direkt bei Anschaffung der Geräte gemacht, wo noch nicht alles per USV abgesichert ist. Im Laufe der Zeit kommen immer mehr Geräte hinzu, die Laufzeit sinkt und die initial eingestellten Werte passen nicht mehr. Solche Dinge lassen sich auch gut monitoren, hier ein Beispiel aus meiner Infrastruktur:


Sie benötigten persönliche Unterstützung oder haben nicht die richtige Lösung für Ihr Problem gefunden?

Dieser Blog wird von mir, Jan Kappen, in seiner Freizeit betrieben, hier beschreibe ich Lösungen für Probleme aller Art oder technische Anleitungen mit Lösungsansätzen.

Die berufliche Unabhängigkeit

Ich bin seit Januar 2020 vollständig selbstständig und habe meine eigene Firma gegründet, die Building Networks mit Sitz in Winterberg im schönen Sauerland. Hier stehe ich als Dienstleister gerne für Anfragen, Support oder Projekte zur Verfügung.

Die Firma Building Networks bietet Ihnen:

  • Hilfe und Support per Telefon, Fernwartung oder persönlich vor Ort
  • Projekt-Unterstützung
  • Ausgezeichnete Kompetenz zu den Themen
    • Microsoft Hyper-V
    • Microsoft Failover Clustering & HA
    • Storage Spaces Direct (S2D) & Azure Stack HCI
    • Veeam Backup & Recovery
    • Microsoft Exchange
    • Microsoft Exchange Hybrid Infrastruktur
    • Microsoft Active Directory
    • Microsoft Office 365
    • Ubiquiti
    • 3CX VoIP PBX
    • Fortinet Network Security
    • Baramundi Software
    • ...

Ich freue mich über Ihren Kontakt, weitere Informationen finden Sie auf der Webseite meiner Firma unter Building-Networks.de

Jan

Jan Kappen arbeitet seit 2005 in der IT. Er hat seine Ausbildung 2008 abgeschlossen und war bis 2018 als IT-Consultant im Bereich Hyper-V, Failover Clustering und Software Defined Storage unterwegs. Seit 2015 wurde er jährlich von Microsoft als Most Valuable Professional (MVP) im Bereich "Cloud & Datacenter Management" ausgezeichnet für seine Kenntnisse und die Weitergabe seines Wissens. Jan ist häufig auf Konferenzen als Sprecher zu finden, weiterhin bloggt er viel. Von September 2018 bis Dezember 2019 war Jan als Senior Network- und Systemadministrator bei einem großen mittelständischen Unternehmen im schönen Sauerland angestellt. Im Januar 2020 hat er den Sprung in die Selbstständigkeit gewagt und ist seitdem Geschäftsführer der Firma Building Networks in Winterberg. In seiner Freizeit kümmert er sich um das Freifunk-Netzwerk in Winterberg und Umgebung.

3 Kommentare:

  1. Hallo Jan, gibt es eine Möglichkeit eine Abfrage zu starten welches prüft ob der Partnerknoten im Wartungsmodus ist. Möchte gerne ein Script erstellen welches prüft ob am zweiten Standort die USV auch keinen Strom mehr hat. DIeses soll dann nur denn Knoten an einem Standort abschalten und dabei die VMs auf den Partnerknoten umziehen. Danke

    • Hallo,
      ja diese Möglichkeiten bestehen. Dazu muss das Skript erweitert werden, und es muss eine Abfrage eingebaut werden, bei der z.B. die USV direkt per SNMP abgefragt wird. Hier muss man dann den passenden Wert abfragen und prüfen (z.B. Spannung am Eingang der USV), und kann dann definieren, bei welchem Zustand dann die jeweilige Aktion ausgeführt wird. Das keine Sache von fünf Minuten, sollte aber grundsätzlich möglich sein.
      Schönen Gruß
      Jan

  2. Hallo Jan, hab dein Script getestet. Beim abschalten des Cluster wartet er nur bis eine VM auf dem Partner System heruntergefahren ist und schaltet dan den Cluster ab auch wenn noch nicht alle VMs abgeschalten sind. 🙁 Da bei der Schleife ein offline reicht. Gruß Marko

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert