This article is more than one year old. Older articles may contain outdated content. Check that the information in the page has not become incorrect since its publication.

DIY: создайте собственное облако на Kubernetes (часть 3)

Автор: Andrei Kvapil (Ænix)

Приближаясь к самому интересному этапу, эта статья подробно рассматривает запуск Kubernetes внутри Kubernetes. Особое внимание уделяется таким технологиям, как Kamaji и Cluster API, а также их интеграции с KubeVirt.

В предыдущих статьях мы рассмотрели подготовку Kubernetes на bare metal и как превратить Kubernetes в систему управления виртуальными машинами. Эта статья завершает серию, объясняя, как, используя всё вышеперечисленное, можно построить полноценный управляемый Kubernetes и запускать виртуальные кластеры Kubernetes всего одним щелчком.

Для начала давайте погрузимся в Cluster API.

Cluster API

Cluster API — это расширение для Kubernetes, которое позволяет управлять кластерами Kubernetes как пользовательскими ресурсами внутри другого кластера Kubernetes.

Основная цель Cluster API — предоставить единый интерфейс для описания базовых сущностей кластера Kubernetes и управления их жизненным циклом. Это позволяет автоматизировать процессы создания, обновления и удаления кластеров, упрощая масштабирование и управление инфраструктурой.

В контексте Cluster API есть два термина: управляющий кластер и кластеры арендаторов.

  • Управляющий кластер — это кластер Kubernetes, используемый для развёртывания других кластеров и управления ими. Этот кластер содержит все необходимые компоненты Cluster API и отвечает за описание, создание и обновление кластеров арендаторов. Часто он используется только для этой цели.
  • Кластеры арендаторов — это пользовательские кластеры или кластеры, развёрнутые с помощью Cluster API. Они создаются путём описания соответствующих ресурсов в управляющем кластере. Затем они используются для развёртывания приложений и сервисов конечными пользователями.

Важно понимать, что физически кластеры арендаторов не обязательно должны работать на той же инфраструктуре, что и управляющий кластер; чаще всего они работают в другом месте.

Схема, показывающая взаимодействие управляющего кластера Kubernetes и кластеров арендаторов Kubernetes с помощью Cluster API

Схема, показывающая взаимодействие управляющего кластера Kubernetes и кластеров арендаторов Kubernetes с помощью Cluster API

Для своей работы Cluster API использует концепцию провайдеров — это отдельные контроллеры, отвечающие за конкретные компоненты создаваемого кластера. В Cluster API есть несколько типов провайдеров. Основные из них:

  • Infrastructure Provider — отвечает за предоставление вычислительной инфраструктуры, такой как виртуальные машины или физические серверы.
  • Control Plane Provider — предоставляет control plane Kubernetes, а именно компоненты kube-apiserver, kube-scheduler и kube-controller-manager.
  • Bootstrap Provider — используется для генерации конфигурации cloud-init для создаваемых виртуальных машин и серверов.

Для начала вам потребуется установить сам Cluster API и по одному провайдеру каждого типа. Полный список поддерживаемых провайдеров можно найти в документации проекта.

Для установки можно использовать утилиту clusterctl или Cluster API Operator как более декларативный метод.

Выбор провайдеров

Провайдер инфраструктуры

Для запуска кластеров Kubernetes с помощью KubeVirt необходимо установить KubeVirt Infrastructure Provider. Он позволяет развёртывать виртуальные машины для рабочих узлов в том же управляющем кластере, где работает Cluster API.

Провайдер control plane

