Containermanagement

Container sind ein tolles Tool. Man kann damit mühelos Prozesse "paketieren" und damit auch ein Stück weit vom Host isolieren, ohne sich über die zusätzlichen Attribute wie Sizing und Basissystem (wie bei LXC oder VMs) Gedanken machen zu müssen.

Man kann sich aber auch kräftig in den Fuß schießen und einen Zoo von Containern anlegen, die man nie wieder "eingefangen" bekommt. Die größte mir bekannte Kritik am Konzept liegt darin, dass das Paketmanagement vom Host-System umgangen wird und so beispielsweise Sicherheitslücken im Container rumschimmeln können. Ergo wäre ein guter Management-Layer schon sehr vom Vorteil, und das ist auch meine Motivation zum Thema gewesen.

Von BSD-Jails (2000) über Docker (2013) und Kubernetes (2014) sind wir nun bei Podman mit eng verzahnter systemd-Integration, auch Quadlets genannt (2023).

Parallel dazu gibt es für kleinere Umgebungen wie die meine auch noch Portainer (Community Edition) und minikube. Ein kleines Kubernetes würde mich ein bisschen reizen, aber ich konnte mich dafür noch nicht motivieren. Portainer... naja, ich bin erst auf ihrer Homepage gelandet (weil ich dort einen Überblick über den Scope und die Features erhoffte) und wurde erstmal massiv von der Enterprise-Big-Money-Front erschlagen, um dann die github-Seite zu finden. Da ich aber nur ungern Aufwand in freemium-Modelle investiere, war das dann auch raus (dann lieber beizeiten minikube).

Mein bisheriges Setup

Ein kleiner Haufen Container, erst vor etwa einem Jahr oder so auf podman und podman-compose migriert... inklusive Scripte, die mir die Parameter gesetzt haben. Beispielsweise zigbee2mqtt:

~$ cat /usr/local/bin/run_zigbee2mqtt.sh 
podman run -d -v /var/lib/zigbee2mqtt/:/app/data/ -v /run/udev:/run/udev:ro --device=/dev/ttyACM0 --user 125:125 --group-add dialout -e TZ=Europe/Berlin --add-host heimdall:192.168.1.100 -p 8083:8080 --name zigbee2mqtt koenkk/zigbee2mqtt

Und davon gab es weitere. Dann eine systemd-Unit, die darauf ausgelegt war, einen existierenden Container zu steuern. Besonders elegant war das nicht, und die compose-basierten Projekte musste ich auch noch von ihrem jeweiligen Verzeichnis starten.

Derzeit habe ich sieben Container - nichts, was Kubernetes rechtfertigt, aber auch mehr als ich von Hand starten will.

Quadlets

Da die anderen Optionen weniger attraktiv aussahen, und ich eh schon ein Stück weit in systemd investierte, schaute ich mir Quadlets an.

Was Quadlets nicht inhärent haben, ist die Beziehung zwischen den einzelnen Containern innerhalb einer Compose-Umgebung. Das muss man selbst nachbilden, bzw. in die systemd-Welt übersetzen. Hier beispielsweise für tandoor, eine Rezeptverwaltung:

/etc/containers/systemd/tandoor_app.container

[Unit]
Requires=tandoor_db.service
After=tandoor_db.service

[Container]
Image=docker.io/vabene1111/recipes:2
AutoUpdate=registry
PublishPort=7400:80

EnvironmentFile=/var/lib/tandoor/.env
Volume=staticfiles:/opt/recipes/staticfiles
Volume=/var/lib/tandoor/mediafiles:/opt/recipes/mediafiles

Network=tandoor.network

[Service]
Restart=always

[Install]
WantedBy=default.target

/etc/containers/systemd/tandoor_db.container

[Container]
ContainerName=tandoor_db

Image=docker.io/postgres:16-alpine
EnvironmentFile=/var/lib/tandoor/.env
PublishPort=5432:5432

Volume=/var/lib/tandoor/postgresql:/var/lib/postgresql/data

Network=tandoor.network

[Service]
Restart=always

/etc/containers/systemd/tandoor.network

[Unit]
Description=Tandoor Network

[Network]
Label=app=tandoor

Warum das jetzt eine eigene Postgres braucht.. diskutabel. Aber alleine schon zum Ausprobieren wollte ich das 1:1 mit eigenem Netzwerk übertragen. Darüber hinaus habe ich keine zweite Postgres-Datenbank, insofern ist das verschmerzbar, und es schenkt mir ein automatisiertes DB-Setup.

Aber genug dazu inhaltlich - das Resultat sind Container in Unit-Form, die man sogar bequem aktualisieren kann:

Updates

Dazu muss man den zugehörigen Service von podman aktivieren:

~$ systemctl --user enable podman-auto-update

Und darauf achten, seine Container nicht zu hart zu pinnen (siehe oben, ich habe nur recipes:2 gepinnt, nicht die derzeitige patch-Version), dann kann man wie folgt updaten:

~$ podman auto-update 
Trying to pull docker.io/vabene1111/recipes:2...
Getting image source signatures
Copying blob d8a25ba09267 done   | 
Copying blob c987cde7f297 skipped: already exists  
Copying blob 5eb8a9c59764 skipped: already exists  
Copying blob 53aaed31b5d8 done   | 
Copying blob ea971c774474 skipped: already exists  
Copying blob 4f4fb700ef54 skipped: already exists  
Copying blob 9824c27679d3 skipped: already exists  
Copying blob 609c1235cc6c done   | 
Copying blob 994ca2cf04e9 done   | 
Copying blob af86421c2bda done   | 
Copying blob d4b8c5dc1357 done   | 
Copying blob 869571f6ca29 done   | 
Copying blob 11c584175115 done   | 
Copying blob 84121b4e492e done   | 
Copying blob 4f4fb700ef54 skipped: already exists  
Copying config b416dd0964 done   | 
Writing manifest to image destination
            UNIT                 CONTAINER                           IMAGE                           POLICY      UPDATED
            tandoor_app.service  19227e269278 (systemd-tandoor_app)  docker.io/vabene1111/recipes:2  registry    true

Was ich seit der Aktivierung dieses Setups immer wieder mal händisch ausführe - könnte man sicher mit einem cronjob (oder gleich einem systemd-Timer) automatisieren.

Fazit

Weiter bin ich bisher nicht eingestiegen, aber es hat mir bereits geholfen, den Container-Zoo zu managen. Nachteil ist natürlich, dass man für jedes Projekt Units pflegen muss - aber es bleibt mir ja nicht verwehrt, nach wie vor mit podman oder podman-compose ad-hoc-Container zu starten.

Was ich mir noch nicht angeschaut habe, sind Quadlets im Userspace - ich hab das einfach gelassen und Container, die vorher unter meinem User liefen, mit User=thorsten im Systemkontext laufen lassen. Abgesehen von "ich kann das" fiel mir kein Grund ein, das anders zu halten.

Darüber hinaus habe ich die Gelegenheit genutzt, alle Volumes in /var/lib/ zu zentralisieren - fühlt sich nun aufgeräumter an.

Ein paar der Links aus der Recherche