Debian LXC

Aus Wiki
Zur Navigation springen Zur Suche springen

Einleitung

LXC (Linux Container) erstellt mehrere isolierte, sichere virtuelle Umgebungen (Virtual Environments, kurz VEs) auf einem einzigen physischem Server, sorgt so für eine bessere Serverausnutzung und stellt sicher, dass Programme (Applikationen) nicht miteinander in Konflikt geraten. Jede VE arbeitet und verhält sich genau wie ein eigenständiger Server; VEs können unabhängig voneinander neu gestartet werden und haben Root-Zugriff, Benutzer, IP-Adressen, Speicher, Prozesse, Dateien, Programme, Systembibliotheken und Konfigurationsdateien.

Im Vergleich zu Virtuellen Maschinen von VMware bzw Virtualbox oder zu Para-Virtualisierungstechnologien wie Xen bietet OpenVZ weniger Flexibilität, was die Auswahl von Gast-Betriebssystemen betrifft: sowohl Gast- als auch Host-Betriebssystem muss Linux sein (obwohl verschiedene Linux-Distributionen in verschiedenen VEs eingesetzt werden können).

Im Gegensatz zu OpenVZ ist LXC Bestandteil des Mainline Kernel und erfordert somit keinerlei spezielle Patches, wie dies bei OpenVZ erforderlich ist. D.h. es wird im Rahmen des "normalen" Linux-Kernels weiterentwickelt und sollte deshalb in Zukunft gegenüber OpenVZ bevorzugt werden. Der Nachfolger des aktuellen Squeeze stellt vermutlich den Support für OpenVZ ein.


Installation LXC

Nachdem LXC Bestandteil des Kernels ist, sind lediglich Userspace-Tools für die Verwaltung der LXC-Container erforderlich.

apt-get update
apt-get install lxc bridge-utils debootstrap


Konfiguration des Host

Netzerkbridge

Für die Nezwerkverwaltung benötiogt LXC eine Netzwerkbrücke (Bridge) auf dem Host.

vi /etc/network/interfaces

Z.B. vorhandene Einstallungen:

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
iface eth0 inet static
   address 192.168.100.111
   netmask 255.255.255.0
   gateway 192.168.100.1

Die physikalische Netzwerkschnittstelle (z.B. eth0) auf manual setzen (und die iface-Einstellungen auskommentieren):

auto eth0
iface eth0 inet manual
#iface eth0 inet static
#   address 192.168.100.111
#   netmask 255.255.255.0
#   gateway 192.168.100.1
#   broadcast 192.168.100.255

Stattdessen die Bridge automatisch konfigurieren:

auto br0
iface br0 inet static
  address 192.168.100.111
  netmask 255.255.255.0
  gateway 192.168.100.1
  broadcast 192.168.100.255
  bridge_ports eth0
  bridge_fd 0
  bridge_maxwait 0
  bridge_stp off

Netzwerk neu starten, um die Änderungen zu übernehmen:

/etc/init.d/networking restart


Cgroups

Für die Verwaltung der Ressourcen der LXC-Container sind sog. cgroups erforderlich.

vi /etc/fstab

Folgende Zeilen ans Ende anfügen:

#CGroup for LXC
cgroup  /cgroup  cgroup  defaults  0  0

Cgroup Verzeichnis erstellen:

mkdir -p /cgroup

Cgroup mounten:

mount /cgroup


LXC Templates

Im Verzeichnis /usr/lib/lxc/templates/ liegen Templates für die Installation von Debian (Lenny), Ubuntu und Fedory Distributionen als Gast Container.

Standard Pakete ergänzen

Das Debian-Template lädt lediglich ein Debian Minimalsystem auf die lokale Festplatte herunter, sodass sogar Basisfunktionalitäten wie Ping nicht zur Verfügung stehen. Die Liste zu installierender Pakete kann jedoch beliebig erweitert werden. Z.B.:

vi /usr/lib/lxc/templates/lxc-debian

Zu Beginn der Funktion download_debian() (Zeile 86) wird die Variable packes definiert, die zusätzliche Pakete enthält, die installiert werden. Diese Variable erweitern (durch \ am Zeilenende erstreckt sich dieser Parameter über mehrere Zeilen). Hier z.B. incl. einiger sinnvoller Ergänzungen nach openssh-server (diese Liste kann beliebig erweitert werden):

   packages=\
