Im folgenden Artikel beschreibe ich, wie man OpenVZ als Virtualisierungslösung auf einem Server einsetzt. Der Server (physikalischer Server oder auch Hardware Node genannt) den ich in der Anleitung verwende, ist ein 64bit System, auf dem Debian Lenny installiert ist.

Bevor man sich an die Umsetzung macht, bitte zuerst überprüfen, ob nicht das Betriebssystem des Servers auf Proxmox umgestellt werden kann. Die Installation wird über eine ISO Datei durchgeführt und ist sehr einfach. Weiterhin hat man ein Webfrontend für die Verwaltung der virtuellen Container. Die größte Hürde bei der Proxmox Installation ist die Tatsache, dass man mit der ISO Datei booten muss, um die empfohlene Installation durchzuführen. Hat man einen Rootserver gemietet, stellt dies oft ein unlösbares Problem dar, falls der Server-Hoster dies nicht in seinem Angebot berücksichtigt. Man kann Proxmox auch auf einem bestehenden Debian installieren - der Weg ist aber steinig und wird vom Hersteller nicht supportet.

Entschließt man sich nun ohne Proxmox OpenVZ auf ein bestehendes Debian Lenny zu installieren, dann ist diese Anleitung die Richtige (vielleicht kann aber auch der eine Proxmox User einige Tipps übernehmen).

Vorbereitung des Hardware Nodes

Auf dem physikalischen Rechner müssen folgende Pakete installiert werden:

aptitude install linux-image-openvz-amd64 vzctl vzquota cstream liblockfile-simple-perl liblog-agent-perl iptables

Damit ist der Kernel mit OpenVZ Unterstützung installiert als auch die Pakete, die für vzdump benötigt werden. vzdump wird weiter unten für die Erstellung eines Backups eingesetzt. vzdump ist leider nicht im Lenny Repository, deswegen muss es manuell von der Proxmox Webseite heruntergeladen und installiert werden:

cd /tmp && wget http://download.proxmox.com/debian/dists/lenny/pve/binary-amd64/vzdump_1.2-9_all.deb
dpkg -i vzdump_1.2-9_all.deb

Nun setzen wir noch einen symbolischen Link auf /vz (darin werden sich alle virtuelle Umgebungen befinden).

ln -s /var/lib/vz /vz

Durch die Installation des OpenVZ Kernels wurde auch der Bootmanager so konfiguriert, dass dieser als Standard-Kernel verwendet wird. Anschließend den Server neu starten und mit Hilfe der folgenden Tests sicherstellen, dass OpenVZ einsatzbereit ist:

uname -r

Die Ausgabe sollte ähnlich dieser sein:

2.6.26-2-openvz-amd64

Wichtig ist hier, dass openvz mit im Namen des Kernels vorkommt. Falls dies nicht der Fall ist, ist der richtige Kernel nicht aktiviert, oder es ist ein selbstkonfigurierter Kernel.

Netzwerkkonfiguration

