Benachrichtigung bei VM-Ausfall

TErxleben

Renowned Member
Oct 20, 2008
522
69
93
Noch eine Frage, die mir schon lange durch den Kopf geht:
Wie könnte ich mich im PVE-Universum benachrichtigen lassen, dass eine VM seit x-Minuten nicht erreichbar ist?
Muss ich bei parallelen fettleibigen Monitoringlösungen verbleiben?
 
Last edited:
Muss ich bei parallelen fettleibigen Monitoringlösungen verbleiben?
Naja, was "dick" ist, hängt auch vom Beobachter ab.

Man kann Uptime Kuma durchaus als beides bezeichnen; ich lasse das extern laufen, um Verfügbarkeit von außen testen zu können - also so, also ob ein Dritter auf meine Dienste zugreift.

Intern verwende ich Zabbix, und ja, das ist definitiv "dick" :-)

Vermutlich wolltest du nur "wie geht das mit PVE-Bordmitteln?" wissen. Ohne basteln klappt das meiner Kenntnis nach nicht.

Aber "dünne" (Bash-, Python-, whatever-) Scripte der Art "falls fünfmal kein Ping <meineVM> dann Email" sind natürlich mit Bordmitteln von Debian möglich. Es gibt auch diverse fertige Tools für so etwas.
 
  • Like
Reactions: Johannes S
Aber "dünne" (Bash-, Python-, whatever-) Scripte der Art "falls fünfmal kein Ping <meineVM> dann Email"
Genau das habe ich in einem Netz mit zwei PVE-hosts umgesetzt. Funktioniert wunderbar:

Code:
#!/bin/bash

# Pihole-Failover

MAILTO="info@beispiel.de"

while true; do
  sleep 10

  RUNNING=`nmap -p 67 -sU pihole | grep open | wc -l
`
  if [ $RUNNING -lt 1 ]; then
#    echo "STARTE (LXC401) (pihole) wegen Failover"
    pct start 401
    echo "FAILOVER: "Pihole (LXC401) wurde auf PVE1 gestartet, da der Master (LXC400) auf PVE seit 10s nicht erreichbar ist. " | mutt -s "FAILOVER" -- $MAILTO
  fi
done

Man muss den Failover-Pihole nur manuell wieder herunterfahren, was aber einfacher ist als einen kompletten DHCP/DNS-Ausfall auszubügeln. Selbst wenn beide parallel laufen, führt das nicht schlagartig zu einem totalem Kuddelmuddel.
Das ganze ist sogar "schmaler", als selbiges auf VM-Ebene abzufideln.
 
Last edited:
  • Like
Reactions: UdoB
Moinsen,
auch wenn ihr vermutlich (?) von wesentlich größeren settings redet, als ich hier im kleinen homelab *husthust administriere...ich bin faul und scripten ist echt nicht meins. Deswegen nutze ich zum Überwachen das "nicht ganz so dicke" Uptimekuma für Portmonitoring und einfachen Ping. Dies läuft für alle container und vms / lxcs einmal dem proxmox host selbst (in einer vm als container).
Dann habe ich eine 2. uptimekuma Instanz auf dem NAS, welche nur den proxmox host und das dortige uptimekuma monitored.
Beide senden ggf. per Mail, sollte etwas nicht "online" sein.
Zusätzlich (läuft ja eh) auf dem Raspi mit Home Assistant die uptimekuma Integration, welche beide uptimekuma Instanzen (NAS und VM mit u.a. uptimekuma) überwacht und ggf. eine Nachricht schickt...
Schnell einzurichten, gegenseitig etwas abgesichert und einfache Pflege. Fürs homelab zumindest. Früher auch mal in checkmk reingeschnuppert (und schnell wieder verlassen, da viel zu dick für meine Bedürfnisse).

und dann gibt es da noch das recht kleine und schlanke beszel, das ebenfalls läuft und per agenten (die zB per docker container auf dem jeweiligen host eingespielt werden können) andere Systeme überwacht.
:)
 
Last edited:
  • Like
