Как стать автором
Обновить
VK
Технологии, которые объединяют

Как запускать поды как сервисы systemd в Podman

Время на прочтение7 мин
Количество просмотров6.6K
Автор оригинала: Valentin Rothberg


Расширять традиционные практики администрирования Linux с помощью контейнеров — естественный путь развития. Podman без проблем интегрируется в Linux, но поддержка systemd — краеугольный камень этой интеграции. Команда VK Cloud Solutions перевела статью о том, как она работает.

Использование systemd и контейнеров


В Linux система systemd init часто используется для управления локальными службами: веб-серверами, сетевыми демонами и всеми их взаимозависимостями. 

Есть два распространенных сценария совместного использования systemd и контейнеров:

Запуск systemd внутри контейнера. Как объясняет Дэн Уолш, сделать это с помощью Podman максимально просто: он автоматически настраивает в контейнере несколько mounts, и все — systemd готов к работе. Хотя это относительно незаметная функция Podman, ее появление стало огромным шагом вперед для запуска контейнеризированных рабочих нагрузок.

Раньше другие контейнерные инструменты не поддерживали systemd. Пользователям приходилось писать свои init-скрипты, а это возможный источник ошибок и дополнительная нагрузка на службы поддержки поставщиков ПО. Podman решает все эти проблемы. С помощью systemd можно устанавливать и запускать приложения в контейнерах, как и с помощью других инструментов. А поставщикам ПО не нужно разбираться с init-скриптами, «вышедшими из-под пера» пользователей.

Использование systemd для запуска и работы контейнеризированных приложений. systemd запускает контейнеризированное приложение и управляет им на протяжении его жизненного цикла. C Podman это делается проще с помощью команды podman generate systemd, которая генерирует юнит-файл systemd для конкретного контейнера или пода. Такое генерирование поддерживается в Podman начиная с версии 1.7. Со временем наша команда доработала функцию и создала юнит-файлы systemd, которые могут работать на других машинах, наподобие использования Kubernetes YAML или файла Compose. Тесная интеграция с systemd положила начало автообновлениям и простым откатам, реализованным начиная с версии Podman 3.4.

Хотя в блогах можно найти множество статей о генерировании юнитов systemd для контейнеров, практически ничего не написано об их генерировании для подов. Но прежде чем углубиться в детали хочу напомнить, что такое под.

Что такое под


Под состоит из нескольких частей, и, думаю, Брент Боде лучше всех все объяснил на рисунке ниже:



Под состоит из одного или более контейнеров. У группы есть общие контрольные группы (cgroups) и конкретные пространства имен, такие как пространство PID, сети и IPC. Благодаря общим cgroups для всех контейнеров действуют одни и те же ограничения ресурсов. Общие пространства имен упрощают коммуникацию контейнеров друг с другом, например, через localhost или взаимодействие процессов.

Есть и специальный infra-контейнер. Его основная задача — держать открытыми конкретные ресурсы, связанные с подом, например, порты, пространства имен или cgroups. Infra-контейнер — это верхнеуровневый контейнер пода, он создается раньше других контейнеров и уничтожается последним. Infra-контейнер используют при генерировании юнитов systemd для пода, так что не забывайте: этот контейнер работает на протяжении всей жизни пода. Это также означает, что без infra-контейнера (такого как --infra=false) нельзя генерировать юниты systemd для подов.

И еще один немаловажный момент: для каждого контейнера выполняется по одному процессу conmon — это сокращение от container monitor, что точно выражает главную функцию этого процесса. Он также пересылает логи и выполняет чистку после завершения работы контейнера. Процесс conmon запускается до контейнера и дает среде его исполнения (например, runc или crun) указание создать и запустить контейнер. Его работу можно завершить с помощью кода завершения контейнера, что позволяет использовать его как основной процесс службы systemd.

Генерирование юнитов systemd для пода


Podman генерирует только один системный юнит для контейнера. После установки для запуска, остановки и проверки службы можно использовать systemctl. Основной PID каждого юнита — это процесс conmon контейнера. Таким образом, systemd может читать код завершения работы контейнера и действовать в соответствии с настроенной политикой перезапуска. Узнать больше о юнитах можно из статей Запуск контейнеров в Podman и службы systemd в общем доступе и Улучшения systemd в Podman 2.0.

Генерирование юнитов для пода очень похоже на запуск контейнера. У каждого контейнера в поде есть выделенный юнит systemd, а каждый юнит зависит от основного юнита systemd пода. Можно и дальше использовать systemctl для запуска, остановки и проверки основной службы пода; systemd возьмет на себя (пере)запуск и остановку служб контейнеров вместе с основной службой.

В этом примере создается под с двумя контейнерами и генерируются юнит-файлы для пода, которые потом устанавливаются для текущего пользователя:

$ podman pod create --name=my-pod
635bcc5bb5aa0a45af4c2f5a508ebd6a02b93e69324197a06d02a12873b6d1f7