Es gibt zwei verschiedene Netzwerk Devices (veth und venet. Diese können je nach Bedarf eingesetzt werden. Ich gehe hier nur auf die venet Variante ein, welche in den meisten Fällen ausreicht (Vergleich veth und venet - Englisch). Ein Vorteil der venet Variante ist, dass sie sehr einfach zu konfigurieren ist. An den Netzwerkgeräten in der Datei /etc/network/interfaces muss nichts geändert werden. Mit dem OpenVZ Kernel steht ein Netwerkgerät venet0 bereit, über welches die virtuellen Umgebungen bedient werden.

Folgende Konfiguration wird in die Datei /etc/sysctl.conf eingefügt:

net.ipv4.conf.all.rp_filter=1
net.ipv4.icmp_echo_ignore_broadcasts=1
net.ipv4.conf.default.forwarding=1
net.ipv4.conf.default.proxy_arp = 0
net.ipv4.ip_forward=1
kernel.sysrq = 1
net.ipv4.conf.default.send_redirects = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.eth0.proxy_arp=1

Mit folgendem Befehl aktiviert man die Änderungen (alternativ werden die Änderungen nach dem nächsten Server Restart aktiv):

sysctl -p

Falls in den virtuellen Umgebungen ein anderes Subnetz verwendet wird als auf dem physikalischen Rechner, kann es erforderlich sein, dass die Konfigurationsdatei /etc/vz/vz.conf angepasst werden muss:

NEIGHBOUR_DEVS=detect

ersetzen mit

NEIGHBOUR_DEVS=all

Ich schreibe deswegen kann, da es mit Debian Lenny auch mit ‘detect’ funktioniert. Mit Ubuntu 8.04 LTS ist diese Anpassung notwendig gewesen.

Es gibt verschiedene Möglichkeiten, wie man die virtuellen Umgebungen ins Netzwerk einbindet. Hat man für jede virtuelle Umgebung eine oder mehrere eigene externe IP Adressen, braucht man auf dem physikalischen Server nichts weiter machen. “Braucht” ist wohl nicht ganz richtig. Falls die IP Adressen für eine virtuelle Umgebung verwendet werden sollen, dürfen diese am physikalischen Rechner nicht verwendet werden. Es darf also kein Netzwerkgerät in der /etc/network/interfaces definiert sein (auch kein Virtuelles!)

Die Ausgabe auf dem physikalischen Rechner sieht dann in etwa so aus:

eth0      Link encap:Ethernet  HWaddr 30:11:86:be:cd:bb
          inet addr:11.22.33.44  Bcast:11.22.33.44  Mask:255.255.255.192
          inet6 addr: ee80::4261:77ff:febe:cdbb/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:50570 errors:0 dropped:0 overruns:0 frame:0
          TX packets:55066 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:8861631 (8.4 MiB)  TX bytes:38502715 (36.7 MiB)
          Interrupt:249 Base address:0x4000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:156 errors:0 dropped:0 overruns:0 frame:0
          TX packets:156 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:7800 (7.6 KiB)  TX bytes:7800 (7.6 KiB)

venet0    Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1
          RX packets:47734 errors:0 dropped:0 overruns:0 frame:0
          TX packets:42725 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:36656774 (34.9 MiB)  TX bytes:7180751 (6.8 MiB)

venet0 wurde also keine IP Adresse und auch keine MAC Adresse zugeordnet - dies ist so richtig. Fehlt der Abschnitt venet0 komplett, dann ist sehr wahrscheinlich der falsche Kernel aktiv (oder ein selbstkompilierter Kernel wurde mit falscher Konfiguration übersetzt).

Hat man keine externe IP Adresse, kann man mit privaten IP Adressen arbeiten und mit Hilfe von NAT bestimmte (oder alle) Ports weiterleiten. Im folgenden Beispiel wird gezeigt wie man Port 80 an eine virtuelle Umgebung auf Port 8080 weiterleitet, welche die private IP Adresse 192.168.2.10 besitzt:

iptables -t nat -A PREROUTING -p tcp -d $ext_ip --dport 80 -j DNAT --to 192.168.2.10:8080
iptables -A FORWARD -p tcp -d 192.168.2.10 --dport 8080 -m state --state NEW -j ACCEPT

$ext_ip muss hier noch mit der IP Adresse des physikalischen Rechners ersetzt werden.

Verwendet man in einer virtuellen Umgebung eine oder mehrere private IP Adressen aus dem Bereich 192.168.2., sorgt folgende Anweisung dafür, dass die virtuelle Umgebung Zugriff auf das Netzwerk über den physikalischen Rechner bekommt:

iptables -t nat -A POSTROUTING -s 192.168.2.0/25 -o eth0 -j SNAT --to $ext_ip

Diese Anweisung kann z.B. in die Datei /etc/rc.local angehängt werden.

Verzeichnisse und Dateien zu OpenVZ

Hier ein kurzer Überblick über die Verzeichnisstruktur von OpenVZ und die wichtigsten Dateien dazu.

  • /vz Basisverzeichnis, welches viel Festplattenkapazität besitzen sollte. Eine eigene Partition sollte dafür in Betracht gezogen werden.
  • /vz/dump Hier werden die Backups der virtuellen Umgebungen abgelegt.
  • /vz/lock Lock Files zu verschiedenen Prozessen. Dieses Verzeichnis dient also nur für interne OpenVZ Prozesse oder OpenVZ Tools.
  • /vz/private Die physikalischen Verzeichnisse der einzelnen virtuellen Umgebungen. Jede virtuelle Umgebung befindet sich in einem Unterverzeichnis (Unterverzeichnis = VEID). Auf diese Verzeichnisse/Dateien kann immer zugegriffen werden, auch wenn die virtuelle Umgebung dazu nicht läuft.
  • /vz/root Die Einhängepunkte der einzelnen virtuellen Umgebungen. Ist eine virtuelle Umgebung gestartet, wird hier in einem Unterverzeichnis (Unterverzeichnis = VEID) die Verzeichnisstruktur der virtuellen Einheit zu finden sein. Sind keine virtuellen Maschinen gestartet, ist dieses Verzeichnis leer.
  • /vz/template/cache Hier liegen die Templates, die man zur Erstellung neuer virtueller Umgebungen verwenden kann.
  • /etc/vz Basisverzeichnis zur OpenVZ Konfiguration.
  • /etc/vz/vz.conf Diese Datei ist die OpenVZ Konfigurationsdatei, über die grundlegende Werte wie Pfade zu den Verzeichnissen und das Funktionsverhalten zu OpenVZ festgelegt wird.
  • /etc/vz/conf Konfigurationsvorlagen und die Konfigurationsdateien zu den einzelnen virtuellen Umgebungen. Für jede virtuelle Umgebung existert hier eine Konfigurationsdatei mit dem Dateinamen VEID.conf.
  • /etc/vz/dists Helper-Scripte für die Config-Aufgaben der verschiedenen Distributionen.
  • /etc/vz/names Hier werden Links angelegt wenn neben der ID auch ein Name für ein virtuelle Umgebung vergeben wurde.

Installation einer virtuellen Umgebung (Virtual Environments, kurz VEs)

Als virtuelle Umgebung verwende ich hier auch ein Debian Lenny. Es werden auch andere Templates auf dem OpenVZ Server angeboten, die man nach belieben verwenden kann. Wichtig ist bei der Auswahl, dass man die gleiche Architektur anwendet, die auch auf dem Hardware Node zum Einsatz kommt (also z.B. x86_64). Um das Template zu benutzen, laden wir es erst einmal in das dafür vorgesehen Verzeichnis und installieren es anschließend:

cd /vz/template/cache && wget http://download.openvz.org/contrib/template/precreated/debian-5.0-amd64-minimal.tar.gz

Nun können wir die erste virtuelle Umgebung einrichten und führen einen Testlauf aus:

vzctl create 201 --ostemplate debian-5.0-amd64-minimal
vzctl set 201 --hostname vz201 --save
vzctl set 201 --ipadd 192.168.2.101 --save
vzctl set 201 --nameserver a.b.c.d --nameserver a.b.c.e --save
vzctl set 201 --name vserver --save
vzctl start 201 # Umgebung starten

Jede virtuelle Umgebung muss eine einzigartige VEID (Virtual Environment ID) besitzen. Diese muss eine Integerzahl sein, die größer 100 ist (es wird auch eine kleinere Zahl beim Anlegen funktionieren, aber Tools wie vzdump werden dann ihren Dienst verweigern). Ich verwende für die Auswahl der VEID den letzten Zahlenblock aus der IP Adresse + 100. Das kann jeder machen wie er mag. Verwendet man jedoch immer das gleiche Schema, erleichtert es einem die Identifikation ungemein.

Die Parameter hostname, ipadd (IP Adresse) und nameserver sollten soweit selbsterklärend sein. Der Parameter name kann optional benutzt werden, um anstelle der VEID einen ansprechenderen Namen für die Verwaltung zu verwenden.

Mit dem Programm vzctl werden die virtuellen Umgebungen gesteuert und konfiguriert. Hier die komplette Ausgabe der vorhandenen Parameter:

vzctl version 3.0.24
Copyright (C) 2000-2010, Parallels, Inc.
This program may be distributed under the terms of the GNU GPL License.

Usage: vzctl [options] <command> <ctid> [parameters]
vzctl destroy | mount | umount | stop | restart | status
vzctl enter <ctid> [--exec <command> [arg ...]]
vzctl create <ctid> [--ostemplate <name>] [--config <name>]
   [--private <path>] [--root <path>] [--ipadd <addr>] | [--hostname <name>]
vzctl start <ctid> [--force] [--wait]
vzctl exec | exec2 <ctid> <command> [arg ...]
vzctl runscript <ctid> <script>
vzctl chkpnt <ctid> [--dumpfile <name>]
vzctl restore <ctid> [--dumpfile <name>]
vzctl set <ctid> [--save] [--force] [--setmode restart|ignore]
   [--ipadd <addr>] [--ipdel <addr>|all] [--hostname <name>]
   [--nameserver <addr>] [--searchdomain <name>]
   [--onboot yes|no] [--bootorder <N>]
   [--userpasswd <user>:<passwd>] [--cpuunits <N>] [--cpulimit <N>] [--cpus <N>]
   [--diskspace <soft>[:<hard>]] [--diskinodes <soft>[:<hard>]]
   [--quotatime <N>] [--quotaugidlimit <N>]
   [--noatime yes|no] [--capability <name>:on|off ...]
   [--devices b|c:major:minor|all:r|w|rw]
   [--devnodes device:r|w|rw|none]
   [--netif_add <ifname[,mac,host_ifname,host_mac,bridge]]>] [--netif_del <ifname>]
   [--applyconfig <name>] [--applyconfig_map <name>]
   [--features <name:on|off>] [--name <vename>]
   [--ioprio <N>]
   [--iptables <name>] [--disabled <yes|no>]
   [UBC parameters]
