Podman è noto per la sua perfetta integrazione nei moderni sistemi Linux e il supporto di systemd è una pietra miliare in questi sforzi. Linux usa comunemente il sistema systemd init per gestire servizi locali come server Web, motori di container, demoni di rete e tutte le loro interdipendenze. L'estensione di queste pratiche più tradizionali di amministrazione del sistema Linux al mondo moderno dei container è un'evoluzione naturale.
Esistono due casi d'uso comuni per la combinazione di systemd e container:
- Esecuzione di systemd all'interno di un container
- Utilizzo di systemd per eseguire applicazioni containerizzate
Il primo scenario è l'esecuzione di systemd all'interno di un container. Come spiega Dan Walsh, eseguire systemd all'interno di un container è semplice come può essere quando si utilizza Podman. Podman imposta automaticamente diversi mount nel container e systemd è a posto. Sebbene sia una funzionalità Podman relativamente piccola, quando è stata introdotta è stato un enorme passo avanti per l'esecuzione di carichi di lavoro containerizzati.
Storicamente, altri strumenti contenitore non hanno supportato systemd. Gli utenti hanno dovuto affrontare la sfida di scrivere script di inizializzazione personalizzati, che sono soggetti a errori e un onere di supporto per i fornitori di software. Con Podman, tutti questi problemi scompaiono. Gli utenti possono utilizzare systemd per installare ed eseguire le loro applicazioni in container, proprio come in qualsiasi altro luogo, ei fornitori di software non dovranno affrontare le sfide legate alla gestione di script di inizializzazione personalizzati scritti dai loro utenti.
Il secondo scenario prevede l'utilizzo di systemd per eseguire e gestire le applicazioni containerizzate. Ciò significa che systemd avvia un'applicazione containerizzata e ne gestisce l'intero ciclo di vita. Podman lo semplifica con podman generate systemd
comando, che genera un file di unità systemd per un contenitore o pod specificato. Podman v1.7 e versioni successive supportano la generazione di tali unità. Nel tempo, il nostro team ha migliorato questa funzionalità e generato file di unità di sistema che possono essere eseguiti su altre macchine, in modo simile all'utilizzo di un file YAML di Kubernetes o di un file Compose. Inoltre, la stretta integrazione con systemd ha gettato le basi per aggiornamenti automatici e semplici rollback, supportati da Podman v3.4.
Sebbene ci siano molti blog e articoli precedenti sulla generazione di unità systemd per i contenitori, non ce ne sono per la generazione di queste unità per i pod. Ma prima di entrare in questi dettagli, voglio rivedere cos'è un pod.
[ Iniziare con i container? Dai un'occhiata a questo corso gratuito. Distribuzione di applicazioni containerizzate:una panoramica tecnica. ]
Cos'è un pod?
Ci sono diverse parti in un pod e penso che Brent Baude lo spieghi meglio con l'ottima figura qui sotto:
La prima cosa da notare è che un pod è costituito da uno o più contenitori. Il gruppo condivide i gruppi di controllo (cgroup) e spazi dei nomi specifici come PID, rete e spazio dei nomi IPC. I cgroup condivisi assicurano che tutti i contenitori abbiano gli stessi vincoli di risorse. Gli spazi dei nomi condivisi consentono ai contenitori di comunicare tra loro più facilmente (ad esempio tramite localhost o comunicazione interprocesso).
Puoi anche vedere uno speciale contenitore infra. Il suo scopo principale è tenere aperte risorse specifiche associate al pod, come porte, spazi dei nomi o cgroup. L'infra container è il container di primo livello del pod, viene creato prima di altri container e distrutto per ultimo. Usi il contenitore infra durante la generazione di unità systemd per un pod, quindi tieni presente che questo contenitore funziona per l'intera durata del pod. Implica anche che non puoi generare unità systemd per pod senza un contenitore infra (come --infra=false
).
Ultimo ma non meno importante, vedi più conmon
processi in esecuzione, uno per container. "Comune" è l'abbreviazione di container monitor, che riassume le sue funzionalità principali. Si occupa anche dell'inoltro dei registri e dell'esecuzione di azioni di pulizia una volta terminato il contenitore. Il conmon
il processo inizia prima del contenitore e indica il runtime del contenitore sottostante (come runc
o crun
) per creare e avviare il contenitore. Esce anche con il codice di uscita del contenitore consentendo di utilizzarlo come processo principale di un servizio systemd.
Generazione di unità di sistema per un pod
Podman genera esattamente un'unità di sistema per un container. Una volta installato, usa systemctl
per avviare, interrompere e ispezionare il servizio. Il PID principale di ciascuna unità è il processo comune del contenitore. In questo modo, systemd può leggere il codice di uscita del contenitore e agire in base alla politica di riavvio configurata. Per maggiori dettagli sulle unità, fare riferimento a Contenitori in esecuzione con Podman e servizi condivisibili di sistema e Podman di sistema migliorato con Podman 2.0.
La generazione di unità per un pod è molto simile all'avvio di un container. Ogni contenitore nel pod ha un'unità di sistema dedicata e ogni unità dipende dall'unità di sistema principale del pod. In questo modo, puoi continuare a utilizzare systemctl
avviare, fermare e ispezionare il servizio principale del pod; systemd si occuperà del (ri)avvio e dell'arresto dei servizi dei container insieme al servizio principale.
Questo esempio crea un pod con due contenitori, genera file unit per il pod e quindi installa i file per l'utente corrente:
$ podman pod create --name=my-pod
635bcc5bb5aa0a45af4c2f5a508ebd6a02b93e69324197a06d02a12873b6d1f7
$ podman create --pod=my-pod --name=container-a -t centos top
c04be9c4ac1c93473499571f3c2ad74deb3e0c14f4f00e89c7be3643368daf0e
$ podman create --pod=my-pod --name=container-b -t centos top
b42314b2deff99f5877e76058ac315b97cfb8dc40ed02f9b1b87f21a0cf2fbff
$ cd $HOME/.config/systemd/user
$ podman generate systemd --new --files --name my-pod
/home/vrothberg/.config/systemd/user/pod-my-pod.service
/home/vrothberg/.config/systemd/user/container-container-b.service
/home/vrothberg/.config/systemd/user/container-container-a.service
Come previsto, Podman ha generato tre .service
file, uno per ogni contenitore più quello di primo livello per il pod. Si prega di fare riferimento all'appendice alla fine dell'articolo per vedere l'intero contenuto dei file di unità. Le unità generate per i due contenitori sembrano unità contenitore standard più le seguenti dipendenze systemd:
BindsTo=pod-my-pod.service
:L'unità contenitore è "legata" all'unità del pod. Se l'unità del pod viene arrestata, anche questa verrà arrestata.After=pod-my-pod.service
:L'unità contenitore si avvia dopo l'unità del pod.
Le dipendenze del servizio principale del pod assicurano inoltre che se un'unità container non si avvia correttamente, anche l'unità principale del pod principale si guasta.
Questo è tutto ciò che devi sapere sulla generazione di unità systemd per pod con Podman. Dopo aver ricaricato systemd tramite systemctl --user daemon-reload
, avvia e interrompi il pod.service
a volontà. Dai un'occhiata:
# Reload the daemon
$ systemctl --user daemon-reload
# Start the pod service and make sure the service is running
$ systemctl --user start pod-my-pod.service
$ systemctl --user is-active pod-my-pod.service
active
# Make sure the pod and its containers are running
$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
6dd1090d4ca6 my-pod Running 2 minutes ago 85f760a5cfe5 3
user $ podman container ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
85f760a5cfe5 localhost/podman-pause:4.0.2-1646319369 5 minutes ago Up 5 minutes ago 6dd1090d4ca6-infra
44a7e60b9563 quay.io/centos/centos:latest top 5 minutes ago Up 5 minutes ago container-b
31f24bdff747 quay.io/centos/centos:latest top 5 minutes ago Up 5 minutes ago container-a
Ottimo, tutto funziona come previsto. Puoi usare systemctl
per avviare i servizi e Podman elenca correttamente i pod ei relativi contenitori. Per motivi di coerenza, dai un'occhiata finale a come interrompere il servizio pod.
# Stop the pod service
$ systemctl --user stop pod-my-pod.service
# Make sure the pod and its containers are removed
$ podman pod ps -q
$ podman container ps -q
# Make sure the services are inactive
$ systemctl --user is-active pod-my-pod.service container-container-a.service container-container-b.service
inactive
inactive
inactive
Il messaggio da portare a casa è che Podman genera unità systemd per i pod proprio come fa per i container. Le dipendenze tra queste unità sono impostate in modo tale che tu abbia solo bisogno di interagire con l'unità principale del pod e systemd si occupa dell'avvio e dell'arresto delle unità dei contenitori.
Appendice
Podman genera i seguenti file di unità per un pod e i due contenitori correlati.
pod-my-pod.service
Description=Podman pod-my-pod.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=
Requires=container-container-a.service container-container-b.service
Before=container-container-a.service container-container-b.service
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/pod-my-pod.pid %t/pod-my-pod.pod-id
ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-my-pod.pid --pod-id-file %t/pod-my-pod.pod-id --name=my-pod --replace
ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-my-pod.pod-id
ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-my-pod.pod-id -t 10
ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-my-pod.pod-id
PIDFile=%t/pod-my-pod.pid
Type=forking
[Install]
WantedBy=default.target
container-container-a.service
[Unit]
Description=Podman container-container-a.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers
BindsTo=pod-my-pod.service
After=pod-my-pod.service
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run --cidfile=%t/%n.ctr-id --cgroups=no-conmon --rm --pod-id-file %t/pod-my-pod.pod-id --sdnotify=conmon -d --replace --name=container-a -t centos top
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all
[Install]
WantedBy=default.target
container-container-b.service
[Unit]
Description=Podman container-container-b.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers
BindsTo=pod-my-pod.service
After=pod-my-pod.service
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run --cidfile=%t/%n.ctr-id --cgroups=no-conmon --rm --pod-id-file %t/pod-my-pod.pod-id --sdnotify=conmon -d --replace --name=container-b -t centos top
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all
[Install]
WantedBy=default.target