Как стать автором
Обновить
VK
Технологии, которые объединяют

От Black box к White box: как мы реализовали управление ресурсами кластеров Kubernetes

Время на прочтение7 мин
Количество просмотров3.9K


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

Меня зовут Алексей Волков, я продакт-менеджер Kubernetes aaS и Backup, VK Cloud. В этой статье я расскажу, как мы реализовали управление ресурсами кластера в сервисе Kubernetes, какой стек и почему выбрали, а также сколько ресурсов на это ушло.

Суть проблемы


Ключевым компонентом управления кластером, который позволяет просматривать, редактировать и получать информацию о ресурсах в нем, являются манифесты. Но в зависимости от выбранных параметров конфигурации сетевой доступности кластера могут быть разными, в том числе без прямого доступа к ресурсам извне (через белый IP из публичных сетей). В ряде случаев это создает ограничения: например, для мониторинга ресурсов и их визуализации в панели управления облачного провайдера нужно постоянное транслирование данных из кластера наружу. Например, раньше в VK Cloud не была реализована подобная функциональность, и пользователи в панели управления облаком могли видеть только IP, сущность кластера и виртуалки под ним. При таком сценарии ресурсы внутри кластера оставались для пользователя в Black box: из интерфейса облака о них ничего не известно, а для получения любой информации надо идти непосредственно в кластер. Это проблематично, если таких кластеров десятки.

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

Реализация управления ресурсами кластера


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

  1. Пользователь — в нашем случае конечный пользователь или API панели управления облака.
  2. Кластер-HTTP — сущность, которая содержит запрос от интерфейса платформы к бэкенду.
  3. RabbitMQ — брокер очередей, который отвечает за маршрутизацию запросов от роутера к подписчику, реализует протокол AMQP.
  4. Агент — сущность, которая развернута на каждой виртуальной машине кластера и нужна для выполнения сервисных операций с кластером: обновления, обслуживания, поддержки, мониторинга и других. За агентом есть сам API Kubernetes, который вызывается локально в ноде. Передача сообщений от агента к подписчику реализована через фреймворк gRPC.
  5. Magnum-rapid — сущность, которая реализует основную функциональность бэкенда и обеспечивает взаимодействие агента, пользователя и брокера очередей RabbitMQ.
  6. Роутер — сущность внутри Magnum-rapid, которая отвечает за прием сообщений от пользователя, передачу их к брокеру очередей RabbitMQ и пересылку сообщений в обратном направлении.
  7. Подписчик — сущность внутри Magnum-rapid, которая отвечает за прием сообщений от брокера очередей RabbitMQ, пересылку их к агентам на нодах и отправку сообщений в обратном направлении.



Алгоритм работы решения:

  1. Пользователь отправляет на хост облака API-запрос, чтобы получить информацию о кластере и его ресурсах. Запрос обязательно содержит идентификатор нужного кластера. Для передачи используется протокол HTTP. 
  2. На виртуальных машинах на кластерах запускаются компоненты Kubernetes и наш агент, который нужен для реализации системных функций и передачи данных о кластерах. Соединение инициирует именно агент. Это позволяет нам работать из закрытых контуров, когда мы не знаем, где вообще агент находится. Агент инициирует установление связи своим первичным коннектом и готов через этот двусторонний коннект получать сообщения. За агентом есть сам API Kubernetes, который вызывается локально в ноде. 
  3. Роутер получает запрос в API Kubernetes и идентификатор кластера, после чего отправляет его в RabbitMQ. Также роутер выполняет массив подготовительной работы. Например, конвертирует HTTP в gRPC и обратно, стерилизует сообщения и форматирует их.
  4. RabbitMQ создает очередь к подписчику с идентификатором кластера и передает в нее сообщение, которое конвертируется в запрос к нужному кластеру.
  5. Подписчик, который реализует gRPC-сервер, через gRPC держит соединение с агентом, отправляет к нему запрос, получает ответ и отправляет его обратно к RabbitMQ. 
  6. Цикл повторяется в обратном порядке.

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

Стоит отметить, что Magnum-rapid также обеспечивает валидацию, авторизацию и агрегацию данных и обеспечивает поддержание и мониторинг соединений со всеми подключенными агентами. Именно через него реализуется функциональность управления ресурсами. 

Фактически мы смогли реализовать упрощенную схему без сложных манипуляций и запроса kubeconfig. Это стало возможным, потому что в Kubernetes от VK Cloud внедрена SSO (single sign-on, система единого входа) — благодаря этому пользователь полагается на механизмы авторизации и распределения прав облака. Сам механизм авторизации становится гораздо прозрачнее: пользователь, как и раньше, авторизуется сначала в личном кабинете, а дальше использует авторизующие хедеры, которые мы доносим прямо до кластера, не влияя на процесс.

Стек решений: аргументация выбора


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

В первом случае (с выбором фреймворка) все было просто: мы уже использовали gRPC для получения от агентов системных данных о кластерах, и это решение нас полностью устраивало. Кроме того, gRPC легко справляется с большими сообщениями и многопоточной обработкой операции. В качестве альтернативы gRPC можно было рассматривать WebSocket, но для нашего кейса он не подходит: из-за проблем с HTTP-стеком он плохо справляется с мультиплексированием сообщений, что для нас критично.

