Как Штурвал управляет облаками

Как устроен Cluster API и почему в Штурвале выбран именно такой подход

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

Цель этой статьи: вы перестанете видеть в CAPI «чёрный ящик» и поймёте его внутреннюю механику — от контроллеров до конкретных секретов.

Введение: зачем «Штурвалу» этот фреймворк?

Cluster API — это проект Kubernetes SIG Cluster Lifecycle. Его задача — автоматизировать жизненный цикл кластера: создание, обновление (upgrade) и удаление.

Аналогия для понимания. Вспомните Deployment. Вы меняете image в спецификации, и контроллер сам убивает старые поды и поднимает новые. CAPI делает то же самое с узлами. Вы меняете версию Kubernetes в манифесте — и CAPI «перекатывает» ваши виртуальные машины.

Оркестрация контейнеров и оркестрация инфраструктуры: параллель между Deployment/ReplicaSet/Pod и MachineDeployment/MachineSet/Machine

Важный момент: CAPI по умолчанию ставит «голый Кубер» — базовые бинарники (kubelet, kubeadm, etcd). Всё остальное, что делает кластер полноценным (сеть Cilium, системные сервисы «Штурвала»), — это уже наша надстройка над фундаментом CAPI.

Анатомия управления: шесть ключевых контроллеров

Система не монолитна. Она состоит из специализированных провайдеров, каждый из которых отвечает за свой участок «конвейера»:

  1. Core Provider (CAPI) — общие абстракции: Cluster и Machine.
  2. Bootstrap Provider — конфигурация инициализации узла. В «Штурвале» это всегда kubeadm.
  3. Control Plane Provider — «мозги» клиентского кластера: сборка и масштабирование control plane.
  4. Infrastructure Provider — облакозависимая часть (vSphere, OpenStack, Яндекс, CAPSM): обращение к API облака и заказ ВМ.
  5. Autoscaler — без своих CRD; опирается на аннотации в MachineDeployment, работает как под в менеджмент-кластере в неймспейсе воркер-кластера и следит за нагрузкой.
  6. Service Controller «Штурвала» — внутренний компонент, который доставляет пакеты сервисов в уже готовый кластер.

Схема ответственности: Core API, инфраструктура, bootstrap, control plane, сервисы «Штурвала» и autoscaler

В чём профит? Одна и та же логика kubeadm (Bootstrap) подходит и для vSphere, и для bare metal. Меняется только «поставщик» железа.

Иерархия объектов: от шаблона до реальной ноды

Если вы понимаете структуру ресурсов в Kubernetes, здесь будет легко: CAPI копирует привычные паттерны.

Control Plane (аналог StatefulSet)
      |
MachineDeployment (аналог Deployment)
      |
MachineSet (аналог ReplicaSet)
      |
Machine (аналог Pod)

Control plane и worker-узлы: KubeadmControlPlane против MachineDeployment

Важное замечание по версиям. Следите за apiVersion: «Штурвал» перешёл с v1beta1 на v1beta2 (начиная с версий 2.11/2.12). Старые ресурсы будут выпилены — актуализируйте манифесты.

Почему нельзя одна спецификация на все облака? Параметры сред уникальны: в vSphere — сокеты и ядра, в OpenStack — flavor, в Яндекс.Облаке — свои типы ресурсов. «Коровая» Machine ссылается на инфраструктурный объект (например, YandexMachine), где описано «железо».

Общая логика кластера и машины (версия Kubernetes, тайм-ауты) живёт в core-ресурсах; сокеты, ядра и сети провайдера — в объектах инфраструктурного провайдера. На примере vSphere это выглядит так, см. иллюстрацию ниже.

Разделение абстракции: Cluster и Machine против vSphereCluster и vSphereMachine

Магия Bootstrap: как рождается узел

Процесс оживления виртуальной машины — это передача ей контракта на инициализацию.

  1. Цепочка: KubeadmConfigTemplateKubeadmConfigSecret.
  2. Триггер: Bootstrap-провайдер создаёт секрет с cloud-init скриптом. В KubeadmConfig в статусе появляется DataSecretName.
  3. Сигнал для Infra: инфраструктурный провайдер (например, CAPOV — Cluster API для oVirt) не создаст ВМ, пока не увидит этот DataSecretName. Нет секрета — нет машины.

Цепочка bootstrap: от шаблона KubeadmConfig до секрета и инъекции в ОС

Bootstrap-контроллер записывает имя секрета в статус машины; инфраструктурный контроллер ждёт этот сигнал и только после него запускает создание ВМ, см. иллюстрацию ниже.

Синхронизация: запись dataSecretName и триггер создания ВМ у infra-контроллера

Специфика «Штурвала»:

  • Утилита stc. Образы готовятся заранее: в них уже есть containerd, kubelet и etcd — это экономит минуты при старте.
  • Флаг keep-cloud. В облаках используется в stc, чтобы не ломать штатный cloud-init облачного провайдера.
  • Bare Metal (CAPSM). Cloud-init в привычном виде нет: агент stc по SSH кладёт файл на машину и выполняет std node init, который разбирает формат cloud-init и настраивает систему.

Идентификация: ProviderID

Чтобы контроллер в менеджмент-кластере сопоставил Machine с конкретной Node во воркер-кластере, используется ProviderID — уникальный «паспорт» узла.

Связь абстрактной Machine, InfraMachine и узла Kubernetes через ProviderID

В облаках его обычно проставляет CCM (Cloud Controller Manager). В провайдерах вроде CAPSM или vSphere иногда применяют обходной путь: инфраструктурный контроллер сам заходит во воркер-кластер и прописывает ProviderID в спеке ноды. Этот ID пишется один раз. Если он не совпадёт с ожиданиями CAPI, связь ресурсов не сложится, и нода может остаться в NotReady.

Эксплуатация: ремедиация и пауза

CAPI умеет «лечить» кластер через MachineHealthCheck (MHC). Если нода NotReady дольше десяти минут, она может быть удалена и пересоздана.

Байка из жизни (war story). Админ решил добавить памяти виртуалке «на горячую»: зашёл в vSphere, выключил ВМ и правил конфиг. Пока возился, прошло 10 минут. MHC посчитал ноду «протухшей» и удалил её. Админ включает ВМ — а контроллер уже удаляет её и поднимает новую со старыми параметрами памяти.

Главное правило: если лезете в инфру руками или на СХД авария — ставьте кластер на паузу (см. реконсиляция инфраструктуры и признак paused):

kubectl patch cluster <name> --type merge -p '{"spec":{"paused":true}}'

Так блокируются реконсиляция и MHC: контроллеры не будут «чинить» то, что вы сейчас ломаете или восстанавливаете.

Нюанс с etcd. При обновлении control plane CAPI может пробросить port-forward к живому участнику etcd, чтобы корректно вывести узел из состава кластера.

Траблшутинг: методология поиска

Если кластер застрял, не грепайте всё подряд — идите по слоям:

  1. Слой CAPI (capi-system). Статус Machine: при Ready: False смотрите Conditions.
  2. Слой Bootstrap. KubeadmConfig: есть ли DataSecretName? Если нет — Bootstrap не смог сгенерировать конфиг (например, из-за ошибки в сертификатах).
  3. Слой Infra (capv-system, capy-system и др.). Секрет есть, а ВМ нет — смотрите логи инфраструктурного провайдера.

Дополнительно:

  • Совет: фильтруйте логи контроллера по имени конкретной Machine.
  • Deep debug: поднимите уровень логирования (-v=10) — увидите сырые HTTP-ответы API облака (лимиты, несуществующая папка в vSphere и т.п.).

Сверяйте наблюдения по слоям с тем, как контроллеры и ресурсы связаны на схемах выше: так проще понять, на каком звене цепочки «застряли» объекты.

Заключение

Cluster API — мощный фреймворк, который делает управление облаками предсказуемым. Главное — помнить контракт между контроллерами: Bootstrap отдаёт секрет, Infra создаёт машину, ProviderID связывает всё в одну цепочку.

Используйте pause перед работами, не бойтесь заглядывать в Conditions и держите в голове иерархию объектов. Когда понятно, что происходит «под капотом», «Штурвал» в ваших руках становится заметно послушнее.