Container mit systemd-nspawn erstellen

Datum

Container erstellen mit Systemd

Mit Systemd lassen sich recht simple Conatainer erstellen, welche mit systemd-nspawn erstellt und mit einem seperaten Managment-Tool verwaltet werden.
Im Grunde ist solch ein Container für mich nur chroot auf Steroiden. Ein weiteres Manko dabei ist das man SElinux deaktivieren muss, da sonst bestimmte Operationen, wie zum Beispiel das ändern des Passwortes innerhalb der systemd-Umgebung, nicht möglich sind.

Vorbereitungen

Ich verwende hierbei Centos 7.5.

Zuerst deaktivieren wir SElinux mit dem Befehl setenforce Permissive oder auch setenforce 0
Um diese Einstellung persistent einzustellen ersetzen wir in der Datei /etc/sysconfig/selinux die Zeile
SELINUX=enforcing
durch
SELINUX=permissive

Natürlich kann man auch nach dem Setzen des Passwortes SElinux per setenforce 1 wieder aktivieren.

Nun erstellen wir das Root-Verzeichnis für das Container-System:

$ mkdir /var/lib/container

Erstellen des Containers

Um einen Centos-Container zu erstellen führen wir den folgenden Befehl aus:

$ yum -y --releasever=7 --installroot=/var/lib/container/centos7 install systemd passwd yum vim

Hierbei wird ein Centos in der Version 7 (--releasever) im Verzeichnis /var/lib/container/centos7 (--installroot) angelegt und es werden die Pakete installiert, welche nach dem install mit angegeben werden.
Dies ist natürlich nur das rudimentäre System. Man kann, je nach Bedarf, noch weitere Pakete in den container installieren.

An dieser Stelle könnte man schon den Container starten hineinspringen, allerdings wird dann nach einem root-Passwort gefragt, welches bisher noch nicht gesetzt ist.

Um nun zu einer vollständigen Umgebung zu wechseln, in der man sich tatsächlich einloggen kann, muss man dem systemd-nspawn-Befehl den passwd-Befehl anhängen. Durchgeführt wird dies mit dem folgenden Befehl:

systemd-nspawn -D /var/lib/container/centos7 passwd

Alternativ dazu wechselt man mit dem Befehl
systemd-nspawn -D /var/lib/container/centos7
in den Container und ändert dort mit passwd das root-Passwort.

ANMERKUNG: Um sich später erfolgreich einloggen zu können muss im Container die Datei /etc/securetty entfernt oder umbenannt werden.

$ systemd-nspawn -D /var/lib/container/centos7 
Spawning container centos7 on /var/lib/container/centos7.
Press ^] three times within 1s to kill container.
-bash-4.2# mv /etc/securetty /etc/securetty.disable

Bei auf Debian basierenden Systemen muss dbus installiert sein

Container verwalten

Nun können wir den Container starten und hinwechseln, dies geschieht mit:
systemd-nspawn -D /var/lib/container/centos7 -b
Hier lauscht der Container am vorhandenen Netzwerk-Interface, wodurch uns nach dem Login direkt eine Netzwerkverbindung zur Verfügung steht.

Um den Container wieder zu verlassen, ohne poweroff eingeben zu müssen, verwendet man die Tastenkombination:
Strg + ], also Strg+ Alt Gr + 9 auf meiner Tastatur und das dabei muss die ]-Taste 3 mal hintereinander gedrückt werden.

Verwaltung mit machinectl

machinectl ist das Systemd-eigene Verwaltungs-Tool.

Um den Container für die Verwaltung durch Systemd verfügbar zu machen verwenden wir den folgenden Befehl:

$ systemctl enable systemd-nspawn@centos7
Created symlink from /etc/systemd/system/machines.target.wants/systemd-nspawn@centos7.service to /usr/lib/systemd/system/systemd-nspawn@.service.

Der nächste Schritt ist das starten des Containers mithilfe des Systemd-Container-Managment-Tool machinectl:

$ machinectl start centos7

Und genauso wie bei regulären Systemd-Diesnten kann man sich auch den aktuellen Staus anzeigen lassen:

