インフラ

PodmanのQuadletでコンテナのsystemdサービス化を行う

ryo

はじめに

この記事では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 pssystemctl --user statusコマンドで確認を行うと、コンテナが実行していることが分かります。

まとめ

このブログではv4.4.0からの新機能であるQuadletを利用してコンテナのsystemdサービス化を行いました。

Quadletはユニットファイルの構文に加えて、拡張子ごとのカスタムセクションによってより少ない記述で柔軟にユニットファイルの記述が出来ます。

まだまだ利用例は少ないですが、今後主流になっていく方法なので便利に利用していけたらと思います。

参考

https://docs.podman.io/en/latest/markdown/podman-generate-systemd.1.html

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/building_running_and_managing_containers/advantages-of-using-quadlets-over-the-podman-generate-systemd-command_assembly_porting-containers-to-systemd-using-podman

AUTHOR
ryo
ryo
記事URLをコピーしました