ifupdown,\
locales,\
libui-dialog-perl,\
dialog,\
dhcp-client,\
netbase,\
net-tools,\
iproute,\
openssh-server,apt-utils,wget,vim-nox,nano,iputils-ping,netcat,rsyslog


Debian-Squeeze Template

Durch eine kleine Änderung des Debian-Templates kann dieses anstatt einer Lenny auch eine Squeeze Distribution installieren:

cp /usr/lib/lxc/templates/lxc-debian /usr/lib/lxc/templates/lxc-squeeze
chmod +x /usr/lib/lxc/templates/lxc-squeeze
vi /usr/lib/lxc/templates/lxc-squeeze
  • In Zeile 93: dhcp-client durch isc-dhcp-client ersetzen
  • In Zeile 113: lenny durch squeeze ersetzen
  • In Zeile 139: cache="/var/cache/lxc/debian" durch cache="/var/cache/lxc/squeeze" ersetzen
  • In Zeile 223: cache="/var/cache/lxc/debian" durch cache="/var/cache/lxc/squeeze" ersetzen


TTY-Devices, Locales, Zeitzone und Standardshell

Durch folgende Ergänzung werden die nötigen TTY-Devices automatisch angelegt und es erscheint am Ende des Anlegeprozesses eines neuen LXC-Containers eine Aufforderung zum Setzen der verfügbaren Locales und der Standardsprache, Zeitzone und Shell.

Template erweitern:

  • Debian Lenny Template
vi /usr/lib/lxc/templates/lxc-debian

In der Funktion configure_debian() nach folgendem Block

# reconfigure some services
   if [ -z "$LANG" ]; then
        chroot $rootfs locale-gen en_US.UTF-8
        chroot $rootfs update-locale LANG=en_US.UTF-8
    else
        chroot $rootfs locale-gen $LANG
        chroot $rootfs update-locale LANG=$LANG
    fi

folgende Zeilen einfügen:

    #TTY-Devices
    mknod -m 666 $rootfs/dev/tty1 c 4 1
    mknod -m 666 $rootfs/dev/tty2 c 4 2
    mknod -m 666 $rootfs/dev/tty3 c 4 3
    mknod -m 666 $rootfs/dev/tty4 c 4 4

    #locales und timezone
    chroot $rootfs dpkg-reconfigure locales
    chroot $rootfs dpkg-reconfigure tzdata
  • Debian Squeeze Template
vi /usr/lib/lxc/templates/lxc-squeeze

In der Funktion configure_debian() nach folgendem Block

# reconfigure some services
   if [ -z "$LANG" ]; then
        chroot $rootfs locale-gen en_US.UTF-8
        chroot $rootfs update-locale LANG=en_US.UTF-8
    else
        chroot $rootfs locale-gen $LANG
        chroot $rootfs update-locale LANG=$LANG
    fi

folgende Zeilen einfügen:

    #TTY-Devices
    mknod -m 666 $rootfs/dev/tty1 c 4 1
    mknod -m 666 $rootfs/dev/tty2 c 4 2
    mknod -m 666 $rootfs/dev/tty3 c 4 3
    mknod -m 666 $rootfs/dev/tty4 c 4 4

    #locales, timezone und shell
    chroot $rootfs dpkg-reconfigure locales
    chroot $rootfs dpkg-reconfigure tzdata
    chroot $rootfs dpkg-reconfigure dash


Config Link automatisch anlegen

Die LXC-Templates legen die Konfigurationsfiles standardmäßig unter /var/lib/lxc/lxc-container/config ab. Damit der Container automatisch beim Systemstart gestartet werden kann, muss noch ein Link in /etc/lxc/ auf dieses Configfile angelegt werden. Dies kann automatisch vom Template erledigt werden:

  • Debian Lenny Template
vi /usr/lib/lxc/templates/lxc-debian
  • Debian Squeeze Template
vi /usr/lib/lxc/templates/lxc-squeeze

In der Funktion copy_configuration() nach folgendem Block:

    if [ $? -ne 0 ]; then
        echo "Failed to add configuration"
        return 1
    fi

Folgende Zeile einfügen:

    ln -s $path/config /etc/lxc/`basename $path`.conf


Debian Wheezy Template

apt-get install lxc bridge-utils debootstrap
vi /etc/fstab

folgende Zeile einfügen:

cgroup /cgroup cgroup defaults 0 0
mkdir /cgroup
mount /cgroup

