О systemd и автообновлении контейнеров podman

Поговорим о наболевшем: обновлении контейнеров. Если их у вас много, этот процесс может затянуться на долго. Как решить эту проблему в podman и причём тут systemd?

Контейнерный движок Podman

Podman — это проект с открытым исходным кодом, который доступен на большинстве платформ Linux и находится на GitHub. Podman — это самостоятельная замена Docker, которая не требует демонов. У утилиты похожий интерфейс и набор команд как у Docker, и что более интересно — она может обрабатывать контейнеры с полным и некорневым доступом. Утилита Podman предустановлена на Fedora Linux, так что вы можете сразу её использовать.

Если хотите установить Podman, выберите соответствующую команду для вашей среды:

# Fedora Workstation / Server / Spins
$ sudo dnf install -y podman
# Fedora Silverblue, IoT, CoreOS
$ rpm-ostree install podman

Podman также доступен для других дистрибутивов Linux: CentOS, Debian, Ubuntu и прочих. Больше инструкций здесь.

Автообновление контейнеров

Запуск обновлений для контейнеров может быть утомительным и трудоёмким, поскольку вам нужно:

  • вытащить новый образ,
  • остановить и снять работающий контейнер,
  • запустить контейнер с новым образом.

Эту процедуру необходимо проделать для каждого контейнера. Для обновления 10 контейнеров может понадобиться выполнить 30-40 команд. Автоматизация этих шагов сэкономит время и обеспечит актуальность всех данных.

Podman и systemd

Вы можете запускать, останавливать, перезапускать контейнеры через systemd без отдельного демона. Всё потому что Podman имеет встроенную поддержку этой подсистемы. 

Функции автоматического обновления Podman нужно, чтобы контейнеры работали через systemd. Это единственный способ автоматизировать всё и сделать так, чтобы это “всё” хорошо работало. 

Что нужно сделать?

Запустите контейнер с желаемыми настройками:

# Run httpd container with some custom settings
$ sudo podman container run -d -t -p 80:80 --name web -v web-volume:/usr/local/apache2/htdocs/:Z docker.io/library/httpd:2.4
# Just a quick check of the container
$ sudo podman container ls
CONTAINER ID  IMAGE                        COMMAND           CREATED        STATUS            PORTS               NAMES
58e5b07febdf  docker.io/library/httpd:2.4  httpd-foreground  4 seconds ago  Up 5 seconds ago  0.0.0.0:80->80/tcp  web
# Also check the named volume
$ sudo podman volume ls
DRIVER      VOLUME NAME
local       web-volume

Теперь настройте systemd для обработки развёртывания. Podman сгенерирует необходимый файл.

# Generate systemd service file
$ sudo podman generate systemd --new --name --files web
/home/USER/container-web.service

Далее, он сгенерирует файл container-web.service в вашем текущем каталоге. Просмотрите файл и отредактируйте его так, чтобы вам было удобно. 

Вот содержимое файла с добавленными символами новой строки и форматированием для улучшения читаемости.

# container-web.service
[Unit]
Description=Podman container-web.service
Documentation=man:podman-generate-systemd(1)
Wants=network.target
After=network-online.target
RequiresMountsFor=%t/containers
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/container-web.pid %t/container-web.ctr-id
ExecStart=/usr/bin/podman container run \
          --conmon-pidfile %t/container-web.pid \
          --cidfile %t/container-web.ctr-id \
          --cgroups=no-conmon \
          --replace \
          -d \
          -t \
          -p 80:80 \
          --name web \
          -v web-volume:/usr/local/apache2/htdocs/ \
          docker.io/library/httpd:2.4
ExecStop=/usr/bin/podman container stop \
          --ignore \
          --cidfile %t/container-web.ctr-id \
          -t 10
ExecStopPost=/usr/bin/podman container rm \
          --ignore \
          -f \
          --cidfile %t/container-web.ctr-id
PIDFile=%t/container-web.pid
Type=forking
[Install]
WantedBy=multi-user.target default.target

Теперь удалите текущий контейнер, скопируйте файл в соответствующий каталог systemd и запустите службу.

# Remove the temporary container
$ sudo podman container rm -f web
# Copy the service file
$ sudo cp container-web.service /etc/systemd/system/container-web.service
# Reload systemd
$ sudo systemctl daemon-reload
# Enable and start the service
$ sudo systemctl enable --now container-web
# Another quick check
$ sudo podman container ls
$ sudo systemctl status container-web

Важно! Теперь контейнером можно управлять только через systemd. Запуск и остановка контейнера с помощью команды podman может мешать работе systemd.

Ручное автоматическое обновление

Первое, на что стоит обратить внимание — это автоматические обновления вручную. Звучит странно? Эта функция позволяет избежать лишних шагов, но при этом вы полностью контролируете время и дату обновления контейнеров. Это очень полезно, если вы хотите обновлять их только в период обслуживания или на выходных.

Что нужно делать?

Отредактируйте файл /etc/systemd/system/container-web.service и добавьте к нему метку:

--label "io.containers.autoupdate=registry"

В изменённом файле будет раздел, похожий на этот:

...snip...
ExecStart=/usr/bin/podman container run \
          --conmon-pidfile %t/container-web.pid \
          --cidfile %t/container-web.ctr-id \
          --cgroups=no-conmon \
          --replace \
          -d \
          -t \
          -p 80:80 \
          --name web \
          -v web-volume:/usr/local/apache2/htdocs/ \
          --label "io.containers.autoupdate=registry" \
          docker.io/library/httpd:2.4
...snip...

Теперь перезагрузите systemd и перезапустите контейнерную службу, чтобы изменения вступили в силу.

# Reload systemd
$ sudo systemctl daemon-reload
# Restart container-web service
$ sudo systemctl restart container-web

После этих манипуляций вы сможете запустить простую команду, которая обновит работающий объект до последнего доступного образа. 

Запланированные автообновления

Podman также имеет модуль таймера systemd, который позволяет обновлять контейнеры по расписанию. Не хотите самостоятельно обрабатывать обновления или у вас небольшой домашний сервер? Эта функция станет вашим спасением, ведь вы будете получать последние обновления каждую неделю или около того.

Что делать?

Включите таймер systemd для podman:

# Enable podman auto update timer unit
$ sudo systemctl enable --now podman-auto-update.timer 
Created symlink /etc/systemd/system/timers.target.wants/podman-auto-update.timer → /usr/lib/systemd/system/podman-auto-update.timer.

Вы можете редактировать расписание таймера, если вам это нужно. По умолчанию обновление будет запускаться каждый понедельник утром. 

Отредактировать модуль таймера  можно через эту команду:

$ sudo systemctl edit podman-auto-update.timer

Вот и всё. Podman теперь позаботится об обновлениях, а также удалении старых образов по расписанию.

Кое-что важное

Автоматизация кажется идеальным решением для обновлений контейнеров, но перед этим нужно учесть некоторые моменты:

  • избегайте использования тега “latest”, поскольку он может включать в себя основные обновления,
  • используйте теги “2” или “2.4”, если они есть у поставщика образов,
  • предварительно протестируйте автообновления,
  • подумайте о создании резервных копий, 
  • обратите внимание, что обновление контейнера не только перезапускает контейнер, но и удаляет старый образ,
  • периодически проверяйте, применяются ли обновления.

Добавить комментарий

Спасибо, что поделились