Proxmox OS Image Backup Script
Ein plötzlicher Ausfall der Betriebssystemfestplatte eines Proxmox-Cluster-Nodes kann zu erheblichen Ausfallzeiten und viel manueller Arbeit führen. Normalerweise bedeutet das, dass man den betroffenen Node neu installiert und ihn wieder in den Cluster einbindet. Doch dies hat den Nachteil, dass alle individuellen Konfigurationen, Netzwerk-Einstellungen, Anwendungen und Systemdienste neu eingerichtet werden müssen.
Da ich diesen Aufwand vermeiden wollte, habe ich ein Experiment gestartet. Ich wollte herausfinden, ob es möglich ist, die OS-Disk eines Proxmox-Nodes zu klonen und im Falle eines Ausfalls einfach ein Backup zurückzuspielen, um den Node schnell und unkompliziert wieder in Betrieb zu nehmen. Hier teile ich meine Erfahrungen und die Vorgehensweise, die mir hoffentlich Zeit spart im Ernstfall.
Das Experiment: Klonen und Wiederherstellen der OS-Disk
In einem Test-Cluster habe ich versucht, die Betriebssystemplatte eines Proxmox-Nodes zu klonen und den Node nach einiger Zeit sowie Änderungen im Cluster herunterzufahren. Nach dem Einspielen des geklonten Images habe ich den Node wieder gestartet und erfreut festgestellt, dass der Node automatisch die aktuellen Konfigurationen und Änderungen, die nach dem Backup vorgenommen wurden, vom Cluster synchronisierte und ohne Probleme weiterlief.
Dieses erfolgreiche Experiment hat mich dazu veranlasst, die Idee weiter zu verfolgen. Da der Test im Cluster grundsätzlich gut funktioniert hat, läuft ein Skript dafür nun auch in meinem Hauptcluster.
Automatisiertes Backup der OS-Disk mit dd
Da ich in meinem 3-Node-Proxmox-Cluster ein NFS-Share eingebunden habe, habe ich ein Skript geschrieben, das regelmäßig ein Image-Backup der OS-Disk mittels dd
erstellt. Das Skript speichert die Backups auf dem NFS-Share und überprüft, ob das Backup erfolgreich war. Benachrichtigungen über den Backup-Status werden mir per Telegram gesendet.
Hier ist das Skript, das ich verwende:
#!/bin/bash
# Telegram Notification Setup
BOT_TOKEN="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
CHAT_ID="XXXXXXXXX"
hostname=$(hostname)
SUCCESS_MESSAGE="Backup auf ${hostname} wurde erfolgreich erstellt!"
ERROR_MESSAGE="Fehler beim Erstellen des Backups auf ${hostname}!"
send_message() {
local message="$1"
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-H "Content-Type: application/json" \
-d "{\"chat_id\": \"${CHAT_ID}\", \"text\": \"${message}\"}" | grep -q '"ok":true'
}
# Parameter
DISK=$1 # Die zu kopierende Festplatte (z.B. /dev/sda, /dev/nvme0n1)
TARGET_DIR=$2 # Zielverzeichnis für die Backups
MAX_VERSIONS=$3 # Maximale Anzahl der zu speichernden Versionen
# Check if parameters are provided
if [ -z "$DISK" ] || [ -z "$TARGET_DIR" ] || [ -z "$MAX_VERSIONS" ]; then
echo "Usage: $0 <disk> <target_directory> <max_versions>"
exit 1
fi
# Define the filename with the hostname and timestamp
timestamp=$(date +"%Y%m%d_%H%M%S")
backup_file="${TARGET_DIR}/${hostname}_disk_backup_${timestamp}.img"
# Create the backup using dd
echo "Creating disk backup of $DISK at $backup_file..."
dd if="$DISK" of="$backup_file" bs=4M status=progress
# Check if the backup was successful
if [ $? -eq 0 ]; then
echo "Backup created successfully: $backup_file"
send_message "$SUCCESS_MESSAGE"
else
echo "Backup failed."
send_message "$ERROR_MESSAGE"
exit 1
fi
# Manage old backups: keep only the latest $MAX_VERSIONS
echo "Managing old backups, keeping only the latest $MAX_VERSIONS..."
backup_count=$(ls -1 ${TARGET_DIR}/${hostname}_disk_backup_*.img 2>/dev/null | wc -l)
if [ "$backup_count" -gt "$MAX_VERSIONS" ]; then
# Find and delete the oldest backups
ls -1 ${TARGET_DIR}/${hostname}_disk_backup_*.img | sort | head -n -"$MAX_VERSIONS" | while read -r old_backup; do
echo "Deleting old backup: $old_backup"
rm -f "$old_backup"
done
fi
echo "Backup process completed."
Automatisierung mit Cron
Dieses Skript führe ich mithilfe eines Cronjobs jeden Montag um 3 Uhr morgens aus. Hier ist der entsprechende Cronjob-Eintrag:
0 3 * * 1 /root/pve-os-backup.sh /dev/sdi /mnt/pve/nfs-share/pve-backup/pveX 2 >/dev/null 2>&1
/root/pve-os-backup.sh <disk> <target_directory> <max_versions>
Automatisches Löschen alter Backups
Ein wichtiger Bestandteil meines Skripts ist das automatische Löschen von alten Backups, um Speicherplatz auf dem NFS-Share zu sparen. Über einen Parameter im Skript kann definiert werden, wie viele Versionen eines Backups aufbewahrt werden sollen. Sobald diese Anzahl überschritten wird, werden die ältesten Backups automatisch gelöscht. Dadurch bleibt das Backup-Verzeichnis übersichtlich, und unnötiger Speicherverbrauch wird vermieden. Es ist besonders hilfreich in Umgebungen mit begrenztem Speicherplatz, um sicherzustellen, dass immer genügend Platz für neue Backups vorhanden ist, ohne manuell eingreifen zu müssen.
Wichtige Hinweise
Es gibt einige Dinge zu beachten. Wenn sich Daten auf der Festplatte geändert haben, bevor der Ausfall auftritt, aber nachdem das letzte Backup erstellt wurde, sind diese Daten verloren. Dies ist jedoch meistens kein Problem, da in einem Proxmox-Cluster alle relevanten Informationen zu VMs und Konfigurationen auf den anderen Nodes gespeichert sind und nach dem Restore synchronisiert werden.
Besondere Vorsicht ist bei einem Ceph-Cluster geboten. Wurden Änderungen am Ceph-Cluster oder an den OSDs vorgenommen, kann das Einspielen eines veralteten Backups problematisch werden. In solchen Fällen ist es ratsam, den Node neu zu installieren und zu konfigurieren, anstatt ein Backup einzuspielen, wenn diese Änderungen nach dem letzten Backup erfolgt sind.
Ein weiterer wichtiger Punkt ist, dass das Erstellen von regelmäßigen Backups mit dd
die Lebensdauer der OS-Festplatten der Proxmox-Nodes beeinträchtigen kann, da diese häufiger gelesen werden. Es ist daher zu erwarten, dass die OS-Disks schneller verschleißen.
Fazit
Bislang ist in meinem Proxmox-Cluster noch keine OS-Disk ausgefallen, aber es ist gut zu wissen, dass ich für den Ernstfall vorbereitet bin. Dieses Verfahren ist zwar experimentell, bietet jedoch eine Möglichkeit, im Falle eines Festplattenausfalls schnell wieder online zu gehen, ohne den gesamten Node neu aufsetzen zu müssen – im besten Fall.
Sollte der Ernstfall eintreten, werde ich natürlich ein Update veröffentlichen und berichten, ob der Restore problemlos geklappt hat oder ob ich auf unerwartete Schwierigkeiten gestoßen bin.