UBC parameters (N - items, P - pages, B - bytes):
Two numbers divided by colon means barrier:limit.
In case the limit is not given it is set to the same value as the barrier.
   --numproc N[:N]	--numtcpsock N[:N]	--numothersock N[:N]
   --vmguarpages P[:P]	--kmemsize B[:B]	--tcpsndbuf B[:B]
   --tcprcvbuf B[:B]	--othersockbuf B[:B]	--dgramrcvbuf B[:B]
   --oomguarpages P[:P]	--lockedpages P[:P]	--privvmpages P[:P]
   --shmpages P[:P]	--numfile N[:N]		--numflock N[:N]
   --numpty N[:N]	--numsiginfo N[:N]	--dcachesize N[:N]
   --numiptent N[:N]	--physpages P[:P]	--avnumproc N[:N]
   --swappages P[:P]

Den ersten Test führt man durch, indem man die virtuellen Umgebung “verwendet”. Unter anderen Virtualisierungen spricht man davon, dass man das System über die Konsole betritt. Dies macht man mit OpenVZ wie folgt:

vzctl enter 201

Man sollte nun einen anderen Eingabeprompt sehen. Gibt man die folgenden Befehl ein, bekommt man die Liste der Netzwerkgeräte angezeigt, die in der virtuellen Maschine automatisch anhand der zugeordneten IP Adressen erzeugt werden:

ifconfig

sollte zeigen:

root@squatlabs.net:/etc/vz# vzctl exec 55 ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:16934 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16934 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:30419628 (29.0 MiB)  TX bytes:30419628 (29.0 MiB)

venet0    Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:127.0.0.1  P-t-P:127.0.0.1  Bcast:0.0.0.0  Mask:255.255.255.255
          UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1
          RX packets:53310 errors:0 dropped:0 overruns:0 frame:0
          TX packets:59119 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:8592532 (8.1 MiB)  TX bytes:45801792 (43.6 MiB)

venet0:0  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:192.168.2.101  P-t-P:192.168.2.101  Bcast:0.0.0.0  Mask:255.255.255.255
          UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1

Hat man mehr als eine IP Adresse der virtuellen Umgebung zugeordnet, würde hier venet0:1 u.s.w. zu sehen sein.

Den Container verlässt man, indem man den Befehl “exit” verwendet. Nachdem “exit” ausgeführt wurde, befindet man sich wieder auf dem physikalischen Server.

Anwendung - mit den Containern arbeiten

Das erste was man mit einem frisch installieren Container machen sollte ist das setzen des root Kennwortes. Dafür geht man wie folgt vor:

vzctl exec 201 passwd

Man wird nun aufgefordert das neue Kennwort 2mal einzugeben.

