ADG Оставить заявку
Блог DevOps 4 мин чтения

Docker 1.11: containerd и runc как отдельные процессы

Docker 1.11 разбил монолитный демон на containerd, runc и shim. Разбираемся что это дало нашей CI-среде и мониторингу через Zabbix.

Контекст момента

Docker 1.11 разделил рантайм на containerd и runc, приближаясь к стандарту OCI - контейнерный демон перестал быть монолитом

Docker 1.11 вышел в апреле, и обновление прошло у нас тише чем обычно - без видимых поломок, без восклицательных знаков в release notes, которые заставляют притормозить. Но под капотом изменилось кое-что важное: то, что раньше было одним монолитным процессом docker, теперь стало тремя.

Что именно поменялось

До 1.11 Docker-демон делал всё сам: принимал API-запросы, создавал контейнеры, управлял их жизненным циклом, следил за ними. Один pid, одна точка отказа, один лог. В 1.11 эту работу распределили:

  • containerd - долгоживущий демон, который управляет жизненным циклом контейнеров: запуск, остановка, пауза, снятие образов. Работает как отдельный системный процесс.
  • runc - минималистичный инструмент запуска контейнера по спецификации OCI. Стартует, создаёт контейнер и завершается. Никакого фонового процесса.
  • containerd-shim - тонкий процесс-прокладка, который остаётся живым пока живёт контейнер. Через него containerd держит связь с работающим контейнером без того чтобы самому держать открытые файловые дескрипторы каждого процесса.

На практике это означает: теперь ps aux на Docker-хосте показывает не один dockerd, а несколько процессов, и у каждого контейнера есть свой containerd-shim.

Как это проявилось в нашей CI-среде

Обновление на Jenkins-агентах мы откатили один раз - не из-за Docker, а из-за того что скрипт проверки health check-а смотрел на конкретный pid docker и падал с ошибкой когда не находил то что привык видеть. Мелочь, но именно из таких мелочей состоит неожиданный полдень.

После правки стало лучше. Неожиданный плюс: containerd как отдельный процесс дал нам более чистую точку наблюдения. Раньше, когда мы мониторили Docker-демон через Zabbix, весь overhead был свален в один процесс - и было непонятно, это высокое потребление памяти от управляющей логики или от самих контейнеров. Сейчас containerd живёт отдельно, shim-процессы видны поимённо, и картина стала читаемее.

Конкретно у нас Zabbix-агент теперь следит за containerd как за самостоятельным системным сервисом - через стандартный proc-мониторинг, без дополнительных скриптов. Если containerd упал - это сразу alert, даже если dockerd формально ещё жив. Раньше такого разделения не было.

OCI и зачем это вообще нужно

За архитектурным изменением стоит более широкий контекст. Open Container Initiative - это попытка стандартизировать формат контейнеров и рантайм на уровне спецификации, независимой от конкретного вендора. runc - референсная реализация этой спецификации. То, что Docker теперь использует runc внутри, означает что граница между «Docker-контейнером» и «OCI-контейнером» становится тоньше.

Для нас это пока теоретически. Образы остаются теми же, Compose-файлы те же, CI-пайплайн тот же. Но сам факт что рантайм вынесен в отдельный компонент с публичной спецификацией - это другое ощущение от инструмента. Меньше vendor magic внутри.

Что со Swarm и продакшн-кластером

В нашем Swarm-кластере обновление до 1.11 прошло по нодам поочерёдно без остановки приложений. Рестарт dockerd пережили штатно: containerd перехватил управление работающими контейнерами через shim-прослойку, так что сами контейнеры не остановились в момент обновления демона.

Это, кстати, одно из практических следствий новой архитектуры: перезапуск dockerd больше не означает остановку всех контейнеров. Containerd и shim-процессы живут независимо. На это обратили внимание только когда проверяли что происходит с контейнерами при systemctl restart docker - ожидали краткой паузы, получили продолжение работы. Полезное свойство для rolling update самого демона.

Что ещё не трогали

Новая архитектура пока создала один открытый вопрос: логирование. Раньше всё шло через dockerd, теперь часть событий жизненного цикла контейнера проходит через containerd. Наш текущий pipeline сбора логов через Docker API это видит нормально - но насколько полный это охват, пока не проверяли детально. Это следующий пункт в очереди.

В целом 1.11 - это обновление из тех, где нужно потратить час чтобы разобраться что изменилось, и потом оценить что новая картина понятнее старой. Инфраструктура для managed-проектов от этого стала чуть наблюдаемее, что само по себе хорошо.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.