Nun muss das lxc-debian-wheezy Template im Ordner /usr/share/lxc/templates anlegen.

mkdir /usr/share/lxc
mkdir /usr/share/lxc/templates
vi /usr/share/lxc/templates/lxc-debian-wheezy
#!/bin/bash

configure_debian()
{
    rootfs=$1
    hostname=$2
 
    # configure the inittab
    cat <<EOF > $rootfs/etc/inittab
id:3:initdefault:
si::sysinit:/etc/init.d/rcS
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
1:2345:respawn:/sbin/getty 38400 console
c1:12345:respawn:/sbin/getty 38400 tty1 linux
c2:12345:respawn:/sbin/getty 38400 tty2 linux
EOF
 
    # create tty devices
    chroot $rootfs mknod -m 666 /dev/tty1 c 4 1
    chroot $rootfs mknod -m 666 /dev/tty2 c 4 2
 
    # disable selinux in debian
    mkdir -p $rootfs/selinux
    echo 0 > $rootfs/selinux/enforce
 
    # configure the network using the dhcp
    cat <<EOF > $rootfs/etc/network/interfaces
auto lo
iface lo inet loopback
 
auto eth0
iface eth0 inet dhcp
EOF
 
    # set the hostname
    cat <<EOF > $rootfs/etc/hostname
$hostname
EOF
 
    # set dhcp hostname
    cat <<EOF >> $rootfs/etc/dhcp/dhclient.conf
send host-name "$hostname";
EOF
 
    # set default locale
    cat <<EOF > $rootfs/etc/locale.gen
en_US.UTF-8 UTF-8
EOF
 
    # reconfigure some services
    if [ -z "$LANG" ]; then
    chroot $rootfs locale-gen en_US.UTF-8
    chroot $rootfs update-locale LANG=en_US.UTF-8
    else
    chroot $rootfs locale-gen $LANG
    chroot $rootfs update-locale LANG=$LANG
    fi
 
    # remove pointless services in a container
    chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove
    chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove
    chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove
 
    echo "root:root" | chroot $rootfs chpasswd
    echo "Root password is 'root', please change !"
 
    return 0
}
 
download_debian()
{
    packages=\
ifupdown,\
locales,\
libui-dialog-perl,\
dialog,\
isc-dhcp-client,\
netbase,\
net-tools,\
iproute,\
vim,\
emacs23-nox,\
iputils-ping,\
openssh-server
 
    cache=$1
    arch=$2
 
    # check the mini debian was not already downloaded
    mkdir -p "$cache/partial-$arch"
    if [ $? -ne 0 ]; then
        echo "Failed to create '$cache/partial-$arch' directory"
     return 1
    fi
 
    # download a mini debian into a cache
    echo "Downloading debian minimal ..."
    debootstrap --verbose --variant=minbase --arch=$arch \
    --include $packages \
    wheezy $cache/partial-$arch http://ftp.us.debian.org/debian
    if [ $? -ne 0 ]; then
    echo "Failed to download the rootfs, aborting."
    return 1
    fi
 
    mv "$1/partial-$arch" "$1/rootfs-$arch"
    echo "Download complete."
 
    return 0
}
 
copy_debian()
{
    cache=$1
    arch=$2
    rootfs=$3
 
    # make a local copy of the minidebian
    echo -n "Copying rootfs to $rootfs..."
    cp -a $cache/rootfs-$arch $rootfs || return 1
    return 0
}
 
install_debian()
{
    cache="/var/cache/lxc/debian-wheezy"
    rootfs=$1
    mkdir -p /var/lock/subsys/
    (
        flock -n -x 200
        if [ $? -ne 0 ]; then
            echo "Cache repository is busy."
            return 1
        fi
 
        arch=$(arch)
        if [ "$arch" == "x86_64" ]; then
            arch=amd64
        fi
 
        if [ "$arch" == "i686" ]; then
            arch=i386
        fi
 
        echo "Checking cache download in $cache/rootfs-$arch ... "
        if [ ! -e "$cache/rootfs-$arch" ]; then
            download_debian $cache $arch
            if [ $? -ne 0 ]; then
                echo "Failed to download 'debian base'"
                return 1
            fi
        fi
 
        copy_debian $cache $arch $rootfs
        if [ $? -ne 0 ]; then
            echo "Failed to copy rootfs"
            return 1
        fi
 
        return 0
 
    ) 200>/var/lock/subsys/lxc
 
    return $?
}
 