vzctl exec

Mit exec kann man als vom physikalischen Server aus Befehle absetzen, die im Container ausgeführt werden. Man muss sich also nicht vorher im Container anmelden.

Hier ein Beispiel um den Apache in der virtuellen Umgebung 201 vom physikalischen Server aus neu zu starten:

vzctl exec 201 invoke-rc.d apache2 restart

vzctl enter

Mit enter kann man sich über die Konsole am Container System anmelden. Dafür ist also keine Netzwerkverbindung (ssh oder ähnliches) erforderlich.

vzctl enter 201

Durch diese Eingabe befindet man sich im Container. Hier kann man nun nach Herzenslust Programme installieren und die Konfiguration anpassen. Ohne dass der physikalische Server dadurch gefährdet wird (mal davon abgesehen, dass die Ressourcen entsprechend eingeschränkt wurden ;) - siehe nächster Absatz).

vzctl start

Mit start wir eine virtuelle Umgebung gestartet. Folgende Schritte werden dadurch ausgeführt:

  • Erzeugen eines Virtual Environment im Kernel
  • Mounten des Filesystems des VEs von /vz/private/VEID nach /vz/root/VEID
  • Initialisieren von Resourcenverwaltungsparametern
  • Netzwerk initialisieren
  • Starten von /sbin/init im VE

Beispiel zur Anwendung:

vzctl  start 201

wird folgende Anzeige ausgeben:

Starting VE ...
VE is mounted
Adding IP address(es): 192.168.2.101
Setting CPU units: 1000
Configure meminfo: 268288
Set hostname: vz201
File resolv.conf was modified
VE start in progress...

vzctl stop

Mit stop wir eine virtuelle Umgebung angehalten. Alternativ kann auch in der virtuellen Umgebung ein Shutdown Prozess eingeleitet werden.

Folgende Schritte werden dadurch ausgeführt:

  • Stoppen aller Prozesse im VE
  • Stoppen des Virtual Environment im Kernel
  • umount von /vz/root/VEID

Beispiel zur Anwendung:

vzctl  stop 201

wird folgende Anzeige ausgeben:

Stopping VE ...
VE was stopped
VE is unmounted

vzctl destroy

Mit destroy löscht man eine virtuelle Umgebung. Man übergibt als Parameter die VEID der zu löschenden Umgebung.

vzctl create

Mit create wird eine neue virtuelle Umgebung aus einem vorhanden Template erzeugt (das haben wir weiter oben schon verwendet). Wichtig ist, dass man vorher das passende Template im Verzeichnis /vz/template/cache bereit stellt. Es gibt mehrere Möglichkeiten um Templates bereit zu stellen:

  • man besorgt sich fertige Templates aus dem Internet: http://download.openvz.org/contrib/template/precreated/
  • man erstellt sich selbst ein Template. Eine Anleitung dazu finden man im OpenVZ Wiki unter Debian template creation und Templates
  • man erstellt von einer bestehenden virtuellen Umgebung ein Template. Dazu erstellt man eine TAR Datei im Verzeichnis /vz/template/cache mit einem aussagekräftigen Namen von dem "private" Verzeichnis der gewünschten virtuellen Umgebung. Der Dateiname der TAR Datei (ohne Endung) wird dann im vzctl create Befehl verwendet.

Ein Beispiel dazu:

cd /vz/private/201
tar --numeric-owner -zcf /vz/template/cache/debian-201-vorlage.tar.gz .

# Erzeugen einer virtuellen Umgebung mit dem neu erstellen Template
vzctl create 202 --ostemplate debian-201-vorlage
vzctl set 202 --ipadd 192.168.2.102 --save
vzctl set 202 --nameserver a.b.c.d --nameserver a.b.c.e --save
vzctl set 202 --name vserver2 --save

vzctl set

Mit set setzt man die Konfiguration der virtuellen Umgebungen. Wenn der Parameter –save verwendet wird, werden die Einstellungen permanent in der Konfigurationsdatei gespeichert. Lässt man den Parameter –save weg, wird die gesetzte Einstellung nach einem Neustart der virtuellen Umgebung nicht mehr berücksichtigt.