Проект Kamaji предлагает готовое решение для запуска control plane Kubernetes для кластеров арендаторов в виде контейнеров внутри управляющего кластера. Такой подход имеет несколько существенных преимуществ:

  • Экономичность: запуск control plane в контейнерах избавляет от необходимости использовать отдельные узлы control plane для каждого кластера, тем самым значительно снижая затраты на инфраструктуру.
  • Стабильность: упрощение архитектуры за счёт устранения сложных многоуровневых схем развёртывания. Вместо последовательного запуска виртуальной машины и последующей установки в ней etcd и компонентов Kubernetes используется простой control plane, который развёртывается и работает как обычное приложение внутри Kubernetes и управляется оператором.
  • Безопасность: control plane кластера скрыт от конечного пользователя, что снижает вероятность компрометации его компонентов, а также исключает доступ пользователя к хранилищу сертификатов кластера. Такой подход к организации невидимого для пользователя control plane часто используется облачными провайдерами.

Bootstrap-провайдер

Kubeadm в качестве Bootstrap Provider — стандартный метод подготовки кластеров в Cluster API. Этот провайдер разрабатывается как часть самого Cluster API. Ему требуется только подготовленный образ системы с установленными kubelet и kubeadm, и он позволяет генерировать конфигурации в форматах cloud-init и ignition.

Стоит отметить, что Talos Linux также поддерживает провижининг через Cluster API и имеет провайдеры для этого. Хотя в предыдущих статьях обсуждалось использование Talos Linux для настройки управляющего кластера на bare-metal-узлах, для провижининга кластеров арендаторов подход Kamaji+Kubeadm имеет больше преимуществ. Он упрощает развёртывание control plane Kubernetes в контейнерах, тем самым устраняя необходимость в отдельных виртуальных машинах для экземпляров control plane. Это упрощает управление и снижает затраты.

Как это работает

Основной объект в Cluster API — ресурс Cluster, который выступает родителем для всех остальных. Обычно этот ресурс ссылается на два других: ресурс, описывающий control plane, и ресурс, описывающий инфраструктуру, каждый из которых управляется отдельным провайдером.

В отличие от Cluster, эти два ресурса не стандартизированы, и их kind зависит от конкретного используемого провайдера:

Схема, показывающая связь ресурса Cluster с ресурсами, на которые он ссылается, в Cluster API

Схема, показывающая связь ресурса Cluster с ресурсами, на которые он ссылается, в Cluster API

В Cluster API также есть ресурс с именем MachineDeployment, который описывает группу узлов — будь то физические серверы или виртуальные машины. Этот ресурс работает аналогично стандартным ресурсам Kubernetes, таким как Deployment, ReplicaSet и Pod, предоставляя механизм для декларативного описания группы узлов и автоматического масштабирования.

Другими словами, ресурс MachineDeployment позволяет декларативно описывать узлы для вашего кластера, автоматизируя их создание, удаление и обновление в соответствии с заданными параметрами и запрошенным количеством реплик.

Схема, показывающая связь ресурса Cluster с его дочерними ресурсами в Cluster API

Схема, показывающая связь ресурса MachineDeployment с его дочерними ресурсами в Cluster API

Для создания машин MachineDeployment ссылается на шаблон для генерации самой машины и шаблон для генерации её конфигурации cloud-init:

Схема, показывающая связь ресурса Cluster с ресурсами, на которые он ссылается, в Cluster API

Схема, показывающая связь ресурса MachineDeployment с ресурсами, на которые он ссылается, в Cluster API

Чтобы развернуть новый кластер Kubernetes с помощью Cluster API, вам потребуется подготовить следующий набор ресурсов:

  • Общий ресурс Cluster
  • Ресурс KamajiControlPlane, отвечающий за control plane, управляемый Kamaji
  • Ресурс KubevirtCluster, описывающий конфигурацию кластера в KubeVirt
  • Ресурс KubevirtMachineTemplate, отвечающий за шаблон виртуальной машины
  • Ресурс KubeadmConfigTemplate, отвечающий за генерацию токенов и cloud-init
  • Как минимум один MachineDeployment для создания рабочих узлов

Доработка кластера

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

На этом этапе у вас уже есть готовый кластер Kubernetes арендатора, но пока он не содержит ничего, кроме API, рабочих узлов и нескольких основных плагинов, которые стандартно входят в установку любого кластера Kubernetes: kube-proxy и CoreDNS. Для полной интеграции вам потребуется установить ещё несколько компонентов:

