[[Vorlage(Archiviert)]] [[Vorlage(Fortgeschritten)]] {{{#!vorlage Wissen [:Pakete_installieren:Installation von Programmen] [:Terminal:Ein Terminal öffnen] [:Editor:Einen Editor öffnen] }}} [[Inhaltsverzeichnis(2)]] '''L'''inu'''X''' '''C'''ontainer (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 [wikipedia_en: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 [https://libvirt.org/ libvirt] {en}, das man zum Beispiel über [:virsh:] bedient. Zum anderen gibt es das Projekt [http://lxc.sourceforge.net/ LXC] {en}, 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: {{{#!vorlage Paketinstallation lxc, universe }}} Wer ein komplettes System mittels LXC virtualisieren möchte, der benötigt zusätzlich: {{{#!vorlage Paketinstallation debootstrap, Ubuntu/Debian-System erzeugen bridge-utils, Programme für die Nutzung von Ethernet Bridge }}} = Einrichtung = Zunächst muss das cgroup-Dateisystem eingehängt werden: {{{#!vorlage Befehl sudo mount cgroup -t cgroup /sys/fs/cgroup }}} Damit das beim Starten von Ubuntu automatisch und dauerhaft geschieht, kann man das auch über die [:fstab:/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: {{{#!vorlage Befehl 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 [:Shell/ps:Prozessliste] anzeigen, {{{#!vorlage Befehl 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: * Eine Konfigurationsdatei mit Informationen über die verwendeten Ressourcen * Eine Datei im [:fstab:]-Format, welche die Einhängepunkte für den Container enthält. Diese Informationen kann man alternativ auch direkt in der Konfigurationsdatei angeben. * Das Root-Dateisystem des Containers, falls der Container eins benötigt Soll nur eine einzelne Anwendung in einem Container ausgeführt werden, spricht man von einem Anwendungscontainer. [#LXC-testen 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`: {{{#!vorlage Tabelle <-2 rowclass="titel">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 [:man: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 [https://berrange.com/posts/2009/12/13/routed-subnets-without-nat-for-libvirt-managed-virtual-machines-in-fedora/ Route] {en} zu erstellen. = Container erstellen = Einen Container erstellt man mit: {{{#!vorlage Befehl 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: {{{#!vorlage Befehl 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: {{{#!vorlage Befehl sudo lxc-create -n Containername -f Konfiguration -t Vorlagenname }}} Dabei können weitere Optionen übergeben werden: {{{#!vorlage Befehl sudo lxc-create -n Containername -f Konfiguration -t Vorlagenname -- Vorlagenoptionen }}} Man kann sich die Vorlagenoptionen mit folgendem Befehl anzeigen lassen: {{{#!vorlage Befehl lxc-create -t Vorlagenname -h }}} Es stehen folgende Vorlagen zur Verfügung: {{{#!vorlage Tabelle <-2 rowclass="titel">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: {{{#!vorlage Befehl 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: {{{#!vorlage Befehl chroot /var/lib/lxc/CONTAINERNAME/rootfs /bin/bash }}} und dort das Passwort mit {{{#!vorlage Befehl passwd root }}} ändert. Die Chroot-Umgebung verlässt man mit {{{#!vorlage Befehl exit }}} Wenn man eine [:Lokale_Paketquellen:lokale Paketquelle] wie [:Lokale_Paketquellen/Apt-Cacher-ng:apt-cacher-ng] einsetzt, kann man beim Erstellen von Containern über Vorlagen den Download minimieren, indem man die Umgebungsvariable `MIRROR` setzt, z.B.: {{{#!vorlage Befehl 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: {{{#!vorlage Befehl 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. {{{#!vorlage Hinweis Konfigurationen mit der Einstellung `lxc.rootfs` sind nicht für Anwendungscontainer geeignet. }}} == Systemcontainer starten == Einen Systemcontainer startet man mit {{{#!vorlage Befehl 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: {{{#!vorlage Befehl sudo lxc-start -n CONTAINERNAME -d }}} In diesem Fall kann man sich anmelden mit dem Befehl: {{{#!vorlage 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 [[Vorlage(Tasten, Strg+a)]] [[Vorlage(Tasten, 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 [:Herunterfahren:heruntergefahren] werden, indem man z.B. innerhalb des Gastsystems den Befehl (bei Ubuntu `sudo` voranstellen): {{{#!vorlage Befehl shutdown -h now }}} oder {{{#!vorlage Befehl halt }}} ausführt. Sollte das aus irgendeinem Grund nicht möglich sein, kann man den Container mit {{{#!vorlage Befehl sudo lxc-stop -n Containername }}} beenden. {{{#!vorlage 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 = {{{#!vorlage Tabelle <-3 rowclass="titel">Containerverwaltung +++ Befehl <-2>Beschreibung +++ `lxc-kill -n CONTAINERNAME SIGNUM` <-2>Das Signal `SIGNUM` wird an den ersten Benutzerprozess im Container gesendet +++ `lxc-monitor -n CONTAINERNAME` <-2>Der Zustand von Containern wird beobachtet. `CONTAINERNAME` kann auch ein regulärer Ausdruck sein, so dass mehrere oder alle Container beobachtet werden können. +++ <|2>`lxc-wait -n CONTAINERNAME -s ZUSTAND` <-2>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]` <-2>Eigenschaften des Containers können zur Laufzeit ausgelesen (ohne `WERT`) oder geändert (mit `WERT`) werden. +++ <|3>`lxc-ls` <-2>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. +++ <|4>`lxc-ps [Optionen]` <-2>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 [:Shell/ps:ps] weitergereicht. +++ `lxc-info -n CONTAINERNAME` <-2>Es wird der Zustand des Containers angezeigt. +++ `lxc-freeze -n CONTAINERNAME` <-2>Alle Prozesse innerhalb eines Containers werden angehalten. +++ `lxc-unfreeze -n CONTAINERNAME` <-2>Die mit `lxc-freeze` angehaltenen Prozesse eines Containers werden fortgesetzt. +++ `lxc-checkconfig` <-2>Überprüft, ob der Kernel LXC unterstützt (nur für ältere oder selbst erstellte Kernel notwendig) +++ `CONFIG=/path/to/config lxc-checkconfig` <-2>Überprüft, ob die Kernelkonfigurationsdatei '''/path/to/config''' LXC unterstützt. }}} Weitere Informationen liefern die [:man:Manpages] der einzelnen Befehle. = Hinweise = LXC hat noch einige Einschränkungen im Vergleich mit anderen vergleichbaren Lösungen: * Nicht alle Resourcen können vollständig isoliert werden. Das '''/proc/'''-Dateisystem des Host-Systems zum Beispiel muss in einem Container eingebunden werden. Das kann ein Sicherheitsproblem darstellen, denn dadurch können Programme, die im Container mit Root-Rechten ausgeführt werden, das Host-System beeinflussen. Deshalb sollten nicht vertrauenswürdige Benutzer oder Programme in einem Container niemals Root-Rechte erhalten. Seit [:Precise_Pangolin:Ubuntu 12.04] wird ein Container zwar durch [:AppArmor:] geschützt, aber das Ziel ist dabei, das Host-System vor versehentlichem Schaden durch den Container zu schützen und nicht vor bösartigen Aktionen. * LXC enthält noch keine Möglichkeit zur Live-Migration. Der dazu nötige Befehl `lxc-checkpoint` ist zwar schon vorhanden, aber noch nicht funktionsfähig. * [:systemd:] funktioniert nicht in einem Container. * Es ist zwar möglich, einem Container eine eigene IP-Adresse zuzuweisen, aber es ist nicht möglich zu verhindern, dass eine Anwendung im Container diese dann ändert. * Es fehlen verschiedene Einstellungsmöglichkeiten, wie das Festlegen eines garantierten Speichers oder einer maximalen Prozessanzahl. 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] {de}). = Links = * [https://www.stgraber.org/2013/12/20/lxc-1-0-blog-post-series/ LXC 1.0: Blog post series] {en} - Stéphane Graber, 12/2013 ff. * [https://www.stgraber.org/2016/03/11/lxd-2-0-blog-post-series-012/ LXD 2.0: Blog post series] {en} - Stéphane Graber, 03/2016 ff. * [https://blog.simos.info/trying-out-lxd-containers-on-our-ubuntu/ Trying out LXD containers on our Ubuntu] {en} - Blogbeitrag, 06/2016 * [https://en.opensuse.org/LXC Gute Anleitung für openSUSE] {en} #tag: Emulation und Virtualisierung, System