Hier einige Beispiel zur Anwendung:

vzctl set 201 --hostname vz201.local --save # Hostnamen für die VE 201 setzen
vzctl set 201 --onboot no --save # VE 201 nicht nach einem Neustart des physikalischen Rechners automatisch starten
vzctl set 201 --diskspace 20G --save # Festplattenquata für VE 201 auf 20 GB setzen

vzsplit

Mit diesen Programm (welches mit vzctl installiert wurde) kann man Konfigurationsdateien erzeugen, die die verfügbaren Hardware-Ressourcen auf den virtuellen Umgebungen gleichmässig verteilt. Dies ist vor allem für die Inbetriebnahme sehr hilfreich und kann als Basis für das anschliessende Feintuning verwendet werden.

vzcfgvalidate

Mit diesen Programm (welches mit vzctl installiert wurde) kann man die Werte überprüfen, die in den Konfigurationsdateien für die einzelnen virtuellen Umgebungen gesetzt sind. Das Programm liefert auch Vorschläge zur Behebung der Fehler, falls welche gefunden werden.

Beispiel:

vzcfgvalidate /etc/vz/conf/201.conf
Error: barrier should be = 0 for physpages (currently, 268288)
Error: limit should be = 9223372036854775807 for physpages (currently, 268288)

vzlist

vzlist liefert eine Liste der vorhanden oder gestarteten virtuellen Umgebungen:

vzlist # wird Parameter -a verwendet, werden auch die nicht gestarteten VEs aufgelistet

liefert die Ausgabe:

      VEID      NPROC STATUS  IP_ADDR         HOSTNAME
        201         60 running 192.168.2.101     vz201
        202         32 running 192.168.2.102     vz202

Über Parameter kann man z.B. die Spalten oder auch die Sortierreihenfolge der Ausgabe festlegen. Hier die gesamte Liste der vorhanden Parameter:

Usage: vzlist [-a] [-o name[,name...]] [-s {name|-name}] [-h <pattern>] [-N <pattern>]
		[-H] [-S] [veid [veid ...]|-1]
	vzlist -L

	--all -a	 list of all VEs
	--output -o	 output only specified parameters
	--hostname -h	 hostname search pattern
	--name -n	 display VE name
	--name_filter -N	 name search patter
	--sort -s	 sort by specified parameter, - sign before parametr
			 mean sort in reverse order
	--no-header -H	 supress display header
	--stopped -S	 list of stopped Ve
	--list -L	 list of allowed parameters

vzpid

Eines der Vorteile von OpenVZ ist, dass man auf dem physikalischen Rechner alle Prozess angezeigt bekommt, die in den virtuellen Umgebungen laufen, da ja auch der gleiche Kernel verwendet wird. Führt man auf dem physikalischen Server top aus, bekommt man also alle Prozesse des physikalischen und aller virtuellen Umgebungen angezeigt. Wie findet man nun aber heraus, in welcher virtuellen Umgebung welcher Prozess läuft? Und genau hierfür ist vzpid da. Man übergibt vzpid die Prozess ID (PID) und man bekommt dann die VEID der virtuellen Umgebung angezeigt, in der dieser Prozess läuft.

Ressourcenverwaltung

