PodmanのQuadletでコンテナのsystemdサービス化を行う
はじめに
この記事ではPodman v4.4.0から導入されたQuadletについて概念や使い方の解説を行います。
Quadletとは
Podmanではv4.4.0からQuadletという仕組みが導入されました。
https://github.com/containers/podman/releases/tag/v4.4.0
従来はPodmanのコンテナをsystemdサービスにする際に、ユニットファイルを用意する必要があり、ユニットファイルの生成にsystemd generate
コマンドが利用されていました。
Quadletを利用することで、直接systemdのユニットファイルを作成・編集する必要が無くなり、より抽象化された形でコンテナのsystemdサービス化を行うことが出来ます。
なおv4.7.0から従来のsystemd generate
コマンドは非推奨になり、Quadletを利用することが推奨されています。
https://github.com/containers/podman/releases/tag/v4.7.0
https://docs.podman.io/en/latest/markdown/podman-generate-systemd.1.html
Quadletの仕組み
Quadletファイルの形式
QuadletではまずQuadletファイルの作成をする必要があります。
Quadletファイルの文法はsystemdユニットファイルと同様です。
Quadletファイル特有のカスタムセクションとユニットファイルに記載出来る設定で構成されます。
カスタムセクションには後述する拡張子に応じて設定内容が変わります。
例えば.container
の場合は以下のドキュメントに記載されているように[Container]セクション
にpodman run
コマンド実行時のオプションの内容が指定可能です。
https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html#container-units-container
拡張子は以下にすることが出来、拡張子によってユニットファイルのService
セクション内のType
フィールドが変わります。
.container
Type=notify
-
.volume
Type=oneshot
.network
Type=oneshot
.pod
Type=forking
.kube
Type=notify
またファイルの保存場所としては以下のパターンがあります。
/etc/containers/systemd/
/usr/share/containers/systemd/
$XDG_CONFIG_HOME/containers/systemd/ または ~/.config/containers/systemd/
/etc/containers/systemd/users/$(UID)
/etc/containers/systemd/users/
実際に動かす
前提
- OSバージョン
- RHEL v9.3
- Podmanバージョン
- v4.6.1
- Rootlessでコンテナを起動
利用するファイル
今回はドキュメントに記載のファイル例を実際に動かしながら動作を確認します(volumeとnetworkの設定など一部を変更しています)。
[Unit]
Description=A minimal container
[Container]
# Use the centos image
Image=quay.io/centos/centos:stream9
# In the container we just run sleep
Exec=sleep 60
[Service]
# Extend Timeout to allow time to pull the image
TimeoutStartSec=900
[Install]
# Start by default on boot
WantedBy=multi-user.target default.target
https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html#examples
このQuadletファイルはCentOS Streamイメージをコンテナとして動かしsleep 60
コマンドを実行しています。
ファイルの保存場所についてはドキュメントにいくつか記載がありますが、今回はルートレスかつ特定のユーザーでのみ動作すれば問題ないので/etc/containers/systemd/user/${UID}/
以下に保存します。
実行するコマンド
まず作成したファイルに問題が無いか確認を行ってみます。
作成したファイルのデバッグは/usr/lib/systemd/system-generators/podman-system-generator --user --dryrun
コマンドで可能です。
ファイル内容に問題があれば、エラーが表示されるため素早くデバッグが可能です。
# 正常パターン
$ /usr/lib/systemd/system-generators/podman-system-generator --user --dryrun
quadlet-generator[17580]: Loading source unit file /etc/containers/systemd/users/1000/test.container
---test.service---
[Unit]
Description=A minimal container
SourcePath=/etc/containers/systemd/users/1000/test.container
RequiresMountsFor=%t/containers
[X-Container]
# Use the centos image
Image=quay.io/centos/centos:stream9
# In the container we just run sleep
Exec=sleep 60
[Service]
# Extend Timeout to allow time to pull the image
TimeoutStartSec=900
Environment=PODMAN_SYSTEMD_UNIT=%n
KillMode=mixed
ExecStop=/usr/bin/podman rm -f -i --cidfile=%t/%N.cid
ExecStopPost=-/usr/bin/podman rm -f -i --cidfile=%t/%N.cid
Delegate=yes
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
ExecStart=/usr/bin/podman run --name=systemd-%N --cidfile=%t/%N.cid --replace --rm --cgroups=split --sdnotify=conmon -d quay.io/centos/centos:stream9 sleep 60
[Install]
# Start by default on boot
WantedBy=multi-user.target default.target
# 異常パターン
$ /usr/lib/systemd/system-generators/podman-system-generator --user --dryrun
quadlet-generator[17045]: Loading source unit file /etc/containers/systemd/users/1000/test.container
quadlet-generator[17045]: No files parsed from [/home/ec2-user/.config/containers/systemd /etc/containers/systemd/users/1000 /etc/containers/systemd/users]
作成したファイルに問題が無ければ、systemctl --user daemon-reload
コマンドを実行することで作成したQuadletファイルがサービスとして認識されます。
生成された後の状態を確認すると以下のようになり、サービスが増えているのが分かります。
$ systemctl --user list-unit-files -t service
UNIT FILE STATE PRESET
dbus-broker.service enabled enabled
dbus.service alias -
dirmngr.service static -
gpg-agent.service static -
grub-boot-success.service static -
podman-auto-update.service disabled disabled
podman-kube@.service disabled disabled
podman-restart.service disabled disabled
podman.service disabled disabled
ssh-agent.service static -
systemd-exit.service static -
systemd-tmpfiles-clean.service static -
systemd-tmpfiles-setup.service enabled enabled
test.service generated - # new
14 unit files listed.
$ systemctl --user status test.service
○ test.service - A minimal container
Loaded: loaded (/etc/containers/systemd/users/1000/test.container; generated)
Active: inactive (dead)
systemctl --user start
コマンドを利用してサービスを試しに起動してみます。
$ systemctl --user start test.service
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
281c67ee5a16 quay.io/centos/centos:stream9 sleep 60 4 seconds ago Up 4 seconds systemd-test
$ systemctl --user status test.service
● test.service - A minimal container
Loaded: loaded (/etc/containers/systemd/users/1000/test.container; generated)
Active: active (running) since Thu 2024-02-22 12:02:59 UTC; 35s ago
Main PID: 17680 (conmon)
Tasks: 3 (limit: 22830)
Memory: 1.6M
CPU: 103ms
CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/test.service
├─libpod-payload-3ea4056bc3eb8090825dd84c49b38865dcbbcb88c0392231471752d30ec32d9a
│ └─17682 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 60
└─runtime
├─17677 /usr/bin/slirp4netns --disable-host-loopback --mtu=65520 --enable-sandbox --enable-seccomp --enable-ipv6 -c -r 3 -e 4 --netns-type=path /run/user/1000/netns/netns-a86401c6-b2a5-4434-1f9d-262495bf77de tap0
└─17680 /usr/bin/conmon --api-version 1 -c 3ea4056bc3eb8090825dd84c49b38865dcbbcb88c0392231471752d30ec32d9a -u 3ea4056bc3eb8090825dd84c49b38865dcbbcb88c0392231471752d30ec32d9a -r /usr/bin/crun -b /home/ec2-user/.local/shar>
podman ps
やsystemctl --user status
コマンドで確認を行うと、コンテナが実行していることが分かります。
まとめ
このブログではv4.4.0からの新機能であるQuadletを利用してコンテナのsystemdサービス化を行いました。
Quadletはユニットファイルの構文に加えて、拡張子ごとのカスタムセクションによってより少ない記述で柔軟にユニットファイルの記述が出来ます。
まだまだ利用例は少ないですが、今後主流になっていく方法なので便利に利用していけたらと思います。
参考
https://docs.podman.io/en/latest/markdown/podman-generate-systemd.1.html