Mich interessiert das Thema rund um die Container Virtualisierung LXC seitdem ich durch Zufall über einen Vortrag von Thomas Krenn auf youtube gestolpert bin. Da hab ich mich immer mal ein bisschen zu informiert, aber hab irgendwie nie so wirklich mal selbst rumprobiert. Nach einem Beitrag über LXC in der iX 2/2014 juckte es mir dann doch gewaltig in den Fingern. Nochmal zur Erklärung was LXC überhaupt ist, für die die es nicht wissen:
LXC (LinuX Containers) ist ein leichtgewichtige Alternative zur Virtualisierung mit Hypervisoren. Besonders eignet es sich, wenn sehr viele Linux-Gäste auf einem Host laufen sollen oder für die Isolierung einzelner Anwendendungen auf einem Host. Sie erlauben eine bessere Ressourcenauslastung bei nahezu nativer Performance der Container. Außerdem sind sie wesentlich schlanker als ihre Hypervisor-Pendants. Gastssysteme werden als einfache Unterverzeichnisse realisiert, aus denen der Host jeweils eine isolierte chroot-Umgebung startet. Der Boot Zyklus eines Containers startet dabei erst beim Aufruf von /sbin/init. Alle unterhalb dieses Punktes existierenden Ressourcen wie der Kernel, teilen sich alle Container, weshalb es auch nicht möglich ist andere Betriebssysteme wie Windows als LXC-Gast zu starten.
Ich werde heute erstmal die Installation von LXC 1.0.0-rc3 auf Debian Wheezy und die erste Benutzung niederschreiben. Es gibt zwar schon eine gute Anzahl von Anleitungen, überwiegend für Ubuntu – aber das war mir zu leicht mit ppa und so. Die Anleitungen für Debian waren irgendwie größten Teils nicht vollständig oder für ältere Versionen von LXC. Deshalb habe ich mal alles mitgeschrieben, was ich so gemacht habe und im Anschluss ist es mir auch gelungen innerhalb von 15 min das ganze lauffähig zu bekommen
Vorbereiten des Hosts
Installieren von Paketen die LXC benötigt, wobei bridge-utils optional ist, je nachdem für welche Netzwerkkonfiguration man sich entscheidet
apt-get install debootstrap bridge-utils
Als nächstes muss man das cgroup Dateisystem automatisch einhängen lassen. Dazu muss die /etc/fstab um folgende Zeile ergänzt werden
cgroup /sys/fs/cgroup cgroup defaults 0 0
Um den Memory cgroup support (CONFIG_CGROUP_MEM_RES_CTLR) und Swap cgroup support (CONFIG_CGROUP_MEM_RES_CTLR_SWAP) zu aktivieren, welcher zwar seit Kernel 2.6.39-bpo60-2 integriert ist, aber per default deaktiviert ist, muss man folgendes in der /etc/default/grub ändern, bzw. ergänzen
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
Anschließend den grub updaten
update-grub
und einen Neustart.
Kompilieren
Als erstes mal git installieren
apt-get install git
und anschließend die Sourcen runterladen
git clone git://github.com/lxc/lxc
Noch ein paar Pakete zum kompilieren installieren
apt-get install build-essential automake pkg-config
Nun die autogen.sh im Ordner lxc ausführen, welche die configure Datei generiert
cd lxc/
./autogen.sh
Nochmal ein bzw. zwei zusätzliche Paket installieren, denn das Paket docbook2x wird nur benötigt falls ihr bei configure die Option für Manuals mit übergebt
apt-get install libcap-dev docbook2x
Jetzt sollte configure ohne Probleme durchlaufen. Ich habe noch ein paar zusätzliche Optionen für Pfade übergeben, aber die kann man sich auch im Help von configure durchlesen
./configure --enable-doc --with-init-script=sysvinit --bindir=/usr/bin --sbindir=/usr/sbin --libdir=/usr/lib --includedir=/usr/include --datarootdir=/usr/share --sysconfdir=/etc --localstatedir=/var
- –enable-doc – Erstell manpages
- –with-init-script=sysvinit – Welche Typen von initscripts installiert werden sollen
Sollte das geklappt haben kann man den Spass nun kompilieren und installieren
make
make install
Anlegen eines ersten Containers mit Netzwerk
Sollte die Installation ohne Probleme durchgelaufen sein ist LXC installiert und es kann mit lxc-checkconfig geprüft werden ob alle Voraussetzungen erfüllt sind
lxc-checkconfig
Kernel configuration not found at /proc/config.gz; searching...
Kernel configuration found at /boot/config-3.2.0-4-amd64
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled
Multiple /dev/pts instances: enabled
--- Control groups ---
Cgroup: enabled
Cgroup clone_children flag: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled
--- Misc ---
Veth pair device: enabled
Macvlan: enabled
Vlan: enabled
File capabilities: enabled
Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig
Einen neuen Container legt man wie folgt an
lxc-create -n c1 -t debian
-n gibt dabei den Namen des Containers und -t das Template (verfügbare Templates liegen unter /usr/share/lxc/templates) an. In früheren Versionen ist das Debian Template übrigens kaputt (z.B. Version im Repository), dafür kann man dann dieses Template verwenden.
Das erste anlegen eines Containers dauert etwas, da er erstmal die Dateien herunter laden muss. Das anlegen künftiger Container geschieht in wenigen Sekunden, da die Dateien lediglich aus dem Cache in den Ordner des neuen Containers gesynct werden.
Standartmäßig wird mit diesem Befehl im Verzeichnis /var/lib/lxc ein Unterverzeichnis mit dem Containernamen erstellt, welcher die Containerkonfiguration und das rootfs enthält. In unserem Fall also /var/lib/lxc/c1. Die config Datei sollte wie folgt aussehen
# Template used to create this container: /usr/share/lxc/templates/lxc-debian
# Parameters passed to the template:
# For additional config options, please look at lxc.conf(5)
lxc.network.type = empty
lxc.rootfs = /var/lib/lxc/c1/rootfs
# Common configuration
lxc.include = /usr/share/lxc/config/debian.common.conf
# Container specific configuration
lxc.mount = /var/lib/lxc/c1/fstab
lxc.utsname = c1
lxc.arch = amd64
Als Netzwerktyp ist derzeit noch empty angegeben, da wir aber eine Netzwerkverbindung haben wollen ergänzen wir die Datei mit folgenden Einträgen
# Network configuration
lxc.network.name = veth0 # Name des Interfaces im Container
lxc.network.flags = up
lxc.network.link = br0 # Bridge Interface auf dem Host
lxc.network.veth.pair = veth0-sid # Interface auf dem Host welches benutzt wird um LXC zum Host zu connecten
lxc.network.ipv4 = 192.168.1.1/24 # IP Adresse des Containers
lxc.network.ipv4.gateway = 192.168.1.254
In der Zeile lxc.network.type muss noch das empty durch veth ersetzt werden. Andere Beispiele liegen unter /usr/share/doc/lxc/examples.
Meine /etc/network/interfaces auf dem Host habe ich dann wie folgt angepasst:
# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp
up iptables -t nat -F POSTROUTING
up iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
auto br0
iface br0 inet static
address 192.168.1.254
netmask 255.255.255.0
bridge_ports none
Nun muss noch das IPv4 Forwarding aktiviert werden. In der Datei /etc/sysctl.conf folgende Zeile hinzufügen oder die vorhandene suchen und unkommentieren (mir fällt grad das Wort nicht ein :D )
net.ipv4.ip_forward=1
Mit diesen Einstellungen sollte der Container mit der Außenwelt kommunizieren können. Um das zu testen tut man folgendes
sysctl net.ipv4.ip_forward=1
iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
ifup br0
lxc-start -n c1 -d
-n gibt den Namen des Containers an und -d das er als Daemon laufen soll. Mit dem Befehl
lxc-console -n c1
kann man sich nun mit dem Container verbinden und auf diesem mit root root einloggen.
So das soll es erstmal gewesen sein. Ich werde denke mal in Zukunft weiter berichten, wenn ich damit noch mehr rummgespielt hab.
Quellen: Debian Wiki – LXC, coderwall – Clean LXC + NAT configuration (Debian Wheezy)