Kubernetes 1.20 GA: dockershim deprecated официально, начинаем миграцию
Kubernetes 1.20 вышел с официальным warning на dockershim и стабильным kubectl debug. Обновляем кластеры и запускаем миграцию на containerd по плану.
Kubernetes 1.20 GA: dockershim официально deprecated, RuntimeClass stable, kubectl debug stable
Kubernetes 1.20 вышел в GA, и deprecation notice на dockershim теперь не в RC-черновике, а в официальном релизе. Теперь при старте kubelet с --container-runtime=docker в логах появляется предупреждение прямым текстом: dockershim is deprecated, migrate to a CRI-compliant runtime. Это не катастрофа прямо сейчас - dockershim никуда не делся физически. Но сигнал чёткий, и план действий нужен не абстрактный, а конкретный.
Мы ждали GA, чтобы переходить от "наблюдаем и готовимся" к "делаем". В ноябре, когда вышел RC, провели инвентаризацию кластеров под managed-сопровождением и разложили их по категориям. Теперь инвентаризация есть, GA подтвердил курс - запускаем переходы по очереди.
Что нового в 1.20 помимо dockershim
Фокус на deprecation понятен, но релиз принёс и другое полезное.
RuntimeClass дорос до stable. RuntimeClass позволяет назначать поду конкретный container runtime или runtime handler - например, gVisor или kata containers для изоляции отдельных workload-ов при том же кластере. В GA это значит, что API не будет меняться обратно-несовместимым образом. Для большинства кластеров это фоновая новость, но если есть задача запускать часть подов в sandbox-окружении - теперь нормальный инструмент.
kubectl debug вышел из beta в stable. Это команда для отладки запущенного пода с помощью эфемерного контейнера. Добавляет временный контейнер в под без перезапуска, с нужными инструментами - tcpdump, strace, curl, что угодно. Раньше debug без прав на exec в образ приложения был болью: либо пересобирать образ с инструментами, либо городить init container. Теперь:
kubectl debug -it <pod-name> --image=busybox --target=<container-name>
На практике первый же дежурный после обновления использовал это на реальном инциденте - под не стартовал, образ приложения минимальный без шелла. Раньше это был звонок разработчикам и час на пересборку образа. С kubectl debug - эфемерный busybox рядом, смотрим /proc, проверяем сетевые соединения, находим что не хватает переменной окружения. Двадцать минут против часа.
Что с миграцией на containerd
После RC мы уже начали двигаться. Dev и staging-кластеры большей части клиентов переведены на containerd 1.4 - тут ничего неожиданного, схема отработана ещё в августе.
На production-кластерах картина пёстрая. Там принцип один: одна нода, наблюдение, следующая нода. Форсировать не нужно - deprecation warning не означает, что dockershim уберут в 1.21. По публичному roadmap у него ещё несколько циклов. Но и ждать последнего момента незачем: чем дольше ждать, тем больше версия прыжка.
Из нюансов, которые вылезли при переходе на production-нагрузке:
Мониторинг container runtime. Prometheus-экспортёр для Docker (cadvisor в docker-режиме) и для containerd ведут себя немного по-разному в метриках. Не критично, но дашборды Grafana с хардкодными label-фильтрами типа runtime="docker" перестают работать. Нужно пройтись по алертам и дашбордам до перехода ноды, а не после.
Image pull secrets и registry auth. При containerd auth-конфиг для приватных registry прописывается в /etc/containerd/config.toml, а не через docker login. Если были скрипты или ansible-роли, которые делали docker login на нодах - их надо переписать. Kubernetes image pull secrets работают нормально без изменений, это касается только ручного или скриптового pull на ноде.
Systemd cgroup driver - критично. Если пропустить SystemdCgroup = true в конфиге containerd, через какое-то время начнётся drift между cgroup-иерархиями kubelet и runtime. Симптомы неочевидные: поды вроде работают, но OOM killer и throttling ведут себя странно. На dev это незаметно, на production-нагрузке вылезает через несколько дней. Добавили явную проверку этого параметра в чеклист перехода.
Следующий шаг
До конца года планируем закрыть все dev и staging-контуры. Production-кластеры - по согласованию с заказчиками, с окнами обслуживания. Новые кластеры поднимаем только на containerd - dockershim в них не появляется вообще.
Параллельно делаем аудит скриптов на нодах: всё что обращается к Docker socket напрямую нужно переписать до перехода, иначе первый же инцидент будет о скриптах, а не о runtime. Это занимает больше времени, чем сам переход, но без этого порядка не будет.