Weil alle virtuellen Umgebungen denselben Kernel nutzen, spielt die Ressourcenverwaltung eine wichtigste Rolle. Die Ressourcenverwaltung besteht aus drei Subsystemen:

  • Zwei-Ebenen-Festplattenquota Die Beschänkung des Festplattenplatzes pro virtueller Umgebung. Die erste Ebene ist die Festplattenquota auf eine virtuelle Umgebung bezogen, die zweite Ebene ist die standardmäßige UNIX-Festplattenquota pro Benutzer und pro Gruppe innerhalb der virtuellen Umgebung.
  • CPU-Planer Es ist möglich die CPU Zeit und den CPU Takt pro virtueller Umgebung zuzuweisen.
  • User Beancounters (UBC) Über die User Beancounters kann man die Ressourcen bzgl. RAM und verschiedene in-kernel-Objekte wie IPC shared memory segments kontrollieren. Die aktuell benutzten Ressourcen kann man in der Datei /proc/user_beancounters innerhalb jeden Containers einsehen. Die Einheit der Werte für die einzelnen Parameter unterscheidet sich je nach Resource:
    • Parameter deren Namen mit "num" beginnen haben die Einheit "Stück"
    • Parameter deren Namen mit "pages" enden haben die Einheit "memory pages" (4k auf IA-32 hardware)
    • die Einheit für alle anderen Parameter sind in Bytes angegeben
    Beispiel für die Ausgabe der /proc/user_beancounters mit überschrittenen Ressourcen Infos zu den einzelnen Spalten: Die Werte barrier und limit werden durch die Konfiguration der virtuellen Umgebung bestimmt. Mit dem Befehl vzctl set werden diese Werte angepasst.
    • barrier - Softlimit der Resource
    • limit - Hardlimit der Resource
    Für die Fehlerdiagnose und Monitoring sind folgende Spalten
    • held - Aktueller Verbrauchswert der Resource
    • maxheld - Maximaler Verbrauch für die Resource seit dem letzten Start (kann nur durch ein Neustarten der virtuellen Umgebung zurückgesetzt werden)
    • failcnt - Stösst eine der Ressourcen einer virtuellen Umgebung an ihr Limit wird der entsprechende failcnt der Resource erhöht (kann nur durch ein Neustarten der virtuellen Umgebung zurückgesetzt werden).
    Einfache Eselsbrücke: Wenn in der Spalte failcnt alle Werte auf 0 stehen, gibt es keine Ressourcenprobleme in der virtuellen Umgebung.

Anpassungen darf man im laufenden Betrieb machen, ohne einen Container neu starten zu müssen (mit Hilfe des Befehls vzctl set).

Die Standardvergabe der Ressourcen sind sehr restriktiv, daher ist eine Anpassung in den meisten Fällen erforderlich. Man muss bei einem neuen System die genutzten Ressourcen genau im Auge behalten, um einen fehlerfreien Betrieb der Anwendungen in den virtuellen Umgebungen zu garantieren. Idealerweise setzt man dafür einen Monitoring-Dienst wie z.B. Cacti ein. Die Cacti Erweiterung mysql-cacti-templates bringt auch OpenVZ Monitoring Templates mit, die eine Überwachung der virtuellen Umgebungen sehr komfortabel machen.

Das Bild zeigt eine Cacti Grafik mit OpenVZ Prozessen: OpenVZ Monitoring mit Cacti Kurze Info zur Verwendung mysql-cacti-templates: Für das Monitoring von OpenVZ wird hier eine SSH Verbindung benoetigt und der Benutzer benoetigt root Rechte. Will man einen Benutzer verwenden, der keine Rootrechte besitzt (was ich nur empfehlen kann), kann man diese kleine C Programm verwenden:

#include <stdio.h>
#include <stdlib.h>

#define MAX_LINE 1024

int main() {
    char line[MAX_LINE];
    FILE *file = fopen("/proc/user_beancounters", "r");
    if (file == NULL) exit(1);
    while (fgets(line, MAX_LINE, file))
            printf("%s", line);
    fclose(file);
    return 0;
}

Diesen Code speichert man in der virtuellen Umgebung unter /tmp/beanc.c und fuehrt dann folgenden Befehl aus:

cc /tmp/beanc.c -o /bin/beanc && chmod 4755 /bin/beanc

In der Datei dfdfd ersetzt man nun:

$openvz_cmd    = 'cat /proc/user_beancounters';

mit

$openvz_cmd    = 'beanc';

Wichtig ist, dass in allen virtuellen Umgebungen das Binary /bin/beanc vorhanden sein muss. Hat man mehrere virtuelle Umgebungen mit der gleiche Distribution und Architektur laufen, übertragt man die Datei in alle anderen Umgebungen.

Backup einer virtuellen Umgebung

Da alle virtuellen Umgebungen von der physikalischen Umgebung direkt angesprochen werden, bietet es sich an das Backup von der physikalischen Umgebung aus durchzuführen (aus Sicherheitsgründen und Ressourcengründen). Also kein Cronjob in der VE, um es nochmal deutlich zu schreiben. Hier einige Möglichkeiten, die man je nach Erfordernis auswählt.