Для установки дополнительных компонентов можно использовать отдельный Cluster API Add-on Provider for Helm или тот же FluxCD, который обсуждался в предыдущих статьях.

При создании ресурсов в FluxCD можно указать целевой кластер, сославшись на kubeconfig, сгенерированный Cluster API. Тогда установка будет выполнена непосредственно в него. Таким образом, FluxCD становится универсальным инструментом для управления ресурсами как в управляющем кластере, так и в пользовательских кластерах арендаторов.

Схема, показывающая механизм работы fluxcd, который может устанавливать компоненты как в управляющих кластерах Kubernetes, так и в кластерах арендаторов

Схема, показывающая механизм работы fluxcd, который может устанавливать компоненты как в управляющих кластерах Kubernetes, так и в кластерах арендаторов

О каких компонентах идёт речь? В общем случае набор включает следующее:

CNI-плагин

Для обеспечения связи между подами в кластере Kubernetes арендатора необходимо развернуть CNI-плагин. Этот плагин создаёт виртуальную сеть, которая позволяет подам взаимодействовать друг с другом, и традиционно развёртывается как Daemonset на рабочих узлах кластера. Вы можете выбрать и установить любой CNI-плагин, который сочтёте подходящим.

Схема, показывающая CNI-плагин, установленный внутри кластера Kubernetes арендатора, на схеме вложенных кластеров Kubernetes

Схема, показывающая CNI-плагин, установленный внутри кластера Kubernetes арендатора, на схеме вложенных кластеров Kubernetes

Cloud Controller Manager

Основная задача Cloud Controller Manager (CCM) — интегрировать Kubernetes с облачной инфраструктурой провайдера (в вашем случае это управляющий кластер Kubernetes, в котором происходит провижининг всех рабочих узлов Kubernetes арендаторов). Вот некоторые задачи, которые он выполняет:

  1. При создании сервиса типа LoadBalancer CCM инициирует процесс создания облачного балансировщика нагрузки, который направляет трафик в ваш кластер Kubernetes.
  2. Если узел удаляется из облачной инфраструктуры, CCM обеспечивает его удаление и из вашего кластера, поддерживая актуальное состояние кластера.
  3. При использовании CCM узлы добавляются в кластер со специальным taint node.cloudprovider.kubernetes.io/uninitialized, что при необходимости позволяет обрабатывать дополнительную бизнес-логику. После успешной инициализации этот taint удаляется с узла.

В зависимости от облачного провайдера CCM может работать как внутри, так и снаружи кластера арендатора.

KubeVirt Cloud Provider предназначен для установки во внешнем родительском управляющем кластере. Таким образом, создание сервисов типа LoadBalancer в кластере арендатора инициирует создание сервисов LoadBalancer в родительском кластере, которые направляют трафик в кластер арендатора.

Схема, показывающая Cloud Controller Manager, установленный за пределами кластера Kubernetes арендатора, на схеме вложенных кластеров Kubernetes, и сопоставление управляемых им сервисов из родительского в дочерний кластер Kubernetes

Схема, показывающая Cloud Controller Manager, установленный за пределами кластера Kubernetes арендатора, на схеме вложенных кластеров Kubernetes, и сопоставление управляемых им сервисов из родительского в дочерний кластер Kubernetes

CSI-драйвер

Container Storage Interface (CSI) разделён на две основные части для взаимодействия с хранилищем в Kubernetes:

  • csi-controller: этот компонент отвечает за взаимодействие с API облачного провайдера для создания, удаления, подключения, отключения и изменения размера томов.
  • csi-node: этот компонент работает на каждом узле и обеспечивает монтирование томов к подам по запросу kubelet.