Reactions: Johannes S and UdoB
uptimekuma
Kenn ich nun nicht, werde es aber mal antesten.
Die neun Scriptzeilen von mir, erzeugen aber minimalsten Overhead um die allerwichtigsten Dienste am Start zu halten. Heutzutage ist das WLAN natürlich auch extrem wichtig. Da bietet aber per Mesh schon ganz elegant Failover.
Raucht dein Switch ab, dann hast du eh verloren oder mit viel Geld Redundanz geschaffen. Sonst musst du dann eben manuell umstöpseln. Sofern man einen Ersatzswitch im Regal liegen hat oder gar schon ins Rack geschraubt hast, dann geht das ruckzuck. Die Dinger habe ich in meinem Berufsleben allerdings als extrem zuverlässig erlebt. Die gehen nur kaputt, wenn du mit einem Radlader drüberfährst.
 
Last edited:
Mann kann solches Monitoring auch mit Webmin aufbauen. Dabei können dann auch gleich gezielt die Linux Dienste, Programme oder Datenbanken geprüft werden und man lässt sich per eMail oder anderem benachrichtigen.
Je nachdem wo man das mit aufsetzt, kann man sein Linux gleich mit managen oder administrieren.
 
Es gibt natürlich einen ganzen Sack an Tools. Allen gemein ist, dass der Ausfall von DNS/DHCP sie auch plättet.
Da benutze ich lieber das von mir gepostete Script, welches auf x PVE-Hosts läuft. Im Desasterfall ist mir auch egal, ob es womöglich mehrere identische Piholes parallel startet. Sicherlich Holzhammermethode aber eben mit minimalem Wartungsaufwand.
 
Last edited:
Ich habe am o.g. Mini-script nochmal so gefeilt, dass bei Wiederverfügbarkeit der MasterVM die FailoverVM automatisch gestoppt wird.
Vielleicht ist es für manche ganz nützlich.

Bash:
#!/bin/bash

# Failover für VMs auf mehreren Proxmox-hosts.
# Script am besten als systemd-Service auf allen hosts integrieren, die ein Failover durchfüren sollen.
# Bei Hosts, die als Backup eines Failoverhosts dienen sollen, sollte man die SLEEPTIME passend erhöhen.
# Vorraussetzung ist ein konfigurierter Postfix, um Benachrichtgungen zu versenden
# mutt als mailclient
# nmap um fehlende Dienste zu identifizieren
# sshpass falls man ohne public key authentication arbeiten möchte.
# Letzteres ist in lokalen Netzen m.E. durchaus vertretbar.

MAILTO="fail@example.de"
SLEEPTIME=30            # wir prüfen hier alle 30s solange kein DELAY-Wert die Spanne verlängert.
DELAY200=360            # wir warten VM-individuell sicherheitshalber x Sekunden bis die Master-VM wieder am Start sind.
DELAY400=120            # Die Werte sind wichtig, damit wir uns nicht selbst überholen.
                        # Lieber hoch einsteigen und ggfs. reduzieren.
while true; do
  sleep $SLEEPTIME
  RUNNING=`nmap -p 67 -sU pihole | grep open | wc -l`
  RUNNING1=`nmap -p 8080 gua | grep open | wc -l`
  MAYBESTOP400=`pct status 400 | grep running | wc -l`
  MAYBESTOP200=`pct status 200 | grep running | wc -l`
  if [ $RUNNING == 0 ]; then
    echo "Dienst pihole ist im Netz nicht erreichbar."
    pct start 400
    echo "FAILOVER: pihole LXC400 wurde auf PVE gestartet. Bitte kontrollieren und ggf. manuell stoppen, sobald der Master wieder betriebsbereit ist." | mutt -s "FAILOVER Pihole TES von PVE auf PVE1" -- $MAILTO
  fi
  if [ $RUNNING1 == 0 ]; then
    echo "Dienst guacamole ist im Netz nicht erreichbar."
    pct start 200
    echo "FAILOVER: Guacamole LXC200 wurde auf PVE gestartet. Bitte kontrollieren und ggf. manuell stoppen, sobald der Master wieder betriebsbereit ist." | mutt -s "FAILOVER Guacamole TES von PVE auf PVE1" -- $MAILTO
  fi
  if [ $MAYBESTOP400 == 1 ]; then
    echo "Failover LXC400 (pihole) aktiv."
    # Wir prüfen ob der Master wieder läuft
    SHUTDOWN400=`sshpass -p 'ganzgeheim' ssh root@pve1 pct list | grep 400 | grep running | wc -l`
    if [ $SHUTDOWN400 == 1 ]; then
      echo "Master pihole wieder aktiv Failover wird deaktiviert."
      pct shutdown 400
      sleep $DELAY400
    fi
  fi
  if [ $MAYBESTOP200 == 1 ]; then
    echo "Failover LXC200 (guacamole) aktiv."
    # Wir prüfen ob der Master wieder läuft
    SHUTDOWN200=`sshpass -p 'ganzgeheim' ssh root@pve1 pct list | grep 200 | grep running | wc -l`
    if [ $SHUTDOWN200 == 1 ]; then
      echo "Master guacamole wieder aktiv Failover wird deaktiviert."
      pct shutdown 200
      sleep $DELAY200
    fi
  fi
