Linux Container sind eine schlanke und effiziente Methode Linux-Systeme zu virtualisieren. Ein Linux Container ist eine Gruppe von Prozessen, die zusammen in einer isolierten Umgebung laufen. Innerhalb des Containers ergibt sich ein Bild wie in einer virtuellen Maschine, am Host-System scheint der Container als normaler Prozesse auf. Um Ressourcen zu verwalten und zu limitieren verwenden Linux Container Control Groups (cgroups). Der folgende Artikel stellt die Metriken vor, die sich per cgroups im Zusammenhang mit Linux Container verwalten lassen. Es wird dabei auch auf die Userspace Werkzeuge, unter dem Namen LXC, eingegangen.
Control Groups sind ein Mechanismus zur Strukturierung/Verwaltung von Tasks in hierarchische(n) Gruppen. Im Speziellen können über unterschiedliche Subsysteme, Limitierungs (Accounting) Maßnahmen getroffen werden.[1]
Folgende Subsysteme sind aktuell verfügbar:[2]
| Subsystem | Zweck |
|---|---|
| cpusets | Limits für CPUs und Memory Nodes für Tasks einer Gruppe. |
| blkio | Limits für Input/Output Zugriffe auf Block Devices. |
| cpuacct | Limits für CPU Ressourcen von Tasks einer Gruppe. |
| devices | Erlaubt oder verbietet Zugriffe auf Devices für Gruppen. |
| freezer | Suspend oder Resume von Tasks. |
| hugetlb | Limits für Virtual Memory Tables. |
| memory | Limits für Memory für Tasks in einer Gruppe. |
| net_cls | Tagged Netzwerk-Pakete mit Class IDs, ein Traffic Controller kann IDs Prioritäten zuordnen. |
| net_prio | Prioritäten für Netzwerk-Traffic von Tasks einer Gruppe. |
| cpu | CPU Scheduling Verwaltung, zusammen mit cpuacct.
|
| perf_event | Monitoring Threads einer Task Gruppe auf einer CPU. |
Die folgenden Beispiele zeigen zwei einfache Tests mit cgroups. Erstens über den traditionellen Weg über Verzeichnisse und Dateien, zweitens über die cgmanager-utils, die unter Ubuntu mit dem Central cgroup manager daemon kommunizieren. Ubuntu setzt seit 14.04 Codename Trusty per Default einen Socket-Daemon ein, um cgroups zu verwalten. Das war in Zusammenhang mit LXC vor allem für nested Containers nötig.[3][4]
Die cgroup freezer übernimmt das Starten und Stoppen von Tasks.[5] Diese CGroup wird z.B. auch bei Checkpoint/Restore eingesetzt.
Im folgenden Beispiel wird ein ping Befehl mit FROZEN eingefroren, das tailf gibt keine weiteren Zeilen aus, solange der Tasks im FROZEN Status ist.
# mkdir /mnt/cgroup1 # mount -t cgroup -o freezer cgroup /mnt/cgroup1 # mkdir /mnt/cgroup1/task1 # ls /mnt/cgroup1/task1/ cgroup.clone_children cgroup.procs freezer.self_freezing notify_on_release cgroup.event_control freezer.parent_freezing freezer.state tasks # ping -D thomas-krenn.com >> freezer.txt & [1] 2958 # echo 2958 > /mnt/cgroup1/task1/tasks # cat /mnt/cgroup1/task1/tasks 2958 # echo FROZEN > /mnt/cgroup1/task1/freezer.state # tailf freezer.txt # echo THAWED > /mnt/cgroup1/task1/freezer.state # tailf freezer.txt # kill 2958
blkio setzt Limits für den Block IO Controller um. Im folgenden Beispiel wird der Durchsatz auf 1M/s limitiert:
# cgm create blkio bt
# cgm create blkio bt/test1
# fio ssd-test.fio &> ssd.out &
[2] 1859
# cgm movepid blkio bt/test1 1859
# cgm gettasks blkio bt/test1
method return sender=(null sender) -> dest=(null destination) reply_serial=1
array [
int32 1859
]
# cgm setvalue blkio bt/test1 blkio.throttle.read_bps_device "8:0 1048576"
# cgm getvalue blkio bt/test1 blkio.throttle.read_bps_device
string "8:0 1048576"
# iotop -o -n 3 -b|grep fio
1914 be/4 root 1015.88 K/s 0.00 B/s 0.00 % 0.00 % fio ssd-test.fio
1914 be/4 root 1013.04 K/s 0.00 B/s 0.00 % 0.00 % fio ssd-test.fio
LXC setzt beim Verwalten von Linux Container auf cgroups. Ressourcen können dadurch auf Container aufgeteilt werden.[6]

