Podman でサービス運用
サービス運用に利用していた VPS が障害により起動しなくなり、初期化することになりました。
いい機会なので、運用方針を見直しています。
サービスは Podman というコンテナツールを利用するようにします。
同じコンテナツールである Docker と比較して、以下のような特徴があります。
- 一般ユーザーで利用するように作られている。
- dockerd デーモンのようなデーモンで起動の管理するのではなく、Linux の systemd の仕組みを利用するなどして管理する。
僕は Web サービスは主に Go 言語を使っています。
Go の場合は基本的には実行ファイルが一つできて、これをデプロイする形になります。
Python などのように実行環境が不要なのでコンテナ化せずに、実行ファイルを直接 systemd で管理してもいいのですが、以下のようなメリットがあります。
- デプロイが簡単。
podman pullコマンドでデプロイできます。ほとんどこれが採用の決め手です。 - Go でもまれに環境に依存することがある。Ubuntu のバージョン違いによる共有ライブラリのバージョン違いなど。
- Go 以外のものをデプロイするときにも同じやり方でデプロイできる。
Podmanについて
Podman の特徴です。
1. Rootlessモード
Podman コンテナを起動するのに一般ユーザーで起動できる。
一般ユーザーで起動すればいいだけ。
デフォルトで Rootless モードなので。
一般ユーザーのプロセスなので万が一何かあっても、一般ユーザーの権限内の事故で収まる。
2. IDマッピング
ボリュームを使ってコンテナ内のファイルを永続化している場合を考える。
Docker ではコンテナ内で作成したファイルはホスト側ではアクセス権限の都合で編集できない。権限の設定が面倒。
Podman ではコンテナを起動すると、特にユーザーを指定しないとコンテナ内では root が実行ユーザーになっている。
この root はホスト側の起動したユーザーにマッピングされている。
コンテナ内で root でファイルを作成した場合、ホスト側ではそのファイルの owner はコンテナを起動した一般ユーザーになっている。
sudo せずに普通に編集できる。
3. Quadlet
Podman コンテナを systemd で管理するようにする。
systemd で管理すると、
- OS 起動時に自動起動できる
- ログを journalctl で見られる
などのメリットがある。
Quadlet というツールを利用して、コンテナの説明を書いたファイルから systemd 用の.servece ファイルを作成する。
このツールは systemd と連動して裏で動いてくれるので、特にツールを意識しなくてもいい。
Podman インストール時に既に Quadlet が利用できるようになっている。
以下のようなファイルを次の場所に用意します。~/.config/containers/systemd/mysleep.container
(mysleep.container ファイルは RedHat のドキュメントより引用。)
そして、systemctl コマンドを実行すると.service ファイルが作成されます。
[Unit]
Description=The sleep container
After=local-fs.target
[Container]
Image=registry.access.redhat.com/ubi8-minimal:latest
Exec=sleep 1000
[Install]
# Start by default on boot
WantedBy=multi-user.target default.target
次のコマンドを実行すると .service ファイルが作成されます。
systemctl --user daemon-reload
/run/user/1000/systemd/generator/mysleep.service が作成される。
# Automatically generated by /usr/lib/systemd/user-generators/podman-user-generator
#
[Unit]
Description=The sleep container
After=local-fs.target
SourcePath=/home/myuser/.config/containers/systemd/mysleep.container
RequiresMountsFor=%t/containers
[X-Container]
Image=registry.access.redhat.com/ubi8-minimal:latest
Exec=sleep 1000
[Install]
# Start by default on boot
WantedBy=multi-user.target default.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
KillMode=mixed
ExecStop=/usr/bin/podman rm -v -f -i --cidfile=%t/%N.cid
ExecStopPost=-/usr/bin/podman rm -v -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 registry.access.redhat.com/ubi8-minimal:latest sleep 1000
以下のコマンドで、サービスとして起動します。
systemctl --user start mysleep.service