done

failover.service sieht so aus.

Code:
[Unit]
Description=Failover Proxmox-VMs

[Service]
Type=simple
ExecStart=/bin/bash /root/failover.sh


[Install]
WantedBy=multi-user.target
 
Last edited:
Um die Sache, für den zwangsläufig folgenden Wünsch nach Aktualisierung der cold-standby-VMs, zu komplettieren noch ein lecker script von @cwt, welches diese aktualisiert.
Geändert habe ich lediglich eine Zeile. Nachzulesen hier: https://forum.proxmox.com/threads/a...h-von-gestoppten-vms-lxcs.169906/#post-793070.

Code:
#!/usr/bin/env bash
set -euo pipefail


NODE="$(hostname)"                 # Lokaler PVE-Node, auf dem restored wird
PBS_STORE="pbs"                    # Name des eingebundenen PBS-Storage in PVE
TARGET_STORE="local-lvm"           # Ziel-Storage für Restore (anpassen)
VMIDS=("200" "400" "107")          # IDs der Cold-Standby-Instanzen (VM & LXC gemischt möglich)
DRYRUN="${DRYRUN:-0}"              # DRYRUN=1 -> nur anzeigen, nichts ausführen
KEEP_CONFIG_BACKUP=1               # Legt vor dem Destroy ein qm/pct config-Backup an


need() { command -v "$1" >/dev/null || { echo "Fehlt: $1"; exit 1; }; }
need pvesh; need jq

log(){ echo "[$(date +'%F %T')] $*"; }

get_latest_volid() {
  local vmid="$1"
  # holt neueste Backup-VolID (volid wie: pbs:backup/vm/101/2025-08-15T19:01:23Z)
  pvesh get "/nodes/${NODE}/storage/${PBS_STORE}/content" \
    -content backup -vmid "${vmid}" --output-format json \
  | jq -r 'max_by(.ctime) | .volid'
}

detect_type_from_volid() {
  local volid="$1"
  if [[ "$volid" == *"/vm/"* ]]; then echo "qemu"; else echo "lxc"; fi
#  if [[ "$volid" == *"vzdump-qemu-"* ]]; then echo "qemu"; else echo "lxc"; fi
}

stop_and_destroy() {
  local type="$1" vmid="$2"
  if [[ "$type" == "qemu" ]]; then
    qm stop "$vmid" || true
    [[ "$KEEP_CONFIG_BACKUP" -eq 1 ]] && qm config "$vmid" >"/root/qm-${vmid}-$(date +%F-%H%M).conf" || true
    qm destroy "$vmid" --purge 1 --destroy-unreferenced-disks 1
  else
    pct stop "$vmid" || true
    [[ "$KEEP_CONFIG_BACKUP" -eq 1 ]] && pct config "$vmid" >"/root/pct-${vmid}-$(date +%F-%H%M).conf" || true
    pct destroy "$vmid" --purge 1
  fi
}

do_restore() {
  local type="$1" vmid="$2" volid="$3"
  if [[ "$type" == "qemu" ]]; then
    # Hinweis: --unique 0 -> behält MAC/SMBIOS wie im Backup (gut für echtes Failover)
    qmrestore "$volid" "$vmid" --storage "$TARGET_STORE" --force 1 --unique 0
    qm set "$vmid" --onboot 0 || true   # sicherheitshalber nicht automatisch starten
  else
    pct restore "$vmid" "$volid" --storage "$TARGET_STORE" --force 1
    pct set "$vmid" -onboot 0 || true
  fi
}

