LXC

Dieser Artikel wurde für die folgenden Ubuntu-Versionen getestet:

Dieser Artikel ist mit keiner aktuell unterstützten Ubuntu-Version getestet! Bitte hilf mit, indem du diesen Artikel testest. Wiki/FAQ - häufig gestellte Fragen (Abschnitt „Wikiartikel-testen“).

Artikel für fortgeschrittene Anwender

Dieser Artikel erfordert mehr Erfahrung im Umgang mit Linux und ist daher nur für fortgeschrittene Benutzer gedacht.

Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:

  1. Installation von Programmen

  2. Ein Terminal öffnen

  3. Einen Editor öffnen

Inhaltsverzeichnis
  1. Installation
  2. Einrichtung
  3. LXC testen
  4. Container
  5. Containerkonfiguration
    1. Netzwerk einrichten
  6. Container erstellen
    1. Container aus einer Vorlage erstellen
  7. Container starten und beenden
    1. Anwendungscontainer
    2. Systemcontainer starten
    3. Systemcontainer beenden
  8. Weitere Befehle zum Verwalten von Containe...
  9. Hinweise
  10. LXC und Hyper-V
  11. Links

LinuX Container (LXC) bieten die Möglichkeit, Prozesse und Prozessgruppen zu isolieren, indem Kernel-Ressourcen virtualisiert und gegeneinander abgeschottet werden. Dies wird mit Hilfe der im Kernel enthaltenen Cgroups realisiert. Mit LXC kann man entweder einzelne Anwendungen oder ganze Linux-Distributionen in einem Container starten. Ähnliche Konzepte gibt es bei Linux-VServer oder Jails (FreeBSD) oder Zones (Solaris).

Es gibt zwei Werkzeugsammlungen zum Verwalten von Linux-Containern. Zum einen gibt es einen LXC-Treiber für libvirt 🇬🇧, das man zum Beispiel über virsh bedient. Zum anderen gibt es das Projekt LXC 🇬🇧, das in diesem Artikel beschrieben wird. Während libvirt darauf ausgelegt ist, unterschiedliche Virtualisierungslösungen zu verwalten, beschränkt sich LXC nur auf Linux-Container, bietet für diese aber eine größere und flexiblere Werkzeugsammlung.

Installation

Der Kernel von Ubuntu enthält ab Version 2.6.31 (Ubuntu 9.10) bereits alle Voraussetzungen zum Betreiben von LXC. Es müssen nur noch die Programme zur Verwaltung von Containern installiert werden:

Paketliste zum Kopieren:

sudo apt-get install lxc 

Oder mit apturl die Pakete installieren. Link: apt://lxc

Wer ein komplettes System mittels LXC virtualisieren möchte, der benötigt zusätzlich:

Paketliste zum Kopieren:

sudo apt-get install debootstrap bridge-utils 

Oder mit apturl die Pakete installieren. Link: apt://debootstrap,bridge-utils

Einrichtung

Zunächst muss das cgroup-Dateisystem eingehängt werden:

sudo mount cgroup -t cgroup /sys/fs/cgroup 

Damit das beim Starten von Ubuntu automatisch und dauerhaft geschieht, kann man das auch über die /etc/fstab machen:

cgroup /sys/fs/cgroup cgroup defaults 0 0

LXC testen

Man kann jetzt bereits LXC ausprobieren, indem man in einem Terminal [2] folgenden Befehl eingibt:

sudo lxc-execute -n CONTAINERNAME /bin/bash 

Durch diesen Befehl startet man die Bash in einem Container namens CONTAINERNAME. Der Name kann frei gewählt werden, muss aber einmalig sein.

Lässt man sich jetzt die Prozessliste anzeigen,

ps -e 

kann man nur die Prozesse des Containers sehen:

  PID TTY          TIME CMD
    1 pts/8    00:00:00 lxc-init
    2 pts/8    00:00:00 bash
   86 pts/8    00:00:00 ps

Container

Linux-Container bestehen im Allgemeinen aus drei Teilen:

