Podman实现容器自动更新

前言

目前有一个应用服务是通过podman拉取在阿里云的私有镜像仓库中的私有镜像进行部署的。镜像代码会根据开发进度进行实时更新,当需要发布版本时会通过Drone的CI/CD脚本自动推送到阿里云的镜像服务器。 当镜像发布新版本时希望每台服务器都需要自动更新至最新的镜像。

  • 当镜像版本被更新时需要处理的步骤
  1. 停止当前容器
  2. 拉取最新的镜像
  3. 运行新的容器(运行命令需同旧容器一致)

但是使用部署这个镜像的服务器环境有点复杂:一台是公网VPS;另外一台在纯内网环境(无法从公网SSH进去)。这些服务器也没法通过架设k8s来统一管理,也无法通过某个Drone的runner节点ssh到每台服务器执行命令更新。通过查询资料发现podmanauto-update功能可以达到上述要求。

一、容器标签

如果需要通过podman来对容器进行版本更新,则需要为容器打上io.containers.autoupdate=image标签。当容器镜像的版本有变化时podman会通过这个标签识别这个容器是否需要更新进而执行容器更新的处理。

podman run \
...
--label="io.containers.autoupdate=image"
...

二、通过systemd来运行容器

对于auto-update的执行还有另外一个要求,就是必须以systemd来运行该容器。
如何通过systemd来运行容器可以参照另外一篇文章:Podman在用户退出时服务中断
然而在生成service文件时必须指定--new标记,如果未指定的话则会运行失败。

podman generate systemd --new --name pod_name

生成文件后将其移动到~/.config/systemd/user文件夹下并执行systemctl --user daemon-reload
确保服务运行正常后则就可以通过podman auto-update来更新容器了。

~$ podman auto-update
UNIT          CONTAINER            IMAGE                POLICY      UPDATED
xx.service  196c45dxe167 (xx)  aliyuncs.com/xxx/xx      registry    false

三、定时执行

定时运行podman auto-update命令则可以通过cron或则systemd timer来实现。为保证镜像更新时容器能及时更新我将定时任务的频率设为了5分钟检查一次。

  • cron
*/5 * * * /usr/bin/podman auto-update
  • systemd timer
~$ vim .config/systemd/user/podman.service
[Unit]
Description=Podman auto-update service

[Service]
ExecStart=/usr/bin/podman auto-update
~$ vim .config/systemd/user/podman.timer
[Unit]
Description=Podman auto update erery 5 minutes

[Timer]
OnUnitActiveSec=5min
Unit=podman.service

[Install]
WantedBy=default.target
~$ systemctl --user daemon-reload
~$ systemctl --user enable podman.timer
~$ systemctl --user start podman.timer
~$ systemctl --user status podman.timer
● podman.timer - Podman auto update erery 5 minutes
     Loaded: loaded (/home/xxx/.config/systemd/user/podman.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Wed 2024-05-29 10:21:23 CST; 1h 3min ago
    Trigger: Wed 2024-05-29 11:26:18 CST; 1min 41s left
   Triggers: ● podman.service

May 29 10:21:23 xxx systemd[1123]: Started Podman auto update erery 5 minutes.

结语

这个解决方案可能不是最好的,作为个人开发者以及眼前的条件限制这是我能找到的一个最好的方法了。