for VMID in "${VMIDS[@]}"; do
  log "== Bearbeite VMID ${VMID} =="
  VOLID="$(get_latest_volid "$VMID" || true)"
  if [[ -z "$VOLID" || "$VOLID" == "null" ]]; then
    log "!! Keine Backups im PBS für VMID ${VMID} gefunden – skip"
    continue
  fi

  TYPE="$(detect_type_from_volid "$VOLID")"

  log "Neueste Sicherung: ${VOLID} (Typ: ${TYPE})"

  if [[ "$DRYRUN" -eq 1 ]]; then
    log "[DRYRUN] Würde ${TYPE} ${VMID} zerstören und aus ${VOLID} nach ${TARGET_STORE} restoren."
    continue
  fi

  stop_and_destroy "$TYPE" "$VMID"
  do_restore "$TYPE" "$VMID" "$VOLID"
  log "✔ Restore fertig: ${TYPE} ${VMID} aus ${VOLID} → ${TARGET_STORE} (gestoppt belassen)"
done

log "Alle Jobs erledigt."
 
  • Like
Reactions: mattes_201180
Nochmal nachgedengelt.
Da ich mit dem Script auch meinen DNS/DHCP-Server (Pihole) redundant halte, kann man sich natürlich mächtig ins Knie schießen, falls der nicht aus dem Kreuz kommt.
So habe ich nun einen Mischbetrieb zwischen Fester IP und DHCP-clients.
Pihole und die PVE-Host haben sowieso feste IPs.
Meinen wichtigen SSH-Proxy habe ich manuell auf Feste IP umgestellt.
Guacamole und Homeassistant aber auf dem DHCP-Standard belassen.

Siehe script:

Code:
#!/bin/bash

# Failover für Proxmox-hosts.
# Script am besten als systemd-Service auf allen hosts integrieren, die ein Failover durchfüren sollen.
# Bei Hosts, die als Backup eines Failoverhosts dienen sollen, Sollte man die SLEEPTIME passend erhöhen.
# Vorraussetzung ist ein konfigurierter Postfix, um Benachrichtgungen zu versenden
# mutt als mailclient
# nmap um fehlende Dienste zu identifizieren
# sshpass falls man ohne public key authentication arbeiten möchte.
# Letzteres ist in lokalen Netzen m.E. durchaus vertretbar.
# Wichtig ist die qemu-guest agents auf den zu behandelnden Gästen installiert und aktiviert sind.
# Sonst klappt der shutdown nicht.


MAILTO="mail@irgendwer.de"
SLEEPTIME=30            # wir prüfen hier alle 30s solange kein DELAY-Wert die Spanne verlängert.
DELAY200=360            # wir warten VM-individuell sicherheitshalber x Sekunden bis die Master-VM wieder am Start sind.
DELAY400=120            # Die Werte sind wichtig, damit wir uns nicht selbst überholen.
DELAY107=30             # Die Werte sind wichtig, damit wir uns nicht selbst überholen.
DELAY112=120            # Die Werte sind wichtig, damit wir uns nicht selbst überholen.
                        # Lieber hoch einsteigen und ggfs. reduzieren.

MASTERPVE="192.168.100.201"
PIHOLEIP="192.168.100.251"
#GUACAMOLEIP="192.168.100.197"
SSHPROXYIP="192.168.100.250"

while true; do
  sleep $SLEEPTIME
  RUNNING400=`nmap -p 67 -sU $PIHOLEIP | grep open | wc -l`