Soll nur eine einzelne Anwendung in einem Container ausgeführt werden, spricht man von einem Anwendungscontainer. LXC testen ist der einfachste Fall eines solchen Anwendungscontainers. Bei Anwendungscontainern sollte man sich genau überlegen, welche Ressourcen man isolieren will. Man kann zum Beispiel den Rechnernamen (hostname) ändern und das Netzwerk isolieren. Um Konflikte zwischen Dateien zu vermeiden, kann man Teile des Dateisystem neu einhängen, oder man erstellt ein eigenes Root-Dateisystem und kann Teile des Haupt-Dateisystems über Bind-Mounts gemeinsam nutzen. Wenn keine Konfiguration angegeben wird, werden nur Prozessnummern, System V IPC und Einhängepunkte virtualisiert und isoliert.

Wird ein vollständiges System in einem Container eingerichtet, spricht man von einem Systemcontainer. Die Konfiguration eines Systemcontainers ist einfacher, da man sich keine Gedanken über die isolierten Ressourcen machen muss, weil alles isoliert werden muss.

Containerkonfiguration

Jede Zeile in einer Konfigurationsdatei steht für eine Einstellung und hat die Form name = wert:

Containerkonfiguration
Einstellung Beschreibung
lxc.utsname Der Rechnername des Containers
lxc.tty Anzahl der ttys des Containers
lxc.pts Wenn diese Einstellung vorhanden ist, hat der Container eigene Pseudo-TTYs. Der Wert 1024 beschreibt die Maximalanzahl; diese Beschränkung ist aber noch nicht implementiert.
lxc.mount Eine Datei, die die Einhängepunkte des Containers enthält und aufgebaut ist wie die fstab
lxc.mount.entry Einzelner Einhängepunkt im Format einer fstab-Zeile.
lxc.rootfs Das Verzeichnis, in dem sich das Root-Dateisystem des Containers befindet
lxc.network.type Art der Netzwerkvirtualisierung, mögliche Werte sind: empty, veth, vlan, macvlan, phys
lxc.network.flags Wenn hier up angegeben wird, wird das Netzwerkinterface aktiviert
lxc.network.link Das vom Container verwendete Netzwerkinterface
lxc.aa_profile Container werden von AppArmor abgesichert. Man kann hier ein eigenes Profil angeben oder mit unconfined das Standardprofil abschalten.

Weitere Einstellungen und Hinweise findet man in der Manpage zu lxc.conf und in den Beispielen unter /usr/share/doc/lxc/examples/.

Netzwerk einrichten

Die Einrichtung einer Netzwerkbrücke scheint zur Zeit die beste Möglichkeit zu sein, einen Container mit dem Netzwerk zu verbinden. Das Interface br0 muss außerhalb des Containers konfiguriert werden. Wenn man WLAN verwendet, funktioniert eine Netzwerkbrücke nicht. Dann kann man libvirt verwenden, um eine Route 🇬🇧 zu erstellen.

Container erstellen

Einen Container erstellt man mit:

sudo lxc-create -n Containername -f Konfigurationsdatei 

Der Befehl erzeugt im Verzeichnis /var/lib/lxc ein Unterverzeichnis Containername, in dem die Konfigurationsinformationen gespeichert werden.

Einen Container entfernen kann man mit:

sudo lxc-destroy -n Containername 

Um eine Containerkonfiguration zu ändern, kann man die Konfigurationsdatei im Containerverzeichnis direkt bearbeiten oder man löscht mit lxc-destroy den Container und erstellt ihn dann wieder neu mit lxc-create.

Es ist nicht unbedingt erforderlich, Container vor der Benutzung zur Erstellen. Man kann auch beim Starten des Containers die Konfiguration als Parameter übergeben.

Container aus einer Vorlage erstellen

Eine Möglichkeit einen Container zu erstellen ist, eine vorhandene Vorlage zu verwenden:

sudo lxc-create -n Containername -f Konfiguration -t Vorlagenname 

Dabei können weitere Optionen übergeben werden:

sudo lxc-create -n Containername -f Konfiguration -t Vorlagenname -- Vorlagenoptionen 

Man kann sich die Vorlagenoptionen mit folgendem Befehl anzeigen lassen:

lxc-create -t Vorlagenname -h 

Es stehen folgende Vorlagen zur Verfügung:

LXC-Vorlagen
Vorlage Beschreibung
ubuntu über die Vorlagenoption „-r RELEASE“ kann die Ubuntuversion des Gastsystem angegeben werden. Standard ist die Version des Host-Systems.
ubuntu-cloud erzeugt einen Ubuntu-Cloud-Container
debian Debian GNU/Linux 6.0 (Squeeze), ca. 236 MB. Über die Umgebungsvariable SUITE kann eine andere Debian-Version ausgewählt werden.
fedora benötigt die Pakete curl und yum, kann nicht mit systemd umgehen und kann deshalb nur Fedora-Container bis einschließlich Version 14 erzeugen
opensuse benötigt das Programm zypper, für das es allerdings noch kein Ubuntu-Paket gibt
busybox sehr kleiner Systemcontainer, der vollständig auf busybox basiert, nur zu experimentellen Zwecken
sshd Anwendungscontainer zum Betreiben von sshd, nur zu experimentellen Zwecken

Die Vorlagen-Skripte finden sich im Verzeichnis /usr/lib/lxc/templates. Man kann sie als Vorlage für eigene Skripte verwenden. Das Root-Dateisystem dieser Container wird zusammen mit der Konfiguration unter /var/lib/lxc/Containername gespeichert und beim Verwenden des Befehls lxc-destroy samt aller darin vorgenommenen Veränderungen gelöscht.

Die Vorlagen-Skripte lassen sich auch direkt aufrufen:

sudo /usr/lib/lxc/templates/lxc-Vorlagenname -n CONTAINERNAME -p /Pfad/zum/Root-Dateisystem 

Auf diese Weise ist es möglich, das Root-Dateisystem an einem anderen Ort zu speichern.

Minimalbeispiel einer Konfigurationsdatei für Vorlagen:

lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br-lxc

Die Konfigurationsdatei wird durch die Vorlagen-Skripte um weitere Einträge erweitert.

Die Vorlagen für Ubuntu- und Debian-Systeme

Die Vorlagen "ubuntu", "lucid", "debian" und "lenny" erstellen ein Root-Dateisystem unter /var/lib/lxc/CONTAINERNAME. Beim ersten Aufruf wird das mittels debootstrap von den Ubuntu- oder Debian-Servern heruntergeladen und unter /var/cache/lxc/ zwischengespeichert. Werden weitere Container mit derselben Vorlage erstellt, wird durch das Wiederverwenden dieses Caches die Erstellung enorm beschleunigt.

Wenn das Kommando beendet ist, erhält man den Hinweis, das Root-Passwort zu ändern. Das kann man machen, indem man mit chroot das Root-Dateisystem des erstellten Containers betritt:

chroot /var/lib/lxc/CONTAINERNAME/rootfs /bin/bash 

und dort das Passwort mit

passwd root 

ändert. Die Chroot-Umgebung verlässt man mit

exit 

Wenn man eine lokale Paketquelle wie apt-cacher-ng einsetzt, kann man beim Erstellen von Containern über Vorlagen den Download minimieren, indem man die Umgebungsvariable MIRROR setzt, z.B.:

sudo MIRROR=http://localhost:3142/de.archive.ubuntu.com/ubuntu/ lxc-create -n lucid -t lucid 

Man kann diese Umgebungsvariable auch in der Datei /etc/default/lxc festlegen.

Container starten und beenden

Anwendungscontainer

Eine Anwendung in einem Container startet man mit:

sudo lxc-execute -n CONTAINERNAME Befehl 

Wenn der Container nicht mit lxc-create erstellt wurde, muss man zusätzlich noch die Option -f Konfiguration angeben. Wird das Programm beendet, wird auch automatisch der Container beendet.

Hinweis:

Konfigurationen mit der Einstellung lxc.rootfs sind nicht für Anwendungscontainer geeignet.

Systemcontainer starten

Einen Systemcontainer startet man mit

sudo lxc-start -n Containername 

Man erhält im aktiven Terminal eine Konsole, auf der man sich anmelden kann. Diese Konsole hat eine feste Größe von 80×24, unabhängig von der tatsächlichen Größe des Terminals und ist daher zum interaktiven Arbeiten nur bedingt geeignet. Die mit lxc-console geöffneten Konsolen haben diese Einschränkung nicht.

Alternativ kann man den Container auch als Dämon starten:

sudo lxc-start -n CONTAINERNAME -d 