Während des Betriebs der Container können dann zugehörige Werte der cgroups abgefragt werden. Erste Werte liefert lxc-info:
Ein Aufruf von lxc-info zeigt den aktuellen Status zu einem Container:
# lxc-info -n ubuntu1 Name: ubuntu1 State: RUNNING PID: 1645 IP: 10.0.3.119 CPU use: 1.58 seconds BlkIO use: 22.67 MiB Memory use: 31.48 MiB KMem use: 0 bytes Link: veth0EP3QM TX bytes: 1.87 KiB RX bytes: 1.90 KiB Total bytes: 3.77 KiB
Folgende Informationen werden von lxc-info hier benutzt:[7]
| Metrik | Ursprung |
|---|---|
| CPU use | lxc-cgroup -n ubuntu1 cpuacct.usage |
| BlkIO use | lxc-cgroup -n ubuntu1 blkio.throttle.io_service_bytes |
| Memory use | lxc-cgroup -n ubuntu1 memory.usage_in_bytes |
| KMem use | lxc-cgroup -n ubuntu1 memory.kmem.usage_in_bytes |
| Link | cat /sys/class/net/veth0EP3QM/statistics/*_bytes |
Jedes Subsystem besitzt mehrere Parameter, die man abfragen kann. Interessant sind z.B.:[8]
memory.failcnt: Jene Anzahl, an der der Verbrauch an Memory den Schwellwert limit_in_bytes erreicht hat.memory.stat: Detaillierte Memory Statistiken.[9]Traditionelle Kommandos werden über lxc-attach in den Containern ausgeführt:
# lxc-attach -n ubuntu1 -- top -n 1 -b
top - 10:12:47 up 58 min, 0 users, load average: 0.00, 0.02, 0.05
Tasks: 18 total, 1 running, 17 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.4 us, 0.6 sy, 1.3 ni, 97.1 id, 0.4 wa, 0.0 hi, 0.2 si, 0.0 st
KiB Mem: 501756 total, 445412 used, 56344 free, 67048 buffers
KiB Swap: 522236 total, 0 used, 522236 free. 231220 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 33368 2724 1480 S 0.0 0.5 0:00.27 init
191 root 20 0 19472 652 456 S 0.0 0.1 0:00.02 upstart-udev-br
201 root 20 0 49268 1380 948 S 0.0 0.3 0:00.00 systemd-udevd
Problem dabei ist, dass ohne #LXCFS, die ausgegebenen Werte von /proc nicht zum Container passen. Eigentlich hätte folgender Container ein Limit von 256MB konfiguriert:
# grep limit_in_bytes /var/lib/lxc/ubuntu1/config lxc.cgroup.memory.limit_in_bytes = 256M
Wird im Container selbst das free Programm aufgerufen, stimmt dieses Limit nicht mit den Werten überein:[10]
# lxc-attach -n ubuntu1
root@ubuntu1:~# free -m
total used free shared buffers cached
Mem: 489 457 32 5 81 241
Das Problem an den Werkzeugen ist, dass sie sich auf /proc Verzeichnis beziehen, welches aber nicht containerized wird.
LXCFS nimmt sich diesem Problem an, es kann Files mit den korrekten Werten über die /proc Files bind mounten.[11] Unter Ubuntu 15.04 kann lxcfs über die Ubuntu Repos installiert und konfiguriert werden.
Im ersten Schritt wird ein Hook in die Container Config eingefügt:
# vi /var/lib/lxc/ubuntu1/config lxc.include = /usr/share/lxc/config/common.conf.d/00-lxcfs.conf
Beim starten im Debug Mode kann geprüft werden, ob der Hook ausgeführt wird:
# lxc-start -l debug -o lxc.log -d -n ubuntu1
# grep lxcfs lxc.log
lxc-start 1427909718.663 INFO lxc_conf - conf.c:run_script_argv:345 - Executing script '/usr/share/lxcfs/lxc.mount.hook' for container 'ubuntu1', config section 'lxc'
Am Host selbst läuft lxcfs als Service und lxcfs ist nach /var/lib/lxcfs gemountet:
root@vivid:~# mount | grep lxcfs lxcfs on /var/lib/lxcfs type fuse.lxcfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other) root@vivid:~# service lxcfs status lxcfs.service - FUSE filesystem for LXC Loaded: loaded (/lib/systemd/system/lxcfs.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2015-03-31 08:25:32 CEST; 1h 3min ago [...]
Prüft man die Uptime am Host und im Container, stimmt diese nun mit der tatsächlichen Uptime überein:
root@vivid:~# uptime 09:38:23 up 1:12, 2 users, load average: 0.00, 0.01, 0.05 root@vivid:~# lxc-attach -n ubuntu1 root@ubuntu1:~# uptime 09:38:31 up 7 min, 0 users, load average: 0.00, 0.01, 0.05 root@vivid:~# ls /var/lib/lxcfs/proc/ cpuinfo meminfo stat uptime
|
Autor: Georg Schönberger Georg Schönberger, Abteilung DevOps bei der XORTEX eBusiness GmbH, absolvierte an der FH OÖ am Campus Hagenberg sein Studium zum Bachelor Computer- und Mediensicherheit, Studium Master Sichere Informationssysteme. Seit 2015 ist Georg bei XORTEX beschäftigt und arbeitet sehr lösungsorientiert und hat keine Angst vor schwierigen Aufgaben. Zu seinen Hobbys zählt neben Linux auch Tennis, Klettern und Reisen.
|