$ podman create --pod=my-pod --name=container-a -t centos top
c04be9c4ac1c93473499571f3c2ad74deb3e0c14f4f00e89c7be3643368daf0e

$ podman create --pod=my-pod --name=container-b -t centos top
b42314b2deff99f5877e76058ac315b97cfb8dc40ed02f9b1b87f21a0cf2fbff

$ cd $HOME/.config/systemd/user

$ podman generate systemd --new --files --name my-pod
/home/vrothberg/.config/systemd/user/pod-my-pod.service
/home/vrothberg/.config/systemd/user/container-container-b.service
/home/vrothberg/.config/systemd/user/container-container-a.service

Как и ожидалось, Podman создал три файла .service, по одному для каждого контейнера плюс один верхнеуровневый для пода. В приложении в конце статьи приведено содержание юнит-файлов целиком. Юниты, генерируемые для двух контейнеров, выглядят как стандартные юниты контейнеров плюс следующие зависимости systemd:

  • BindsTo=pod-my-pod.service: юнит контейнера «привязан» к юниту пода. Если остановить юнит пода, этот юнит тоже остановится.
  • After=pod-my-pod.service: юнит контейнера запускается после юнита пода.

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

Это все, что нужно знать о генерировании юнитов systemd для подов в Podman.

Перезагрузив systemd через systemctl --user daemon-reload, можно запускать и останавливать pod.service на свое усмотрение. Взгляните:

# Reload the daemon
$ systemctl --user daemon-reload

# Start the pod service and make sure the service is running
$ systemctl --user start pod-my-pod.service

$ systemctl --user is-active pod-my-pod.service
active

# Make sure the pod and its containers are running
$ podman pod ps
POD ID    	NAME    	STATUS  	CREATED    	INFRA ID  	# OF CONTAINERS
6dd1090d4ca6  my-pod  	Running 	2 minutes ago  85f760a5cfe5  3
user $ podman container ps
CONTAINER ID  IMAGE                                	COMMAND 	CREATED    	STATUS        	PORTS   	NAMES
85f760a5cfe5  localhost/podman-pause:4.0.2-1646319369          	5 minutes ago  Up 5 minutes ago          	6dd1090d4ca6-infra
44a7e60b9563  quay.io/centos/centos:latest         	top     	5 minutes ago  Up 5 minutes ago          	container-b
31f24bdff747  quay.io/centos/centos:latest         	top     	5 minutes ago  Up 5 minutes ago          	container-a 

Отлично, все работает как надо. Можно использовать systemctl для запуска служб — Podman выводит список подов и их служб корректно. Заодно покажу вам, как останавливать службу пода:

# Stop the pod service
$ systemctl --user stop pod-my-pod.service

# Make sure the pod and its containers are removed
$ podman pod ps -q

$ podman container ps -q

# Make sure the services are inactive
$ systemctl --user is-active pod-my-pod.service container-container-a.service container-container-b.service
inactive
inactive
inactive

качать

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

Приложение


Podman генерирует следующие юнит-файлы для пода и двух контейнеров.

pod-my-pod.service
Description=Podman pod-my-pod.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=
Requires=container-container-a.service container-container-b.service
Before=container-container-a.service container-container-b.service

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/pod-my-pod.pid %t/pod-my-pod.pod-id
ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-my-pod.pid --pod-id-file %t/pod-my-pod.pod-id --name=my-pod --replace
ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-my-pod.pod-id
ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-my-pod.pod-id -t 10
ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-my-pod.pod-id
PIDFile=%t/pod-my-pod.pid
Type=forking

[Install]
WantedBy=default.target
container-container-a.service
[Unit]
Description=Podman container-container-a.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers
BindsTo=pod-my-pod.service
After=pod-my-pod.service

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run --cidfile=%t/%n.ctr-id --cgroups=no-conmon --rm --pod-id-file %t/pod-my-pod.pod-id --sdnotify=conmon -d --replace --name=container-a -t centos top
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all

[Install]
WantedBy=default.target
container-container-b.service
[Unit]
Description=Podman container-container-b.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers
BindsTo=pod-my-pod.service
After=pod-my-pod.service

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run --cidfile=%t/%n.ctr-id --cgroups=no-conmon --rm --pod-id-file %t/pod-my-pod.pod-id --sdnotify=conmon -d --replace --name=container-b -t centos top
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all

[Install]
WantedBy=default.target

Kubernetes aaS от VK Cloud Solutions можно попробовать бесплатно. Мы начисляем пользователям при регистрации 3 000 бонусных рублей и будем рады, если вы попробуете сервис и дадите обратную связь.

Что почитать по теме:

Теги:
Хабы:
Всего голосов 18: ↑18 и ↓0+18
Комментарии1

Публикации

Информация

Сайт
team.vk.company
Дата регистрации
Дата основания
Численность
свыше 10 000 человек
Местоположение
Россия
Представитель
Руслан Дзасохов