FedoraにおけるPodman Auto-update:ネイティブな手法でコンテナを自動化する

Fedora tutorial - IT technology blog
Fedora tutorial - IT technology blog

深夜の出来事:なぜコンテナの手動更新をやめたのか

午前2時、Telegramボットがサーバーのダウンを知らせました。慌てて起きて確認すると、午後に軽い気持ちで podman pull したNginxイメージの設定にミスがあり、サーバー再起動後にコンテナが起動できなくなっていました。手動でpullコマンドを打ち続ける運用は、いつか必ず限界が来ます。

Fedoraを開発機として2年使って気づいたのは、Watchtowerのようなサードパーティ製ツールをわざわざ導入する必要はないということです。FedoraとPodmanには、systemdに直接統合されたAuto-update機能が標準で備わっています。このソリューションは、Watchtowerを動かすのに比べてRAMを20〜50MBほど節約できます。何より重要なのは、新しい更新に問題があった場合に即座に旧バージョンへロールバックできる点です。

クイックスタート:5分でAuto-updateを設定する

Podmanが更新が必要なコンテナを認識できるようにするには、作成時に label を付与するだけです。以下の手順に従ってください。

ステップ1:識別用ラベルを付けてコンテナを実行する

注意:Podmanがダイジェストを正確にチェックできるように、レジストリを含む完全なイメージ名を使用することが必須です。

podman run -d --name my-web-app \
  --label "io.containers.autoupdate=image" \
  docker.io/library/nginx:latest

ラベル io.containers.autoupdate=image は「フラグ」のような役割を果たします。これにより、Podmanに対してDocker Hub上の新しいバージョンを定期的に確認するよう指示します。

ステップ2:コンテナ管理用のsystemdファイルを作成する

Podmanはデーモンレス(daemonless)モデルで動作するため、ライフサイクル管理にはsystemdが必要です。次のコマンドでsystemdファイルを作成します。

mkdir -p ~/.config/systemd/user/
cd ~/.config/systemd/user/
podman generate systemd --name my-web-app --files --new

パラメータ --new は必須です。これにより、Podmanは古いコンテナを再利用しようとするのではなく、ダウンロードしたばかりの新しいイメージからコンテナを新規作成できるようになります。

ステップ3:サービスとタイマーを有効化する

それでは、systemdの設定をリロードしてサービスを有効化しましょう。

systemctl --user daemon-reload
systemctl --user enable --now container-my-web-app.service

準備が整ったか確認するために、シミュレーションコマンドを実行できます。

podman auto-update --dry-run --format "{{.Image}} {{.Updated}}"

動作の仕組み:コピペで終わらせず、理解を深める

podman auto-update コマンドが実行されると、システムは以下の4つのステップを実行します。

  1. io.containers.autoupdate ラベルを持つ実行中のコンテナをスキャンします。
  2. レジストリ(Docker Hub, Quay.ioなど)にリクエストを送り、イメージのハッシュ値(digest)を取得します。
  3. ダイジェストを比較します。レジストリ上のものが新しい場合、Podmanはイメージをプルします。
  4. systemdサービスを再起動し、プルした新しいイメージからコンテナを起動します。

Fedoraのデフォルトでは、podman-auto-update.timer というタイマーが毎日00:00に実行されます。実行スケジュールは以下のコマンドで確認できます。

systemctl --user status podman-auto-update.timer

ロールバックの極意:安眠のための保険

Podmanの最大の魅力は自己修復能力にあります。新しくプルしたイメージが「Running」状態であっても、実際には内部のサービスがエラーを吐いていることがよくあります。Podmanはこれをヘルスチェック(Health Check)で解決します。

ヘルスチェックを設定しておくと、Podmanは古いイメージを予備として保持します。新しいコンテナがヘルスチェックに合格しなかった場合、自動的に旧バージョンにロールバックします。

podman run -d --name secure-app \
  --label "io.containers.autoupdate=image" \
  --health-cmd="curl http://localhost/ || exit 1" \
  --health-interval=5s \
  --health-retries=3 \
  --health-on-failure=rollback \
  docker.io/library/nginx:latest

--health-on-failure=rollback フラグがあれば、安心して眠りにつけます。アップデートに失敗しても、システムが自動的に「一歩下がって」Webサイトの稼働を維持してくれます。

管理とデバッグ

システムが何を行ったかを確認するには、systemdのログをチェックします。

journalctl --user -u podman-auto-update.service

注意:SSHからログアウトすると、ユーザーサービスが停止することがあります。「linger」モードを有効にして、コンテナがバックグラウンドで走り続けるようにしましょう。

sudo loginctl enable-linger $USER

実践的なアドバイス:陥りやすい失敗

これまでの失敗から学んだ、自動更新を利用する際の3つの教訓を紹介します。

  • データベースには絶対に :latest タグを使わない: Postgresが勝手に13から16に上がり、データ構造が壊れてしまうような事態は避けたいはずです。:13 のように具体的なタグを使用しましょう。
  • ゴミイメージの処理: 更新のたびに古いイメージ(dangling image)が残ります。週に一度 podman image prune -f を実行するcronジョブを追加して、ストレージを掃除しましょう。
  • プライベートレジストリ: ログイン済みであること、そして auth.json ファイルが正しい場所にあり、ログインしていない状態でもsystemdがアクセスできる権限を持っていることを確認してください。

この方法は、毎日手動でpullコマンドを打つのよりもプロフェッショナルで、SysAdminらしいやり方です。セットアップの成功を祈っています!

Share: