Анатомия «Штурвала»: как устроена магия управления кластерами изнутри

Почему одного Cluster API мало для жизненного цикла кластера и какую роль играют Cluster Manager, Init Job и связка cert-manager ↔ вебхуки ↔ CNI.

Приветствую, коллеги. Продолжаем наш технический сериал. В прошлый раз в материале «Как Штурвал управляет облаками» мы разобрали, как Cluster API (CAPI) и его инфраструктурные провайдеры «дергают» виртуализацию, чтобы создать виртуалки и превратить их в узлы. Сегодня перейдем ко второму акту нашего марлезонского балета — тому, что происходит «под капотом» платформы «Штурвал», когда облако уже выдало нам ресурсы.

Разберемся, почему стандартного CAPI недостаточно для жизни и почему без правильной последовательности инициализации ваш кластер так и останется бесполезной грудой запущенных бинарников.

Введение: состояние NotReady и скелет без нервной системы

Представьте: CAPI отработал, виртуалки созданы, на них закрутились пять стандартных бинарников (kubelet, apiserver, controller-manager, etcd и scheduler). Если вы сделаете kubectl get nodes, вы увидите заветную мастер-ноду, но в статусе NotReady.

Проблема в том, что в кластере нет сети. Мы намеренно не ставим CNI через прокси на этапе базового развертывания. CAPI дает нам только «скелет». Роль «доводчика», который натягивает на этот скелет мышцы и нервную систему, берет на себя «Штурвал». И главным дирижером здесь выступает Cluster Manager.

Cluster Manager и Init Job: как обойти лимиты метаданных

Как только базовый куб оживает в минимальном виде, в управляющем кластере (Management Cluster) просыпается Cluster Manager. Его задача — инициировать первую волну деплоя через ресурс ClusterConfig.

Для этого используется механизм Init Job.

  • Что это: это под в новом кластере с образом, содержащим Helm и kubectl.
  • Зачем: почему мы не запихиваем всё в Cloud-init? Потому что Cloud-init не резиновый. У провайдеров вроде Basis или vDirector есть жесткие лимиты на объем метаданных (иногда это жалкие 10 КБ). Попытка пропихнуть туда тяжелые манифесты чартов мониторинга или CRD, которые весят мегабайты, приведет к «метадатному голоданию» — тачка просто не прожует такой конфиг.

Init Job — это наш способ избежать этого ограничения и раскатать базу в цикле. На этом этапе ставятся:

  • Cert-manager (критически важен для выживания);
  • CNI (чтобы ноды наконец ожили);
  • SSC (Shturval Service Config) и NCI (Node Config Interface);
  • SSP (Shturval Service Patch) — для последующей доконфигурации, если параметры изменятся.

Почему Cert-manager — это «голова», или смертельный deadlock

Часто спрашивают: «Зачем нам Cert-manager в первые секунды?». Без него вы попадете в классический архитектурный тупик (deadlock).

Современный Kubernetes завязан на вебхуки (Validating и Mutating). Например, когда вы создаете Ingress или AcmeConfig, API-сервер должен спросить у оператора: «А это вообще валидный конфиг?». Чтобы никто не подменил ответ и не влез в середину процесса (защита от «левых» сервисов, правящих спеки подов на лету), Kubernetes требует строгого TLS-соединения для вебхуков.

Цепочка зависимостей выглядит так:

  • Нет Cert-manager — нет валидных сертификатов для вебхуков.
  • Нет TLS — API-сервер отказывается общаться с мутирующими вебхуками.
  • Без вебхуков ресурсы операторов (включая CNI) будут просто отбиваться как некорректные.

Итог: CNI не поднимется, ноды останутся в NotReady, кластер — «тыква».

CCM и Provider ID: связываем виртуальные сущности с реальностью

Чтобы магия CAPI работала, управляющий кластер должен четко понимать, какая CAPI Machine в его манифестах соответствует реальной Node в клиентском кластере. Связь идет через Provider ID.

Здесь мы идем «ортодоксальным» путем через CCM (Cloud Controller Manager).

  • Безопасность прежде всего: мы запускаем CCM в управляющем кластере (Management Cluster). Почему? Чтобы не хранить облачные креды (пароли от виртуализации) на клиентских нодах. Если злоумышленник «уведет» одну ноду, он не получит доступ к управлению всем вашим облаком.
  • Маппинг: CCM вытаскивает ID из облака и проставляет его в статус ноды. Если этот маппинг ломается или провайдер не выдает ID, CAPI впадает в депрессию и не понимает, жива ли машина.

ClusterInfo и ClusterProfile: контроль и глубокая кастомизация

Чтобы не тонуть в «финализерном аду» и не гадать, что происходит, у нас есть ClusterInfo. Это «единое окно» в потроха: здесь собраны статусы инсталляции, ключи, количество CPU на воркерах и состояние всех системных сервисов. Именно из этого ресурса фронтенд «Штурвала» рисует свои графики.

Для стандартизации парка кластеров используется ClusterProfile. Это наш механизм дефолтов (Defaulting Webhook). Самая мощная фишка здесь — возможность привязать к профилю секреты, содержащие произвольные манифесты.

Используя Match Expressions и лейблы, вы можете сказать: «Для всех кластеров в зоне RU-CENTRAL примени вот эти патчи через SSP и докинь эти секреты». Это позволяет кастомизировать инфраструктуру, не трогая основной код оператора.

Искусство разрушения: как не оставить «призраков» в облаке

Удаление кластера — процесс более тонкий, чем создание. Если просто «грохнуть» Namespace, вы получите ворох бесхозных ресурсов в облаке, за которые продолжите платить.

Алгоритм удаления в «Штурвале» построен на защите от дурака:

  • SSC в manual: останавливаем попытки контроллеров «починить» то, что мы удаляем.
  • Зачистка LoadBalancer: первым делом сносим сервисы с внешними IP, чтобы облако освободило адреса.
  • Игнорирование PV: мы осознанно не трогаем Persistent Volumes. Безопасность данных важнее чистоты. Мы лучше заставим админа удалить диск руками, чем наш скрипт из-за опечатки в политике Retain уничтожит три года продакшена.
  • Триггер удаления CAPI Cluster: только после этого дается команда на снос виртуалок.
  • Garbage Collector и секреты: в Namespace лежат облачные секреты и SSH-ключи, нужные для удаления ресурсов. Если Namespace удалится первым — всё, вы потеряли ключи от квартиры, где лежат деньги (и виртуалки). Наш GC ждет лейбла garbage-collect и финалайзеров CAPI, и только когда облако подтвердит «чисто», он сносит Namespace под ноль.

Заключение: репликаторы и светлое будущее

Платформа растет. В версии 2.14 мы перешли от простого «перекладывания» ресурсов к мультинаправленной репликации. Теперь два менеджмент-кластера могут обмениваться данными встречно, а автоматика через «захват» (capture) сама решает, какой из них сейчас является мастером для конкретного набора клиентских кластеров.

В ближайших планах — окончательно похоронить Init Job ради еще более элегантного процесса запуска. А пока — не стесняйтесь заглядывать в статусы ClusterConfig руками, там много интересного о жизни ваших нод!