В продолжение к недавнему релизу CSI-драйвера для Яндекс.Облака мы публикуем ещё один Open Source-проект для этого облака — Cloud Controller Manager. CCM необходим не только для кластера в целом, но и собственно CSI-драйвера. Подробности о его предназначении и некоторые особенности реализации — под катом.

Введение


Зачем это?


Мотивы, побудившие нас к разработке CCM для Яндекс.Облака, полностью совпадают с уже описанными в анонсе CSI-драйвера. Мы обслуживаем множество Kubernetes-кластеров у разных облачных провайдеров, для чего используем единый инструмент. Он реализует многочисленные удобства «в обход» managed-решений этих провайдеров. Да, у нас довольно специфичный случай и потребности, однако созданные из-за них наработки могут пригодиться и другим пользователям.

Что вообще такое CCM?


Как правило, мы подготавливаем окружающую нас среду для кластера извне — например, с помощью Terraform. Но иногда есть необходимость управлять окружающей нас облачной средой из кластера. Такая возможность предусмотрена, и именно её реализует CCM.

В частности, Cloud Controller Manager обеспечивает пять основных типов взаимодействия:

  1. Instances – реализует связь 1:1 между объектом узла в Kubernetes (Node) и виртуальной машиной в облачном провайдере. Для этого мы:
    • заполняем поле spec.providerID в объекте Node. К примеру, для OpenStack CCM это поле имеет следующий формат: openstack:///d58a78bf-21b0-4682-9dc6-2132406d2bb0. Можно видеть имя облачного провайдера и уникальный UUID server’а (виртуальная машина в OpenStack) объекта;
    • дополняем nodeInfo в объекте Node информацией о виртуальной машине. Например, указываем instance type в AWS;
    • проверяем наличие виртуальной машины в облаке. К примеру, если объект Node перешёл в состояние NotReady, можно проверить, существует ли вообще виртуальная машина в облачном провайдере по providerID. Если её нет — удаляем объект Node, который в противном случае остался бы в кластере навечно;
  2. Zones – задаёт failure domain для объекта Node, чтобы планировщик мог выбрать узел для Pod’а согласно регионам и зонам в облачном провайдере;
  3. LoadBalancer – при создании объекта Service с типом LoadBalancer создаёт некий балансировщик, который направит трафик извне к узлам кластера. Например, в Yandex.Cloud можно использовать NetworkLoadBalancer и TargetGroup для этих целей;
  4. Route – строит сеть между узлами, т.к. по требованиям Kubernetes каждый pod должен иметь свой IP-адрес и иметь возможность достучаться до любого другого pod’а. Для этих целей можно использовать оверлейную сеть (VXLAN, GENEVE) или задать таблицу маршрутизации прямо в виртуальной сети облачного провайдера:

  5. Volume – позволяет динамически заказывать PV, используя PVC и SC. Изначально этот функционал являлся частью CCM, но ввиду большой сложности был вынесен в отдельный проект Container Storage Interface (CSI). Про CSI мы не раз писали и, как уже говорилось, даже выпустили CSI-драйвер.

Ранее весь код, взаимодействующий с облаком, лежал в основном Git-репозитории проекта Kubernetes по адресу k8s.io/kubernetes/pkg/cloudprovider/providers, но от этого решили отказаться из-за неудобства работы с большой кодовой базой. Все старые реализации были вынесены в отдельный репозиторий. Для удобства дальнейшей поддержки и разработки все общие компоненты тоже были вынесены в отдельный репозиторий.

Как и в случае с CSI, многие крупные поставщики облачных услуг уже разработали свои CCM для использования облаков в Kubernetes. Если же CCM у поставщика нет, но все необходимые функции доступны через API, то можно реализовать CCM самостоятельно.

Чтобы написать свою реализацию CCM, достаточно реализовать нужные Go-интерфейсы.

И вот что у нас получилось.

Реализация


Как пришли к этому


Разработку (а точнее — даже использование) мы начали с готового(!) CCM для Yandex.Cloud годовой давности.

Однако в этой реализации нам не хватало:

  • аутентификации через JWT IAM-токен;
  • поддержки Service controller’а.

По согласованию с автором (dlisin) в Telegram, мы форкнули yandex-cloud-controller-manager и дописали недостающие функции.

Основные возможности


На текущий момент CCM поддерживает следующие интерфейсы:

  • Instances;
  • Zones;
  • LoadBalancer.

В будущем, когда Yandex.Cloud начнёт работать с продвинутыми возможностями VPC, мы добавим и интерфейс Routes.

LoadBalanacer как главный вызов


Изначально мы пробовали, как у других реализаций CCM, создавать пару из LoadBalancer и TargetGroup для каждого Service с типом LoadBalancer. Однако у Yandex.Cloud обнаружилось одно интересное ограничение: нельзя использовать TargetGroups с пересекающимися Targets (пара SubnetIDIpAddress).



Поэтому внутри созданного CCM запускается контроллер, который при изменении объектов Node собирает информацию обо всех интерфейсах на каждой виртуальной машине, группирует их по принадлежности к определённым NetworkID, создаёт по TargetGroup на NetworkID, а также следит за актуальностью. Впоследствии, при создании объекта Service с типом LoadBalanacer мы просто прикрепляем заранее созданную TargetGroup к новым NetworkLoadBalanacer'ам.

Как начать пользоваться?


CCM поддерживает Kubernetes версии 1.15 и выше. В кластере для его работы требуется, чтобы флаг --cloud-provider=external был установлен в значение true для kube-apiserver, kube-controller-manager, kube-scheduler и всех kubelet’ов.

Все необходимые шаги по самой установке описаны в README. Инсталляция сводится к созданию объектов в Kubernetes из манифестов.

Для использования CCM также понадобится:

  • указать в манифесте идентификатор каталога (folder-id) Яндекс.Облака;
  • сервисный аккаунт для взаимодействия с API Яндекс.Облака. В манифесте Secret необходимо передать авторизованные ключи от сервисного аккаунта. В документации описано, как создать сервисный аккаунт и получить ключи.

Будем рады обратной связи и новым issues, если столкнетесь с какими-то проблемами!

Итоги


Реализованный CCM мы используем в пяти Kubernetes-кластерах на протяжении двух последних недель и планируем расширить их число до 20 в ближайший месяц. Использовать CCM для больших и критических инсталляций K8s в настоящий момент не рекомендуем.

Как и в случае с CSI, будем рады, если разработчики Яндекса возьмут на себя развитие и поддержку этого проекта — мы готовы передать репозиторий по их просьбе, чтобы заниматься более профильными для нас задачами.

P.S.


Читайте также в нашем блоге:

Комментарии (2)