copy_configuration()
{
    path=$1
    rootfs=$2
    name=$3
 
    cat <<EOF >> $path/config
l xc.tty = 4
l xc.pts = 1024
lxc.rootfs = $rootfs
lxc.cgroup.devices.deny = a
# /dev/null and zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
# consoles
lxc.cgroup.devices.allow = c 5:1 rwm
lxc.cgroup.devices.allow = c 5:0 rwm
lxc.cgroup.devices.allow = c 4:0 rwm
lxc.cgroup.devices.allow = c 4:1 rwm
# /dev/{,u}random
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 136:* rwm
lxc.cgroup.devices.allow = c 5:2 rwm
# rtc
lxc.cgroup.devices.allow = c 254:0 rwm
 
# mounts point
lxc.mount.entry=proc $rootfs/proc proc nodev,noexec,nosuid 0 0
lxc.mount.entry=devpts $rootfs/dev/pts devpts defaults 0 0
lxc.mount.entry=sysfs $rootfs/sys sysfs defaults  0 0
 
lxc.utsname = $name
 
# networking
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.name = eth0
# It is fine to be commented out
#lxc.network.ipv4 = 192.168.10.21/24
# Change this
# lxc.network.hwaddr = 00:11:22:33:44:00
EOF
 
    if [ $? -ne 0 ]; then
        echo "Failed to add configuration"
        return 1
    fi
 
    return 0
}
 
clean()
{
    cache="/var/cache/lxc/debian-wheezy"
 
    if [ ! -e $cache ]; then
        exit 0
    fi
 
    # lock, so we won't purge while someone is creating a repository
    (
        flock -n -x 200
        if [ $? != 0 ]; then
            echo "Cache repository is busy."
            exit 1
        fi
 
        echo -n "Purging the download cache..."
        rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
        exit 0
 
    ) 200>/var/lock/subsys/lxc
}
 
usage()
{ 
    cat <<EOF
$1 -h|--help -p|--path=<path> --clean
EOF
    return 0
}
 
options=$(getopt -o hp:n:c -l help,path:,name:,clean -- "$@")
if [ $? -ne 0 ]; then
    usage $(basename $0)
    exit 1
fi
eval set -- "$options"
 
while true
do
    case "$1" in
        -h|--help)      usage $0 && exit 0;;
        -p|--path)      path=$2; shift 2;;
        -n|--name)      name=$2; shift 2;;
        -c|--clean)     clean=$2; shift 2;;
        --)             shift 1; break ;;
        *)              break ;;
    esac
done
 
if [ ! -z "$clean" -a -z "$path" ]; then
    clean || exit 1
    exit 0
fi
  
type debootstrap
if [ $? -ne 0 ]; then
    echo "'debootstrap' command is missing"
    exit 1
fi
 
if [ -z "$path" ]; then
    echo "'path' parameter is required"
    exit 1
fi
 
if [ "$(id -u)" != "0" ]; then
    echo "This script should be run as 'root'"
    exit 1
fi
 
rootfs=$path/rootfs
 
install_debian $rootfs
if [ $? -ne 0 ]; then
    echo "failed to install debian"
    exit 1
fi
 
configure_debian $rootfs $name
if [ $? -ne 0 ]; then
    echo "failed to configure debian for a container"
    exit 1
fi
 
copy_configuration $path $rootfs $name
if [ $? -ne 0 ]; then
    echo "failed write configuration file"
    exit 1
fi
 
if [ ! -z $clean ]; then
    clean || exit 1
    exit 0
fi

LXC Container anlegen

Die Container (Root Filesystem des Gastbetriebssystems) werden in Unterverzeichnissen unter /var/lib/lxc abgelegt. Beispielhaft wird hier ein Debian/Squeeze Gast-Container mit Namen debian angelegt.

Debian Squeeeze

mkdir /var/lib/lxc/debian
/usr/lib/lxc/templates/lxc-squeeze -p /var/lib/lxc/debian/
Bulbgraph.png Hinweis:
Am Ende des Scriptes werden Fehler bzgl. Locales ausgegeben ("perl: warning: Setting locale failed." ...), die normal sind, da ein minimales Debian Squeeze System installiert wurde. Die Locales werden im Anschluß konfiguriert.


Nach dem Download der Pakete und Erzeugen des Root- Filesystems werden noch folgende drei Configurationsdialoge angezeigt, um Locales, Zeitzone und Shell zu konfigurieren:

  • Dialogconfiguring locales
    • In der Liste Locales to be generated die zu installierende Locale-Variante (oder mehrere) mit Leertaste auswählen, z.B. en_us.UTF8
    • Mit Tab-Taste OK auswählen und Return betätigen
    • Im nächsten Dialog die Default Locale auswählen (die eben installierte)
    • Mit Tab-Taste OK auswählen und Return betätigen
  • Dialog configuring tzdata (Einstellen der Zeitzone)
    • In der Liste Europe markieren
    • Mit Tab-Taste OK auswählen und Return betätigen
    • In der Liste Timezone Berlin markieren
    • Mit Tab-Taste OK auswählen und Return betätigen
  • Standardshell bash/dash (nur unter Debian Squeeze)
Zum Schluß wird noch die Shell konfiguriert. Standardmäßig kommt unter Debian Squeeze Dash als Shell zum Einsatz. Dies ist eine schnelle, schlanke Alternative Shell. Aus Kompatibilitätsgründen empfiehlt es sich allerdings, Bash zu verwenden:
Im erscheinenden Dialog configuring dash den Punkt no selektieren, um Bash zu verwenden.


Das Konfigurationsfile des Containers wurde im Unterverzeichnis debian angelegt. Es sollte aber auch im Ordner /etc/lxc/debian.conf abgelegt werden, damit der Container Autostart beim Systemstart funktioniert (Siehe hier). Dies wird mit Hilfe eines symbolischen Links erledigt:

ln -s /var/lib/lxc/debian/config /etc/lxc/debian.conf


Debian Wheezy

lxc-create -n debian -t debian-wheezy

Damit wird er Kontainer debian mit dem User root und dem Passwort root angelegt.

Gast Konfiguration

Allgemein

Das Konfigurationsfile des oben angelegten LXC Containers liegt im jeweiligen Unterverzeichnis des Containers (z.B. /var/lib/lxc/debian/config).

Das Root Filesystem des Gast-Containers wird im selben Unterverzeichnis wie das Konfigfile abgelegt. Im Ordner rootfs/ liegen sämtliche Files des virtuellen Gastbetriebssystems und können vom Host wie normale Files behandelt werden.


Container Konfigurationsfile

Mit Hilfe folgender Einstellungen wird der neue Gast debian an die Network Bridge br0 "angedockt". Die Netzwerkschnittstelle innerhalb des Gastes lautet eth0, der nicht mit der physikalischen Nezwerkkarte eth0 auf dem Host zu verwechseln ist.

cd /var/lib/lxc/debian
vi config

Folgende Einträge ergänzen:

lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.name = eth0
lxc.network.mtu = 1500

Optional: Festlegen der MAC-Adresse des virtuellen Gastes (z.B. MAC-Adresse=ce:a2:45:df:2a:3f):

lxc.network.hwaddr = ce:a2:45:df:2a:3f


Netzwerkkonfiguration

Standardmäßig verwenden die LXC Gastsysteme DHCP. Falls eine feste IP-Adresse gewünscht wird, folgende Schritte ausführen:

cd /var/lib/lxc/debian
vi rootfs/etc/network/interfaces

Das File sieht standardmäßig folgendermaßen aus:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

Ändern in feste IP-Adressen (z.B. 192.168.100.111):

iface eth0 inet static
        address 192.168.100.111
        netmask 255.255.255.0
        broadcast 192.168.100.255
        gateway 192.168.100.1


Hostname und Domain

Dem LXC Gast sollte ein eindeutiger Hostname zugewiesen werden, da ansonsten der Name des Hosts verwendet wird.

cd /var/lib/lxc/debian
vi rootfs/etc/hostname

Hostname (ohne Domain) eingeben. Z.B. debian

Desweiteren sollte die Domain korrekt gesetzt werden:

vi rootfs/etc/hosts

Am Anfang des Files sollten folgende beiden Zeilen vorhanden sein bzw. eingefügt werden:

127.0.0.1       localhost
127.0.1.1       debian.schiele.homelinux.org debian


Paketquellen

cd /var/lib/lxc/debian
vi rootfs/etc/apt/sources.list

Es epfiehlt sich, dass das File folgende Zeilen enthält (für einen Debian-Squeeze Container):

deb http://ftp.de.debian.org/debian/ squeeze main contrib non-free 
deb-src http://ftp.de.debian.org/debian/ squeeze main contrib non-free