#  RUNNING200=`nmap -p 8080 $GUACAMOLEIP | grep open | wc -l`
  RUNNING200=`nmap -p 8080 gua | grep open | wc -l`
  RUNNING107=`nmap -p 8123 homeassistant | grep open | wc -l`
  RUNNING112=`nmap -p 22 $SSHPROXYIP | grep open | wc -l`

  MAYBESTOP400=`pct status 400 | grep running | wc -l`
  MAYBESTOP200=`pct status 200 | grep running | wc -l`
  MAYBESTOP107=`qm status 107 | grep running | wc -l`
  MAYBESTOP112=`qm status 112 | grep running | wc -l`
  if [ $RUNNING400 == 0 ]; then
    echo "Dienst pihole ist im Netz nicht erreichbar."
    pct start 400
    echo "FAILOVER TES: pihole LXC400 wurde auf PVE gestartet. Bitte kontrollieren und ggf. manuell stoppen, sobald der Master wieder betriebsbereit ist." | mutt -s "FAILOVER TES Pihole von PVE1 auf PVE" -- $MAILTO
  fi
  if [ $RUNNING200 == 0 ]; then
    echo "Dienst guacamole ist im Netz nicht erreichbar."
    pct start 200
    echo "FAILOVER TES: Guacamole LXC200 wurde auf PVE gestartet. Bitte kontrollieren und ggf. manuell stoppen, sobald der Master wieder betriebsbereit ist." | mutt -s "FAILOVER TES Guacamole von PVE1 auf PVE" -- $MAILTO
  fi
  if [ $RUNNING107 == 0 ]; then
    echo "Dienst homeassistant ist im Netz nicht erreichbar."
    qm start 107
    echo "FAILOVER TES: Homeassistant VM107 wurde auf PVE gestartet. Bitte kontrollieren und ggf. manuell stoppen, sobald der Master wieder betriebsbereit ist." | mutt -s "FAILOVER TES Homeassistant von PVE1 auf PVE" -- $MAILTO
  fi
  if [ $RUNNING112 == 0 ]; then
    echo "Dienst ssh-proxy ist im Netz nicht erreichbar."
    qm start 112
    echo "FAILOVER: ssh-Proxy VM112 wurde auf PVE gestartet. Bitte kontrollieren und ggf. manuell stoppen, sobald der Master wieder betriebsbereit ist." | mutt -s "FAILOVER TES: SSH-Proxy läuft nun auf PVE" -- $MAILTO
  fi
  if [ $MAYBESTOP400 == 1 ]; then
    echo "Failover LXC400 (pihole) aktiv."
    # Wir prüfen ob der Master wieder läuft
    SHUTDOWN400=`sshpass -p 'GeheimPW' ssh root@$MASTERPVE pct list | grep 400 | grep running | wc -l`
    if [ $SHUTDOWN400 == 1 ]; then
      echo "Master pihole wieder aktiv Failover wird deaktiviert."
      pct shutdown 400
      echo "FAILOVER TES beendet: Master pihole wieder aktiv." | mutt -s "RECOVER TES: pihole läuft wieder auf PVE1" -- $MAILTO
      sleep $DELAY400
    fi
  fi
  if [ $MAYBESTOP200 == 1 ]; then
    echo "Failover LXC200 (guacamole) aktiv."
    # Wir prüfen ob der Master wieder läuft
    SHUTDOWN200=`sshpass -p 'GeheimPW' ssh root@$MASTERPVE pct list | grep 200 | grep running | wc -l`
    if [ $SHUTDOWN200 == 1 ]; then
      echo "Master guacamole wieder aktiv Failover wird deaktiviert."
      pct shutdown 200
      echo "FAILOVER TES beendet: Master guacamole wieder aktiv." | mutt -s "RECOVER TES: guacamole läuft wieder auf PVE1" -- $MAILTO
      sleep $DELAY200
    fi
  fi
  if [ $MAYBESTOP107 == 1 ]; then
    echo "Failover VM107 (homeassistant) aktiv."
    # Wir prüfen ob der Master wieder läuft
    SHUTDOWN107=`sshpass -p 'GeheimPW' ssh root@$MASTERPVE qm list | grep 107 | grep running | wc -l`
    if [ $SHUTDOWN107 == 1 ]; then
      echo "Master homeassistant wieder aktiv Failover wird deaktiviert."
      qm shutdown 107
      echo "FAILOVER TES beendet: Master homeassistant wieder aktiv." | mutt -s "RECOVER TES: homeassistant läuft wieder auf PVE1" -- $MAILTO
      sleep $DELAY107
    fi
  fi
  if [ $MAYBESTOP112 == 1 ]; then
    echo "Failover VM112 SSH-Proxy aktiv."
    # Wir prüfen ob der Master wieder läuft
    SHUTDOWN112=`sshpass -p 'GeheimPW' ssh root@$MASTERPVE qm list | grep 112 | grep running | wc -l`
    if [ $SHUTDOWN112 == 1 ]; then
      echo "Master SSH-Proxy wieder aktiv Failover wird deaktiviert."
      qm shutdown 112
      echo "FAILOVER TES beendet: Master SSH-Proxy wieder aktiv." | mutt -s "RECOVER TES: SSH-Proxy läuft wieder auf PVE1" -- $MAILTO
      sleep $DELAY112
    fi
  fi

done