In diesem Fall kann man sich anmelden mit dem Befehl:

sudo lxc-console -n CONTAINERNAME 

(die Einstellung lxc.tty ist dafür in der Konfiguration erforderlich). Die LXC-Konsole beenden kann man mit den Tasten Strg + A Q . Dabei bleibt man angemeldet und kann durch einen erneuten Aufruf von lxc-console die Sitzung fortführen.

Eine andere Möglichkeit zur Anmeldung am Gastsystem ist über SSH.

Systemcontainer beenden

Ein Systemcontainer sollte wie ein normales Betriebssystem heruntergefahren werden, indem man z.B. innerhalb des Gastsystems den Befehl (bei Ubuntu sudo voranstellen):

shutdown -h now 

oder

halt 

ausführt.

Sollte das aus irgendeinem Grund nicht möglich sein, kann man den Container mit

sudo lxc-stop -n Containername 

beenden.

Hinweis:

Bevor das Hauptsystem heruntergefahren wird, sollten zuerst alle Container beendet werden. LXC macht das nicht selbständig. Für die Gastsysteme wäre das genauso, als wenn man einfach den Netzstecker ziehen würde.

Weitere Befehle zum Verwalten von Containern

Containerverwaltung
Befehl Beschreibung
lxc-kill -n CONTAINERNAME SIGNUM Das Signal SIGNUM wird an den ersten Benutzerprozess im Container gesendet
lxc-monitor -n CONTAINERNAME Der Zustand von Containern wird beobachtet. CONTAINERNAME kann auch ein regulärer Ausdruck sein, so dass mehrere oder alle Container beobachtet werden können.
lxc-wait -n CONTAINERNAME -s ZUSTAND Dieser Befehl wartet, bis der Container einen angegebenen Zustand angenommen hat. Dieser Befehl ist für Skripte nützlich.
ZUSTAND Mögliche Zustände sind STOPPED, STARTING, RUNNING, ABORTING und STOPPING. Zustände können auch kombiniert werden (z.B. RUNNING|STOPPED)
lxc-cgroup -n CONTAINERNAME SUBSYSTEM [WERT] Eigenschaften des Containers können zur Laufzeit ausgelesen (ohne WERT) oder geändert (mit WERT) werden.
lxc-ls Anzeigen aller Container. Es stehen die gleichen Optionen wie für ls zu Verfügung, zum Beispiel:
-l Informationen in Langform ausgeben
-1 Pro Zeile wird nur ein Container angezeigt.
lxc-ps [Optionen] Prozessinformationen anzeigen. Optionen sind:
--name CONTAINERNAME Es werden die Prozesse von Containern angezeigt. NAME ist dabei eine durch Kommas getrennte Liste von Containern.
--lxc Anzeige der Prozesse aller Container
PS-OPTIONEN Die restlichen Optionen werden an den Befehl ps weitergereicht.
lxc-info -n CONTAINERNAME Es wird der Zustand des Containers angezeigt.
lxc-freeze -n CONTAINERNAME Alle Prozesse innerhalb eines Containers werden angehalten.
lxc-unfreeze -n CONTAINERNAME Die mit lxc-freeze angehaltenen Prozesse eines Containers werden fortgesetzt.
lxc-checkconfig Überprüft, ob der Kernel LXC unterstützt (nur für ältere oder selbst erstellte Kernel notwendig)
CONFIG=/path/to/config lxc-checkconfig Überprüft, ob die Kernelkonfigurationsdatei /path/to/config LXC unterstützt.

Weitere Informationen liefern die Manpages der einzelnen Befehle.

Hinweise

LXC hat noch einige Einschränkungen im Vergleich mit anderen vergleichbaren Lösungen:

Ein großer Vorteil von LXC ist die Integration in den Kernel. Durch die starke Modularisierung ist LXC auch sehr gut zur Anwendungsvirtualisierung geeignet.

LXC und Hyper-V

Wird LXC in einem Hyper-V virtualisierten System eingesetzt, kann es zu Problemen bei der Verwendung einer Netzwerkbrücke kommen. Konkret kann es passieren, dass sich die virtuelle NIC nicht in den promiscous-Modus umschalten lässt (https://support.microsoft.com/kb/302348 🇩🇪).