Backup mit vzdump

Um ein Backup einer VE zu erstellen, verwendet man am besten das Programm vzdump.

usage: /usr/sbin/vzdump OPTIONS [--all | VMID]

	--exclude VMID		exclude VMID (assumes --all)
	--exclude-path REGEX	exclude certain files/directories
	--stdexcludes		exclude temorary files and logs

	--compress		compress dump file (gzip)
	--dumpdir DIR		store resulting files in DIR
	--maxfiles N		maximal number of backup files per VM
	--script FILENAME	execute hook script
	--storage STORAGE_ID	store resulting files to STORAGE_ID (PVE only)
	--tmpdir DIR		store temporary files in DIR

	--mailto EMAIL		send notification mail to EMAIL.
	--quiet			be quiet.
	--stop			stop/start VM if running
	--suspend		suspend/resume VM when running
	--snapshot		use LVM snapshot when running
	--size MB		LVM snapshot size

	--node CID		only run on pve cluster node CID
	--lockwait MINUTES	maximal time to wait for the global lock
	--stopwait MINUTES	maximal time to wait until a VM is stopped
	--bwlimit KBPS		limit I/O bandwidth; KBytes per second

Backup mit tar

In der Not kann man auch mit einem ganz normalen TAR Befehl ein Backup durchführen. Allerdings ist die Ausfallzeit hier am größten:

vzctl stop 201
cd /vz/private && tar cfz /vz/dump/201-$(date +%Y%m%d-%H%M).tar.gz 201/
vzctl start 201

Backup mit rsnapshot

rsnapshot lässt sich gut in Verbindung mit OpenVZ Instanzen einsetzen. Der Unterschied zu dem Backup mit TAR ist, dass man ein inkrementelles Backup verwenden kann. Dies hat den grossen Vorteil, dass das Backup sehr viel schneller (als ein volles Backup) durchgeführt wird - und die Datenmenge wesentlich geringer ist. Mit Debian Lenny setzt man folgenden Befehl ein, um rsnapshot zu installieren:

aptitude install rsnapshot

Nun muss noch die Konfigurationsdatei /etc/rsnapshot.conf angepasst werden. Mit der Konfiguration snapshot_root lege ich das Verzeichnis fest, in dem die Backups erstellt werden (hier sollte also genügend Platz vorhanden sein). Folgender Konfigurationsblock würde die kompletten virtuellen Umgebungen 201 und 202 sichern:

backup	/vz/private/201/	vz201/
backup	/vz/private/202/	vz202/

Ein Cronjob wurde schon automatisch durch das Debian Paket erstellt. Um die Datenkonsistenz sicherzustellen, am besten die virtuellen Umgebungen vor dem Backup stoppen. Falls man von einem Teil einer virtuellen Umgebung ein Backup erstellen will (wie z.B. /vz/private/201/www), kann man sich eventuell das anhalten der virtuellen Umgebungen sparen, was aber auf dem individuellen Fall ankommt. In der Regel sollte nicht mehr als ein ssh-Daemon auf dem physikalischen Server laufen. Alles andere wird besser in einer virtuellen Umgebung untergebracht.

Sicherheit / Firewall

Besondere Beachtung muss der Absicherung des physikalischen Servers zukommen, da über diesen der Zugang zu allen virtuellen Umgebungen offen ist. Wird der physikalische Server gehackt, haben in diesem Fall auch die virtuellen Umgebungen verloren!

Die Firewall muss ebenfalls immer auf der höchsten Ebene verwendet werden, die verfügbar/möglich ist. Falls bestimmte Ports schon von einem Hardware-Router geblockt werden können, dann sollten diese dort auch schon geblockt werden. Der nächste Level wäre dann auf dem physikalischen Rechner. Ich würde ich persönlich alle Firewall-Regeln auf dem physikalischen Rechner machen und der virtuellen Umgebungen nicht vertrauen (falls gehackt).

Für die Umsetzung der Sicherheits-Policy legt man sich entweder ein eigenes Skript mit iptables Anweisungen an, oder man setzt z.B. Shorewall ein.

Weiterführende Informationen

Aktualisiert: