Virtuelle Maschine Umzug libvirt zu Proxmox

Heute beschreib ich mal die von mir bevorzugte Methode, einen Server von A nach B um zuziehen. Im speziellen handelt es sich um meinen veralteten Webserver (PHP4!), der als virtuelle Maschine derzeit auf einem eigenen Server von mir unter libvirt läuft und zu meinem neuen root-Server bei OVH (Proxmox VM) umziehen soll.

Später sollen dann nach und nach die Webseiten auf eine neuen VM umziehen.

Übersicht

  • Vorbereitungen
  • Kopieren der VM zum neuen Server (Snapshot)
  • Anpassen der VM an die geänderten Netzwerkeinstellungen
  • Vorbereiten der alten VM zum Dienstweiterleiten

Nachtarbeiten:

  • Beenden aller Dienste auf beiden VM
  • Datenabgleich mit rsync
  • Dienstweiterleitung aktivieren
  • Test

Im Detail:

Vorbereitungen

Wenn man kann sollte man bei alle DNS Einträgen die TTL heruntersetzen, von z.B. 86400 (24h) auf 1800 (30min). Wenn man das am Vortag erledigt, hält sich die Serverlast in Grenzen und man kann spätere Änderungen schnell durchführen.

Bei MyDNS reicht dazu übrigends ein SQL Kommando wie dieses:

update `dns_soa` set serial=NEUESERIAL, ttl=1800;
update `dns_rr` set ttl=1800;

Verwendet man BIND als ns1, muss man sich für ein Massenupdate was einfallen lassen, Beispiel:

ttl_update.sh (abgelegt in /etc/bind/)

#!/bin/bash
     for zone in db.*; do
     cp $zone $zone.old
     sed 's/$TTL 8H/$TTL 1H/g' $zone.old > $zone.tmp.1
     sed 's/8H ; default_ttl/1H ; default_ttl/g' $zone.tmp.1 > $zone.tmp.2
     sed 's/2010012901/2011041401/g' $zone.tmp.2 > $zone
     rm -f $zone.tmp.?
     done

Ich bin kein großer Scriptmeister aber es hat funktioniert, aber natürlich nur bei (überwiegend) gleicher Serial in allen Zone-Dateien (db.*)

Kopieren der VM zum neuen Server

Hier gibt es mehrere Möglichkeiten, wenn möglich sollte man einen Snapshot der laufenden Maschine machen und diesen Snapshot zum neuen Host-Server übertragen.
Ist das nicht möglich, kann man auch die VM stoppen, alle Festplattencontainer per scp oder rsync übertragen und die VM wieder starten (natürlich in der Nacht).

Heutzutage kann jedes wichtige Virtualisierungssystem mit fast allen Containerdateien umgehen, wie Vmware vmdk, Qemu(KVM) qcow2 oder das RAW Format.

In meinem Fall wechle ich die Virtualisierungslösung von libvirt (KVM) zu Proxmox (KVM),  hier ist es nur nötig in Proxmox eine VM mit den passenden Parametern (CPU Kerne, RAM) zu erzeugen und dann die kopierten Festplattencontainer einzubinden (in diesem Fall vmdk).

Anpassen der VM

Sobald die VM läuft sind Anpassungen an die neuen Netzwerkeinstellungen zu machen, als „Netzwerkkarte“ verwende ich immer virtio, da dieser Treiber in jedem Linuxkernel mit Version >= 2.6.25 standardmäßig enthalten ist und die größte Performance verspricht.

Jetzt lasse ich einen Einzeiler laufen, der im /etc/ Verzeichnis alle Dateien nach der alten IP durchsucht und mit der neuen ersetzt.

find /etc -type f -exec sed -i 's/1.2.3.4/2.3.4.5/g' {} \;

Damit sind auch MySQL Server und Apache wieder einsatzbereit, dazu noch die Host-Datei und alle weiteren Dienste die z.B. nur auf einer IP lauschen.

Nicht zu vergessen sind noch eventuell geänderte Daten in der Datei /etc/resolv.conf für die Namensauflösung.

Vorbereiten der alten VM zum Dienstweiterleiten

Hier verwende ich das ausgezeichnete Programm rinetd.
rinetd ist ein hochperformanter Einzelprozess-Server, der Anfragen auf der einen Seite annimmt und zur Ziel-IP und den Ziel-Port weiterleitet.

Installieren der nötigen Pakete

apt-get install rinetd rsync

Die Konfigurationsdatei von rinetd ist simpel aufgebaut, ein Beispiel für einen Webserver:

QUELL-IP QUELL-PORT ZIEL-IP ZIEL-PORT
1.2.3.4 80 5.6.7.8 80
1.2.3.4 443 5.6.7.8 443
1.2.3.4 3306 5.6.7.8 3306

# logging information
#logfile /var/log/rinetd.log

Für einen Webserver wären die Ports 80,443 interessant, ev. noch 3306 für MySQL. Logging sollte man vorerst abschalten, will man nämlich aus Versehen einen Port weiterleiten, der durch ein anderes laufendes Programm belegt ist, werden durch einen kleinen Bug Unmengen an Log Einträgen geschrieben (so schnell die Platte schreiben kann).

Damit später kein Dienst außer rinetd mehr gestartet wird, passe ich die Grub Konfiguration an.

nano /boot/grub/menu.lst

Einfach an die „kopt“ Zeile „single“ anfügen, als Beispiel:

# kopt=root=/dev/sda1 ro single

Grub updaten

update-grub

Damit wird das System in den Einzeluser Modus geladen,  Runlevel 1.
Sollte das System gewollt oder ungewollt neu gestartet werden, werden keine Dienste geladen und das System bleibt mit dem Rescue-Prompt stehen.

Alle Vorbereitungsarbeiten sind nun erledigt, die folgenden Schritte werden in der Nacht erledigt

Beenden aller Dienste auf beiden VM

Die Quell und ZielVM in den Single Mode bringen, Achtung auf beiden Servern ist dann SSH nicht mehr verfügbar, also Sicherstellen das ein KVM Zugriff möglich ist!

Auf beiden Maschinen (per Remote Console):

init 1
/etc/init.d/ssh start
/etc/init.d/rsync start

Einen letzten Abgleich mit rsync Quelle -> Ziel, in diesem Beispiel die Virtuellen Hosts und die MySQL Datenbank, Eingabe am Quellserver:

rsync -avz --del /virtual/ 5.6.7.8:/virtual/
rsync -avz --del /var/ 5.6.7.8:/var/cat/etc

Dies sollte in wenigen Minuten erledigt sein, jetzt auf dem neuen Server

init 2

Alle Dienste laufen wieder, auf Fehlermeldungen achten!
Auf dem alten Server soll rinetd nun auch im Runlevel 1 gestartet und rinetd aktiviert werden

/etc/init.d/rinetd start

Ist alles gut gegangen, werden nun alle Anfragen an den alten Server an den neuen weitergeleitet. Der Nutzer merkt davon nichts!

Nacharbeiten

Jetzt können alle DNS Einträge auf die neue Server IP umgestellt werden und nach ein par Tagen sollte eine Log-Kontrolle von rinetd keine oder nur mehr vereinzelte Einträge zeigen. Man kann auch anhand der Quell IP herausfinden, wer/warum die neue IP noch nicht verwendet (wird).

Testen

  • Mehrere Webseiten mit MySQL Datenbanken
  • E-Mail Formulare
  • FTP/SSH
  • DNS Auflösung wenn Änderungen vorgenommen wurden
  • Sonstige Dienste

Schreibe einen Kommentar