В контексте использования KubeVirt CSI Driver появляется уникальная возможность. Поскольку виртуальные машины в KubeVirt работают внутри управляющего кластера Kubernetes, где доступен полноценный API Kubernetes, это открывает путь к запуску csi-controller за пределами кластера арендатора пользователя. Такой подход популярен в сообществе KubeVirt и предлагает несколько ключевых преимуществ:

  • Безопасность: этот метод скрывает внутренний облачный API от конечного пользователя, предоставляя доступ к ресурсам исключительно через интерфейс Kubernetes. Тем самым снижается риск прямого доступа к управляющему кластеру из пользовательских кластеров.
  • Простота и удобство: пользователям не нужно управлять дополнительными контроллерами в своих кластерах, что упрощает архитектуру и снижает нагрузку на управление.

Однако CSI-node обязательно должен работать внутри кластера арендатора, так как он напрямую взаимодействует с kubelet на каждом узле. Этот компонент отвечает за монтирование и размонтирование томов в поды, что требует тесной интеграции с процессами, происходящими непосредственно на узлах кластера.

KubeVirt CSI Driver действует как прокси для заказа томов. Когда внутри кластера арендатора создаётся PVC, PVC создаётся и в управляющем кластере, а затем созданный PV подключается к виртуальной машине.

Схема, показывающая компоненты CSI-плагина, установленные как внутри, так и снаружи кластера Kubernetes арендатора, на схеме вложенных кластеров Kubernetes, и сопоставление управляемых им постоянных томов из родительского в дочерний кластер Kubernetes

Схема, показывающая компоненты CSI-плагина, установленные как внутри, так и снаружи кластера Kubernetes арендатора, на схеме вложенных кластеров Kubernetes, и сопоставление управляемых им постоянных томов из родительского в дочерний кластер Kubernetes

Cluster Autoscaler

Cluster Autoscaler — это универсальный компонент, который может работать с различными облачными API, и его интеграция с Cluster API — лишь одна из доступных функций. Для правильной настройки ему требуется доступ к двум кластерам: кластеру арендатора — для отслеживания подов и определения необходимости добавления новых узлов, и управляющему кластеру Kubernetes (management Kubernetes cluster), где он взаимодействует с ресурсом MachineDeployment и регулирует количество реплик.

Хотя Cluster Autoscaler обычно работает внутри кластера Kubernetes арендатора, в данной ситуации предлагается установить его снаружи по тем же причинам, что описаны ранее. Такой подход проще в обслуживании и безопаснее, так как он не даёт пользователям кластеров арендаторов получить доступ к управляющему API управляющего кластера.

Схема, показывающая Cloud Controller Manager, установленный за пределами кластера Kubernetes арендатора, на схеме вложенных кластеров Kubernetes

Схема, показывающая Cluster Autoscaler, установленный за пределами кластера Kubernetes арендатора, на схеме вложенных кластеров Kubernetes

Konnectivity

Есть ещё один дополнительный компонент, который я хотел бы упомянуть, — Konnectivity. Скорее всего, он понадобится вам позже, чтобы заставить работать вебхуки и слой агрегации API в вашем кластере Kubernetes арендатора. Эта тема подробно рассмотрена в одной из моих предыдущих статей.

В отличие от представленных выше компонентов, Kamaji позволяет легко включить Konnectivity и управлять им как одним из основных компонентов вашего кластера арендатора, наряду с kube-proxy и CoreDNS.

Заключение

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

В дальнейшем вы можете задуматься о сборе метрик и логов с ваших кластеров арендаторов, но это выходит за рамки данной статьи.

Разумеется, все компоненты, необходимые для развёртывания кластера Kubernetes, можно упаковать в единый Helm-чарт и развернуть как единое приложение. Именно так мы организуем развёртывание управляемых кластеров Kubernetes одним нажатием кнопки на нашей открытой PaaS-платформе Cozystack, где вы можете бесплатно попробовать все технологии, описанные в статье.


Первоначально опубликовано на https://kubernetes.io 5 апреля 2024 года.