deb http://security.debian.org/ squeeze/updates main contrib non-free
deb-src http://security.debian.org/ squeeze/updates main contrib non-free

deb http://ftp.de.debian.org/debian/ squeeze-updates main contrib non-free
deb-src http://ftp.de.debian.org/debian squeeze-updates main contrib non-free


Start/Stop des LXC Containers

Der Container kann mit folgenden Befehlen (auf dem Host ausführen!) gestartet bzw. beendet werden:

lxc-start -n lxc-container -d
lxc-stop -n lxc-container
Bulbgraph.png Hinweis:
Der Befehl lxc-stop bricht eine laufende virtuelle Maschine einfach ab, ohne sie herunterzufahren. D.h. dieser Vorgang entspricht dem Ausschalten der Stromversorgung eines Linux-Rechners, ohne diesen vorher herunterzufahren. Um Schäden am Dateisystem der virtuellen Maschine zu vermeiden, sollte diese immer mit dem Shutdown-Befehl shutdown -h now bzw. poweroff auf der Console der virtuellen Maschine (lxc-console oder Putty) heruntergefahren werden. Nur wenn dies nicht möglich ist, kann als Ausweg der Befehl lxc-stop verwendet werden.

Mit dem Befehl

lxc-shutdown -n lxc-container

kann der LXC-Container vom Hostsystem heruntergefahren werden, falls der Workaround (siehe hier) eingerichtet wurde.


Nun den Container zum ersten mal starten:

lxc-start -n debian -d
Bulbgraph.png Hinweis:

Aus Sicherheitsgründen sollte als erster Schritt das Root-Passwort geändert werden. Dies ist Standardmäßig 'root:

passwd root


LXC Info

Mit dem Befehl lxc-info besteht die Möglichkeit zu prüfen, ob ein Container gestartet oder gestoppt wurde:

lxc-info -n lxc-container

LXC Console

LXC bietet die Möglichkeit, eine Console auf den Gast zu öffnen, und so diesen zu administrieren (z.B. ermitteln der IP-Adresse wenn DHCP im Gastbetriebssystem verwendet wird). Andererseits wird mit dem Debian bzw. Squeeze Installerscript automatisch ein SSH-Server mit installiert, sodass die Console eine eher weniger bedeutendes Feature darstellt (außer die IP-Adresse des Gastes ist nicht bekannt).

lxc-console -n lxc-container
Bulbgraph.png Hinweis:

Manchmal erscheint der Login Prompt nicht sofort. In diesem Fall hilft es, die Return-Taste zu betätigen. Die Gast-Console kann mit <CTRL a + q> verlassen werden. D.h. Tasten <CTRL> und <a> gleichzeitig drücken, dann beide loslassen und anschließend zeitnah betätigen


Autostart

LXC-Container können beim Systemstart automatisch gestartet werden.

  • Debian Squeeze:
vi /etc/default/lxc
folgende Änderungen durchführen:
RUN=yes
# Start /etc/lxc/debian.conf, /etc/lxc/squeeze.conf
CONTAINERS="debian squeeze"
Dadurch werden beim Systemstart die beiden Container debian und squeeze automatisch gestartet
  • Debian Wheezy:
vi /etc/default/lxc
folgende Änderungen durchführen:
LXC_AUTO="true"
LXC_DIRECTORY="/var/lib/lxc"
symbolische Links im Ordner /etc/lxc/auto erstellen:
ln -s /var/lib/lxc/debian/config /etc/lxc/auto/debian
ln -s /var/lib/lxc/squeeze/config /etc/lxc/auto/squeeze


LXC-Shutdown

Wenn der Hostrechner neu gebootet (reboot)oder abgeschaltet wird (poweroff), dann werden die LXC-Gastcontainer mittels lxc-stop Befehl gekilled. Dies könnte unter Umständen zu Schäden am Dateisystem der Gastcontainer führen. Deshalb wird hier ein Workaround für dieses Problem beschrieben, sodass alle Gast Container ordentlich heruntergefahren werden, bevor der Hostrechner komplett ausgeschaltet wird.

Bei ALLEN Gastcontainern folgende Änderung im File /etc/inittab durchführen. Dies kann entweder vom Host aus erfolgen:

vi /var/lib/lxc/lxc-container/rootfs/etc/inittab

oder im Gast selbst per lxc-console/Putty:

vi /etc/inittab

Folgende Zeile einfügen (z.B. am Ende):

pf::powerwait:poweroff
Warning.png Achtung:
  • Diese Änderung an allen LXC-Containern durchführen, mindestens jedoch bei denjenigen, die als Autostart (siehe hier) eingerichtet wurden.
  • evtl. laufende LXC-Container müssen unbedingt nach dieser Änderung angehalten und evtl. neu gestartet werden, da diese Änderung an /etc/inittab nur beim Start des Containers übernommen wird.
  • Falls nicht beide Punkte beachtet wurden, dann wird nach einedann wird der Hostrechner nicht mehr korrekt herunterfahren, sondern im Shutdownprozess "unendlich" lange wartenm Timeout von 30s je Container der Hostrechner heruntergefahren, obwohl der jeweilige Container nicht heruntergefahren wurde. Dieser Timeout verhindert, dass der Host Rechner im Shutdown-Prozess "unendlich" lange verharrt, wenn ein Container "hängen" bleiben sollte.

Ändern des/der Templates, damit das File etc/inittab beim künftigen Anlegen von LXC-Containern automatisch den zusätzlichen Eintrag enthält:

vi /usr/lib/lxc/templates/debian-squeeze

In Block die Zeile pf::powerwait:poweroff ergänzen, sodass der Block folgendermaßen aussieht:

   cat <<EOF > $rootfs/etc/inittab
id:3:initdefault:
si::sysinit:/etc/init.d/rcS
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
1:2345:respawn:/sbin/getty 38400 console
c1:12345:respawn:/sbin/getty 38400 tty1 linux
c2:12345:respawn:/sbin/getty 38400 tty2 linux
c3:12345:respawn:/sbin/getty 38400 tty3 linux
c4:12345:respawn:/sbin/getty 38400 tty4 linux
pf::powerwait:poweroff
EOF

Durch obige Änderung wird bei einem Powerfail Ereignis der poweroff Befehl im jeweiligen Container ausgeführt. Dieses Powerfail Ereignis wird von folgendem Script lxc-shutdown für den jeweiligen Container ausgelöst.

vi /usr/bin/lxc-shutdown

Folgende Zeilen einfügen:

#! /bin/sh
# Shut down container.

if [ $# -ne 2 ]; then
    echo "lxc-shutdown: missing container name, use --name option"
    exit 1
fi

case "$1" in
-n|--name)
    cont=$2
    ;;
*)
    echo "lxc-shutdown: missing container name, use --name option"
    exit 1
    ;;
esac

PS=`lxc-ps -C init -opid|grep $cont`
if [ -z "$PS" ]; then
    echo " Error: LXC-Container '$cont' not running or not existing!"
    exit 1
fi

echo "$PS" | while read VM PID ; do
    echo -n " shutting down LXC-Container '$cont' ... "
    kill -PWR $PID
    timeout 30 lxc-wait -n $VM -s STOPPED
    echo "success"
done

Script ausführbar machen:

chmod +x /usr/bin/lxc-shutdown

Damit dieses Shutdown-Script beim Herunterfahren des Hostsystems bzw. beim Befehl /etc/init.d/lxc stop ausgeführt wird, muss noch das Startscript angepasst werden:

vi /etc/init.d/lxc

Den Block um ca. Zeile 57

 stop)
   log_daemon_msg "Stopping $DESC"
   action_all "lxc-stop -n"

folgendermaßen abändern

 stop)
   log_daemon_msg "Stopping $DESC"
   action_all "lxc-shutdown -n"

Funktionstest: Auf den LXC-Gastsystemen ein Putty-Fenster öffnen, um beobachten zu können, ob der jeweilige Gast ordnungsgemäß heruntergefahren wird, oder gekillt wird.

Auf dem Hostsystem ausführen:

/etc/init.d/lxc stop

Sämtliche in /etc/default/lxc definierten Container sollten nun ordnungsgemäß heruntergefahren werden. Dies ist an folgender Meldung im jeweiligen Putty-Fenster ersichtlich:

The system is going down for system halt NOW!

LXC-Reboot

Folgendes Script bietet eine einfache und komfortable Möglichkeit, einen LXC-Container vom Hostsystem zu rebooten.

Voraussetzung:

  • LXC-Shutdown-Script eingerichtet
vi /usr/bin/lxc-reboot

Folgende Zeilen einfügen:

#! /bin/sh
# Reboot container.

