Комментарии 36
Более развернутый ответ — для того чтобы использовать программу как container engine в kubernetes эта программа должна иметь отдельный сокет для работы по интерфейсу CRI. Чтобы управлять этим сокетом программа должна быть запущена как демон. Потому придется превратить podman обратно в демон, как docker.
Потому существует строгое разделение — podman для работы на пользовательских машинах (где демон только мешает и в большинстве случаев требует привелегий) и CRI-O — легковесный демон для работы с Kubernetes и специально заточенный под него. В итоге обе программы используют общий набор библиотек (libpod, containers/images) для работы.
запрос на создания OCI-совместимой среды исполнения systemd-nspawn.
О чём идет речь, не могли бы вы пояснить? Слова все известные, но смысл ускользает.
Кроме того, общение с runc происходит по стандартному протоколу, который регулируется runtime spec. С недавних пор этот протокол поддерживает systemd-nspawn, а значит его можно использовать вместо run
Если под
впиленимелось ввиду то, что, runc у докера идет в базе — то да, тут все верно
А, верно, я был уверен что привязать другой рантайм в докере труднее, а всё просто, спасибо
Что-то я его в новых убунтах не вижу. Оно RH-specific?
Первый аргумент зачем очень странный. Какая нужда запускать сервисы в общем контейнере?
Ну например, в образ контейнера может быть упаковано коробочное решение. Пользователю же намного проще запустить контейнер, чем запускать три контейнера и настраивать связи между ними.
Когда контейнеры используются разработчиком — то же самое, скачать образ со всем необходимым dev-окружением намного проще, чем скачать три образа и настроить их связи.
А вы что заказывали-то? Коробочное решение или что-то, что вы сможете масштабировать?
Если первое — то сами и виноваты. Если второе — ну так пропишите в договоре-то в какой форме вы решение принимать будете.
а не взламывая свою собственную init-службу.
Извините, это перевод? Что подразумевалось? Или имелось в виду — hacking как "разрабатываю свою init-систему"?
Если контейнеры надо запускать при загрузке системы, то можно просто вставить соответствующие команды Podman в юнит-файл systemd, тот запустит сервис и будет его мониторить. Podman использует стандартную модель ветвления при исполнении (fork-exec). Иначе говоря, контейнерные процессы являются дочерними по отношению к процессу Podman’а, поэтому systemd легко может их мониторить.
Docker использует модель клиент-сервер, и CLI-команды Docker тоже можно размещать прямо в юнит-файле. Однако после того, как Docker-клиент подключается к Docker-демону, он (клиент) становится просто еще одним процессом, обрабатывающим stdin и stdout. В свою очередь, systemd понятия не имеет о связи между Docker-клиентом и контейнером, который работает под управлением Docker-демона, и поэтому в рамках этой модели systemd принципиально не может мониторить сервис.
Каким образом нужно запускать Podman контейнер, чтобы его процессы были видны в systemctl status?
Например, предложенный в официальной документации способ запуска приводит к тому, что systemd видит только сам процесс, запустивший контейнер, а именно "/usr/bin/podman start -a NAME". Точно так же ведёт себя Docker, если его запустить с ключом "-a". Как же systemd может мониторить процессы контейнера, если не видит их?
а зачем? Я проверил — systemd не мониторит, мониторит conmon
root 26061 4.6 0.3 1418228 54512 ? Ssl 11:58 0:00 /usr/bin/podman start -a redis_server
root 26140 0.0 0.0 78012 1892 ? Ssl 11:58 0:00 /usr/bin/conmon --api-version 1 -s -c 6e88c46f8c452e058c1bcfda8a77a9e1c36243d24a3149f16e5db1a7cba2f2a8 -u 6e88c46f8c452e058c1b
999 26153 6.6 0.0 40700 4552 ? Ssl 11:58 0:00 \_ redis-server *:6379
проблема когда ты пытаешься одновременно управлять И системд, И подманом — там реально чего-то не то происходит.
Разница с докером именно в том, что докер стартанул, плюнул запрос в АПИ и клиент умер. Тут же подман бежит ровно столько, сколько нужно — пока сервис живет.
Если под мониторингом подразумевается, что systemd видит процесс «podman start -a», который запускает контейнер, то это ничем не отличается от docker, процесс которого не завершается и systemd его видит, если запустить «docker start -a».
Не совсем понятно какую задачу хотите решить.
Ведь нужно не просто мониторить дерево процессов (хотя conmon с этим худо-бедно вроде справляется), а еще смотреть на хелсчеки контейнера — и как они интегрируются с systemd — открытый вопрос (пока не проверял, но есть подозрение, что пока никак).
Про forking — вижу, сами догадались.
systemd видит только сам процесс, запустивший контейнер, а именно "/usr/bin/podman start -a NAME". Точно так же ведёт себя Docker, если его запустить с ключом "-a".
На первый взгляд — да, но самим контейнером управляет докер-демон — настраивает ему cgroup и другое. docker start -a
здесь только команда демону запустить контейнер.
В случае podman будет создан новый slice, который непосредственно управляет контейнером. Если его остановить то остановится сам контейнер.
Вся магия в Type=forking и PIDFile=xxx.
[Service]
...
ExecStart=/usr/bin/podman start de1e3223b1b888bc02d0962dd6cb5855eb00734061013ffdd3479d225abacdc6
Type=forking
PIDFile=/run/user/1000/overlay-containers/de1e3223b1b888bc02d0962dd6cb5855eb00734061013ffdd3479d225abacdc6/userdata/conmon.pid
...
В данном примере podman запускается без параметра "-a", то есть сам процесс, запустивший контейнер, завершается и systemd видит дерево процессов самого контейнера.
К сожалению, проверить не удалось, так как текущая версия conmon из CentOS 7.7 не создаёт PID файл. Но в любом случае, теперь картинка сложилась.
Кстати, для docker есть wrapper, который позволяет добиться того же результата, но другим способом, через манипуляции с cgroups контейнера github.com/ibuildthecloud/systemd-docker
Тут дело даже не в pid-файлах, а в дереве процессов. В случае podman systemd всегда знает запущен контейнер или остановлен. В случае docker systemd знает только запущен или остановлен клиент, а про контейнер не знает ничего.
Да, «под капотом» Podman и Docker контейнеры запустятся совершенно по разному, но с точки зрения systemd, сервис — это один процесс, который подключен к STDIN, STDOUT и STDERR дескрипторам процесса контейнера. Если podman или docker контейнер завершается с ошибкой, то systemd сервис так же завершится с ошибкой. Если podman или docker контейнер завершается успешно, то systemd сервис так же завершится успешно. В этом смысле поведение systemd сервиса одинаковое.
При использовании github.com/containers/libpod/blob/master/docs/podman-generate-systemd.1.md в случае Podman или github.com/ibuildthecloud/systemd-docker в случае Docker, systemd сервисом будет не один процесс, инициировавший запуск контейнера, а всё дерево процессов самого контейнера.
Для чего это нужно — вопрос отдельный. Мне были интересны технические детали реализации в Podman. Как мы выяснили, там это реализовано через создание процессом conmon PID файла, из которого systemd сам узнаёт PID контейнера и дерево процессов контейнера.
А в каких именно сценариях поведение оказалось одинаковое? Меня вот интересуют вот эти:
Запустите сервис-контейнер, прибейте демон докера (dockerd кажется, но могу ошибаться), после чего попробуйте определить статус сервиса-контейнера через sysctl.
Запустите сервис-контейнер, прибейте демон докера, после чего остановите сервис-контейнер через sysctl. Когда демон докера запустится снова, в каком состоянии сервис-контейнер окажется?
Просто прибейте процесс docker и дождитесь пока systemd попытается его перезапустить.
А если во всех этих случаях поведение окажется одинаковым — предлагаю рассмотреть как будет работать зависимость сервисов друг от друга при падении демона докера, во всех вариантах (контейнер зависит от контейнера, контейнер зависит от простого демона, простой демон зависит от контейнера).
Запустите сервис-контейнер, прибейте демон докера (dockerd кажется, но могу ошибаться), после чего попробуйте определить статус сервиса-контейнера через sysctl.
Можете включить опцию в конфиге демона, которая не убивает контейнеры при смерти docker демона. Но опция достаточно стремная.
--live-restore Enable live restore of docker when containers are still running
https://docs.docker.com/engine/reference/commandline/dockerd/
https://docs.docker.com/config/containers/live-restore/
или я неправильно понял ее?
sysctl
небольшое замечание. Не sysctl, а systemctl
предлагаю рассмотреть как будет работать зависимость сервисов друг от друга при падении демона докера, во всех вариантах
Никак. Потому что ее на уровне докер-демона нет. Он стартует все пачкой, если стоит restart: always
или unless-stopped
Можете включить опцию в конфиге демона, которая не убивает контейнеры при смерти docker демона. Но опция достаточно стремная.
Да нет, без неё поведение docker как раз больше похоже на поведение podman в видимой systemd части.
Никак. Потому что ее на уровне докер-демона нет. Он стартует все пачкой, если стоит restart: always или unless-stopped
Она есть на уровне systemd, и отслеживать зависимости — его прямая обязанность. Вот как раз использовать restart: always или unless-stopped в таких сценариях нельзя никак.
systemd в состоянии отслеживать, что контейнер готов, а не просто запущен, но без танцов с бубном?
Она есть на уровне systemd, и отслеживать зависимости — его прямая обязанность. Вот как раз использовать restart: always или unless-stopped в таких сценариях нельзя никак.
да, я просто уточняю.
Пока самый внятный способ интеграции docker & systemd — это либо через systemd-docker, либо ручками, но с run --rm
, чтобы в случае сбоя контейнер удалился (может быть опасно для данных, но главное компоуз в системди не пихать).
systemd в состоянии отслеживать, что контейнер готов, а не просто запущен, но без танцов с бубном?
Да, если контейнер обучен кидать sd_notify. И как раз именно эта часть и работает только в podman.
На opensuse создает
linux-x1:~ # ls /var/run/containers/storage/btrfs-containers/
6e88c46f8c452e058c1bcfda8a77a9e1c36243d24a3149f16e5db1a7cba2f2a8 b2c87cf4ebb2a2e09ea6de6487360598da76f85f82a61d5f2c497733b6784d0b
linux-x1:~ # zypper if conmon
Retrieving repository 'openSUSE-Tumbleweed-Source' metadata .............................................................................................................................[done]
Building repository 'openSUSE-Tumbleweed-Source' cache ..................................................................................................................................[done]
Loading repository data...
Reading installed packages...
Information for package conmon:
-------------------------------
Repository : openSUSE-Tumbleweed-Oss
Name : conmon
Version : 2.0.1-1.1
Arch : x86_64
Vendor : openSUSE
Installed Size : 72.6 KiB
Installed : Yes (automatically)
Status : up-to-date
Source package : conmon-2.0.1-1.1.src
Summary : An OCI container runtime monitor
Description :
Conmon is a monitoring program and communication tool between a
container manager (like podman or CRI-O) and an OCI runtime (like
runc or crun) for a single container.
Раньше было чёткое разделение на системный контейнер и контейнер приложения. Docker был для контейнеров приложения, LXC/LXD/systemd-machined — для системных контейнеров.
Теперь, получается, можно запускать системные контейнеры через Podman, из Dockerfile, но при этом они несовместимы с Docker? И зачем такое нужно?
Ну, что значит несовместимы?
Есть формат образов, разработанный докером и отданный сообществу — OCI. Он поддерживается разными средами выполнения. По сути — это запакованная файловая система. Можно начать с того, что попросту там может оказаться бинарник не от Вашей платформы (не x86, а arm). Ну, да — может оказаться, что там внутри systemd, который с докером не очень дружит. И что? Сам стандарт не говорит о том, что там внутри. Я уж не говорю про то, что я натыкался на ситуации, когда образ докера не мог быть запущен докером (как правило — собранный более свежей версией типа 18.** на версиях времен мамонта из центоси).
Теперь, получается, можно запускать системные контейнеры через Podman, из Dockerfile, но при этом они несовместимы с Docker?
Учитывая, что podman/buildah предлагают альтернативный подход к сборке… То Ваши Докерфайлы никто не трогает )))
Я себе вижу две стороны медали.
- действительно увеличивается фрагментация образов — есть такие, есть сякие, есть третьи. И со всем этим придется разбираться.
- РедХат хочет свой блекджэк — им не дают покоя лавры Убунту (именно они продвигают lxc/lxd) и Докера (здесь все понятно). Нужно свое решение.
- Разработчикам действительно проще писать systemd юнит файл и запускать его везде одинаково. Тем более, если целевым вариантом поставки решения является не только докер. Как пример продуктов, которые могут быть запущены по-разному — gitlab, postgres, nginx и пр.
Запускаем systemd в контейнере