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
Для своей работы 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 API также есть ресурс с именем MachineDeployment, который описывает группу узлов — будь то физические серверы или виртуальные машины. Этот ресурс работает аналогично стандартным ресурсам Kubernetes, таким как Deployment, ReplicaSet и Pod, предоставляя механизм для декларативного описания группы узлов и автоматического масштабирования.
Другими словами, ресурс MachineDeployment позволяет декларативно описывать узлы для вашего кластера, автоматизируя их создание, удаление и обновление в соответствии с заданными параметрами и запрошенным количеством реплик.
Схема, показывающая связь ресурса MachineDeployment с его дочерними ресурсами в Cluster API
Для создания машин MachineDeployment ссылается на шаблон для генерации самой машины и шаблон для генерации её конфигурации cloud-init:
Схема, показывающая связь ресурса 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, так и в кластерах арендаторов
О каких компонентах идёт речь? В общем случае набор включает следующее:
CNI-плагин
Для обеспечения связи между подами в кластере Kubernetes арендатора необходимо развернуть CNI-плагин. Этот плагин создаёт виртуальную сеть, которая позволяет подам взаимодействовать друг с другом, и традиционно развёртывается как Daemonset на рабочих узлах кластера. Вы можете выбрать и установить любой CNI-плагин, который сочтёте подходящим.
Схема, показывающая CNI-плагин, установленный внутри кластера Kubernetes арендатора, на схеме вложенных кластеров Kubernetes
Cloud Controller Manager
Основная задача Cloud Controller Manager (CCM) — интегрировать Kubernetes с облачной инфраструктурой провайдера (в вашем случае это управляющий кластер Kubernetes, в котором происходит провижининг всех рабочих узлов Kubernetes арендаторов). Вот некоторые задачи, которые он выполняет:
- При создании сервиса типа LoadBalancer CCM инициирует процесс создания облачного балансировщика нагрузки, который направляет трафик в ваш кластер Kubernetes.
- Если узел удаляется из облачной инфраструктуры, CCM обеспечивает его удаление и из вашего кластера, поддерживая актуальное состояние кластера.
- При использовании CCM узлы добавляются в кластер со специальным taint
node.cloudprovider.kubernetes.io/uninitialized, что при необходимости позволяет обрабатывать дополнительную бизнес-логику. После успешной инициализации этот taint удаляется с узла.
В зависимости от облачного провайдера CCM может работать как внутри, так и снаружи кластера арендатора.
KubeVirt Cloud Provider предназначен для установки во внешнем родительском управляющем кластере. Таким образом, создание сервисов типа LoadBalancer в кластере арендатора инициирует создание сервисов LoadBalancer в родительском кластере, которые направляют трафик в кластер арендатора.
Схема, показывающая 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
Cluster Autoscaler
Cluster Autoscaler — это универсальный компонент, который может работать с различными облачными API, и его интеграция с Cluster API — лишь одна из доступных функций. Для правильной настройки ему требуется доступ к двум кластерам: кластеру арендатора — для отслеживания подов и определения необходимости добавления новых узлов, и управляющему кластеру Kubernetes (management Kubernetes cluster), где он взаимодействует с ресурсом MachineDeployment и регулирует количество реплик.
Хотя Cluster Autoscaler обычно работает внутри кластера Kubernetes арендатора, в данной ситуации предлагается установить его снаружи по тем же причинам, что описаны ранее. Такой подход проще в обслуживании и безопаснее, так как он не даёт пользователям кластеров арендаторов получить доступ к управляющему API управляющего кластера.
Схема, показывающая Cluster Autoscaler, установленный за пределами кластера Kubernetes арендатора, на схеме вложенных кластеров Kubernetes
Konnectivity
Есть ещё один дополнительный компонент, который я хотел бы упомянуть, — Konnectivity. Скорее всего, он понадобится вам позже, чтобы заставить работать вебхуки и слой агрегации API в вашем кластере Kubernetes арендатора. Эта тема подробно рассмотрена в одной из моих предыдущих статей.
В отличие от представленных выше компонентов, Kamaji позволяет легко включить Konnectivity и управлять им как одним из основных компонентов вашего кластера арендатора, наряду с kube-proxy и CoreDNS.
Заключение
Теперь у вас есть полностью функциональный кластер Kubernetes с возможностью динамического масштабирования, автоматического провижининга томов и балансировщиков нагрузки.
В дальнейшем вы можете задуматься о сборе метрик и логов с ваших кластеров арендаторов, но это выходит за рамки данной статьи.
Разумеется, все компоненты, необходимые для развёртывания кластера Kubernetes, можно упаковать в единый Helm-чарт и развернуть как единое приложение. Именно так мы организуем развёртывание управляемых кластеров Kubernetes одним нажатием кнопки на нашей открытой PaaS-платформе Cozystack, где вы можете бесплатно попробовать все технологии, описанные в статье.
Первоначально опубликовано на https://kubernetes.io 5 апреля 2024 года.