$ machinectl status centos7
centos7
           Since: So 2018-05-27 20:17:46 CEST; 4s ago
          Leader: 11386 (systemd)
         Service: nspawn; class container
            Root: /var/lib/container/centos7
           Iface: ve-centos7
              OS: CentOS Linux 7 (Core)
            Unit: systemd-nspawn@centos7.service
                  ├─11385 /usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth --machine=centos7
                  ├─11386 /usr/lib/systemd/systemd
                  └─system.slice
                    ├─console-getty.service
                    │ └─11418 /sbin/agetty --noclear --keep-baud console 115200 38400 9600 vt220
                    ├─systemd-logind.service
                    │ └─11416 /usr/lib/systemd/systemd-logind
                    ├─dbus.service
                    │ └─11414 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
                    └─systemd-journald.service
                      └─11402 /usr/lib/systemd/systemd-journald

Mai 27 20:17:46 localhost.localdomain systemd-nspawn[11385]: Starting Console Getty...
Mai 27 20:17:46 localhost.localdomain systemd-nspawn[11385]: [  OK  ] Reached target Login Prompts.
Mai 27 20:17:46 localhost.localdomain systemd-nspawn[11385]: [  OK  ] Started Cleanup of Temporary Directories.
Mai 27 20:17:46 localhost.localdomain systemd-nspawn[11385]: [  OK  ] Started Login Service.
Mai 27 20:17:46 localhost.localdomain systemd-nspawn[11385]: [  OK  ] Reached target Multi-User System.
Mai 27 20:17:46 localhost.localdomain systemd-nspawn[11385]: [  OK  ] Reached target Graphical Interface.
Mai 27 20:17:46 localhost.localdomain systemd-nspawn[11385]: Starting Update UTMP about System Runlevel Changes...
Mai 27 20:17:46 localhost.localdomain systemd-nspawn[11385]: [  OK  ] Started Update UTMP about System Runlevel Changes.
Mai 27 20:17:47 localhost.localdomain systemd-nspawn[11385]: CentOS Linux 7 (Core)
Mai 27 20:17:47 localhost.localdomain systemd-nspawn[11385]: Kernel 3.10.0-862.3.2.el7.x86_64 on an x86_64

Um sich nun in den Container einzuloggen kann man auch wieder machinectl verwenden:

$ machinectl login centos7
Connected to machine centos7. Press ^] three times within 1s to exit session.

CentOS Linux 7 (Core)
Kernel 3.10.0-862.3.2.el7.x86_64 on an x86_64

centos7 login: 

Anmerkung Wenn ich mich per machinectl login <Containername> in einen Container einloggen fehlt leider immer Netzwerkverbindung.
Ich habe noch keine Lösung dafür gefunden und deshalb empfehle ich immer die Verwendung von systemd-nspawn -D /var/lib/container/centos7 -b

Um sich eine Auflistung der vorhandenen Container auf dem System anzeigen zu lassen, verwendet man:

$ machinectl list
MACHINE CLASS     SERVICE
centos7 container nspawn 

1 machines listed.

weitere Funktionen

Ähnlich wie z.B. auch LXC/LXD bietet der Systemd Befehl machinectl Funktionen, neben dem Starten, Neustarten, etc., zum kopieren von Dateien vom Hostsystem in den Container und auch hinaus an.

 poweroff NAME...
           Power off one or more containers. This will trigger a reboot by sending SIGRTMIN+4 to the container's init process, which causes systemd-compatible init systems to shut down cleanly.
reboot NAME...
           Reboot one or more containers. This will trigger a reboot by sending SIGINT to the container's init process, which is roughly equivalent to pressing Ctrl+Alt+Del on a non-containerized system,
           and is compatible with containers running any system manager.
copy-to NAME PATH [PATH]
           Copies files or directories from the host system into a running container....
copy-from NAME PATH [PATH]
           Copies files or directories from a container into the host system....

Es ist sogar das Klonen von Containern möglich…

clone NAME NAME
           Clones a container or disk image. The arguments specify the name of the image to clone and the name of the newly cloned image. Note that plain directory container images are cloned into
           subvolume images with this command. Note that cloning a container or VM image is optimized for btrfs file systems, and might not be efficient on others, due to file system limitations.

Autor
Kategorien Linux, Virtualisierung

PRTG Map