if [ $# -ne 2 ]; then
    echo "lxc-reboot: missing container name, use --name option"
    exit 1
fi

case "$1" in
-n|--name)
    cont=$2
    ;;
*)
    echo "lxc-reboot: missing container name, use --name option"
    exit 1
    ;;
esac

lxc-shutdown -n $cont
echo -n "Starting Container '$cont' ... "
lxc-start -n $cont -d
echo "success"

Script ausführbar machen:

chmod +x /usr/bin/lxc-reboot

Container neu starten:

lxc-reboot -n lxc-container


Container auflisten

Mittels lxc-ls können sämtliche definierten und aktuell laufende LXC-Container angezeigt werden.

lxc-ls

Ausgabe z.B.:

debian squeeze test
squeeze test

Die Ausgabe bedeutet:

Die Container in der ersten Zeile sind definiert => debian, squeeze und test
Die Container in der zweiten Zeile werden aktuell ausgeführt => squeeze und test


Gastcontainer löschen

Zum löschen eines Containers dient der Befehl

lxc-destroy -n lxc-container
z.B.
lxc-destroy -n debian


Container clonen

Damit der "Clone" Befehl funktioniert, muss rsync und lxc-clone installiert sein.

  apt-get install rsync

Das Packet lxc-clone kann leider nicht mittels apt-get install installiert werden. Dafür muss das Paket runtergeladen und ausführbar gemacht werden.

  cd /usr/bin

wget: --> tbd

Anschließend muss die Datei noch ausführbar gemacht werden.

  chmod +x lxc-clone

Nun kann mittels dem "Clone" Befehl der Container geklont werden. Dies geht so:

    lxc-clone -o <Containername Original> -n <Containername Kopie>

Z.B.

    lxc-clone -o webserver -n webserver_bak

Zugriff auf USB-Geräte

USB-Geräte können in einem LXC-Container zur Verfügung gestellt werden. Im Gastcontainer muss zunächst ein Verzeichnis angelegt werden, in dem die USB-Geräte zur Verfügung gestellt werden können:

  • Im Gastcontainer:
mkdir -p /dev/bus/usb
  • alternativ vom Host-PC:
 mkdir -p /var/lib/container_name/root/dev/bus/usb

Folgende Schritte auf dem Host-PC ausführen:

  • Ermitteln der ID-des zu verwendenden USB-Gerätes (Paket usbutils muss installiert sein):
lsusb
Die Ausgabe könnte z.B. folgendermaßen aussehen:
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 003: ID 067b:2305 Prolific Technology, Inc. PL2305 Parallel Port
Bus 002 Device 004: ID 04b4:fd11 Cypress Semiconductor Corp.
Hier soll z.B. das Gerät 004 am USB-Bus 002 (SIS-PM Steckdosenleiste) im Container freigegeben werden. Diese verwendet einen Cypress USB-Adapter Chip.
ls -l /dev/bus/usb/002
Die Ausgabe könnte folgendermaßen aussehen:
crw-rw-r-T 1 root root  189, 128 May 12 19:21 001
crw-rw-r-T 1 root root  189, 129 May 12 19:21 002
crw-rw-r-T 1 root lp    189, 130 May 12 19:21 003
crw-rw-r-T 1 root sispm 189, 131 May 15 02:29 004

=> Die ID- des USB-Gerätetreibers für Gerätes 004 am Bus 002 ist 189 (wie auch von allen anderen Geräten). Diese ID wird im folgenden Schritt benötigt, um den Zugriff aus dem Gastcontainer auf diese Geräteklasse zu erlauben.

vi /var/lib/lxc/lxc-container/config

Folgende Zeilen (im Bereich der bereits vorhandenen cgroup Statements) einfügen, um Zugriff auf USB-Geräte zu erlauben (hier ID 189, evtl anpassen):

#USB
lxc.cgroup.devices.allow = c 189:* rwm

Folgende Zeile im Bereich der bereits vorhandenen Mount-Points einfügen, um das USB-Directory im Container zu mounten:

lxc.mount.entry=/dev/bus/usb /var/lib/lxc/lxc-container/rootfs/dev/bus/usb none rw,bind 0 0
  • Container neu starten
  • Überprüfen, ob USB-Geräte im Container verfügbar sind (Paket usbutils muss installiert sein):
lsusb
Die Ausgabe sollte analog der Ausgabe auf dem Host sein (siehe oben)