При выборе брокера очередей или способа маршрутизации сообщений мы рассматривали несколько вариантов:

  • RabbitMQ,
  • Redis,
  • прямые коннекты между инстансами Magnum-rapid.

Redis Server хорошо известен как распределенный кэш. Но он не адаптирован для нашей задачи: нам нужно фильтровать много сообщений. Поэтому пришлось бы дополнительно делать синхронизацию.

Вариант с прямыми соединениями роутера и подписчика хорош и позволяет сократить Latency с помощью уменьшения цепочки передачи сообщений. Но реализовать прямое подключение сложно: надо научить все инстансы Magnum-rapid знать друг о друге, придумать протокол обмена информацией об агентах.

RabbitMQ оказался лучшим из вариантов. Во-первых, он хорошо реализовывает маршрутизацию с помощью функциональности очередей и гарантирует доставку сообщений нужному подписчику. Это упрощает работу всей цепочки: маршрутизация сводится к тому, что нам нужно положить запрос пользователя с нужным идентификатором кластера в нужную очередь. Кроме того, RabbitMQ хорошо масштабируется и у нашей команды была экспертиза в работе с ним.

Подводные камни


Реализованная нами схема асинхронная и параллельно-конкурентная: в обе стороны параллельно передается много разных запросов. Особенно это касается подписчика, у которого с двух сторон недетерминированное подключение: с одной стороны у него двунаправленный стрим в агент, с другой — двунаправленный стрим в RabbitMQ. То есть из одной очереди он получает сообщения, а в другую отправляет. И в один поток он посылает сообщения в агент, из другого получает. В результате подписчик должен управлять четырьмя коннекторами, которые работают независимо. Главный недостаток такой реализации в ненадежности соединений: они могут разрываться по разным причинам, в том числе инфраструктурным.

На этапе финальной реализации мы столкнулись с тем, что для официальной библиотеки RabbitMQ, которую мы используем, частые HTTP-соединения и их обрыв допустимы: никакой функциональности по восстановлению соединений нет, да и сделать это сложно из-за их асинхронности. Более того, сам RabbitMQ-сервер плохо реагирует на большое количество подключений и их нестабильность. Оставлять подобную реализацию было недопустимо как со стороны нашего решения, так и со стороны RabbitMQ.

Для решения этой проблемы мы:

  • реализовали механизмы, которые позволяют делать воспроизводимые соединения;
  • создали «обертку», которая автоматически переподключает и в то же время лояльно относится к количеству и частоте подключений к RabbitMQ.

Разработанная нами «обертка» представляет собой библиотечную структуру, которая связывает роутер, подписчика и RabbitMQ — все запросы перед подключением к библиотеке RabbitMQ попадают в «прослойку», поэтому проблем с разрывами и переподключениями нет. 

Сроки внедрения


Благодаря тому, что мы использовали стандартные инструменты и компоненты Kubernetes, на реализацию и внедрение новой функциональности у нас ушло около четырех месяцев. За это время мы:

  • выработали идею добавления фичи управления ресурсами кластера в рамках развития Fully Managed-подхода;
  • провели research решений задачи, выбрали вариант технической реализации — решение с gRPC;
  • выполнили Proof of concept и создали прототип решения;
  • запустили рабочую бету, которую проверили с помощью нагрузочных тестов.

В реализации проекта были задействованы две команды, которые работали параллельно:

  • фронтенды, которые занимались UI и логикой с учетом предоставленной бэкендом спецификации API Kubernetes, который стал основой решения;
  • бэкенды, которые занимались непосредственно разработкой «прослойки» (Reverse proxy) для организации безопасного и стабильного взаимодействия между агентом в кластере и учетной записью пользователя. 

Что получили в итоге


Реализация проекта и добавление новой фичи позволили нам безопасно перейти в мониторинге K8s-кластеров от Black box к White box. Теперь пользователи VK Cloud могут через личный кабинет отслеживать не только кластеры K8s, но и ресурсы в них: не обращаясь напрямую в кластер, видеть, какие нагрузки, где и как выполняются. В перспективе это позволяет расширить возможности управления, чтобы пользователь через панель управления облака мог не только мониторить сущности внутри кластеров, но и управлять ими без сложных и рутинных манипуляций.

Вы прямо сейчас можете воспользоваться Kubernetes от VK Cloud. Для тестирования мы начисляем новым пользователям 3000 бонусных рублей и будем рады вашей обратной связи.

Stay tuned

Присоединяйтесь к телеграм-каналу «Вокруг Kubernetes», чтобы быть в курсе новостей из мира K8s! Регулярные дайджесты, полезные статьи, а также анонсы конференций и вебинаров.
Теги:
Хабы:
Всего голосов 20: ↑20 и ↓0+20
Комментарии0

Публикации

Информация

Сайт
team.vk.company
Дата регистрации
Дата основания
Численность
свыше 10 000 человек
Местоположение
Россия
Представитель
Руслан Дзасохов