Гибридный Kubernetes-кластер из bare metal и динамически подключаемых облачных виртуальных машин

от автора

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

Мы решили сделать гибридный кластер Kubernetes на базе существующего bare-metal-кластера, чтобы:

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

  • разворачивать на этих узлах нужные окружения для тестов;

  • сворачивать окружения после выхода изменений в production и отключать узлы.

Для этого мы воспользовались модулем cloud-provider-openstack, который входит в состав Kubernetes-платформы Deckhose. Расскажу, как это работает.

☝️ В статье рассматривается вариант развертывания гибридного кластера в Selectel и OpenStack-облаке, которое предоставляет провайдер. Но сам подход универсален, его можно применять, к примеру, и на собственной инфраструктуре.

Настройка сетевой связности

У нас был bare-metal-кластер Kubernetes, расположенный в Selectel. Узлы в нем находились в разных зонах: SPB-3 и SPB-5. Также некоторые приложения использовали managed PostgreSQL, расположенный в облачной зоне ru-3. Чтобы была возможность дозаказывать узлы в OpenStack-облаке Selectel, нам пришлось настроить сетевое взаимодействие между уже существующими сетями и облачными.

Так выглядит L3VPN-роутер от Selectel, который позволяет связать bare-metal-узлы в зонах SPB-3 (network_SPB-3) и SPB-5 (network_SPB-5) с PostgreSQL (network_ru-3):

Четвёртую сеть — k8s_l3vpn — добавили инженеры Selectel, чтобы связать виртуальные машины (ВМ) в облаке с остальными сетями.

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

Одна из сетей дает ВМ доступ во внешнюю сеть:

Через вторую L3VPN-роутер связывает облачные ВМ с остальными сетями:

Две этих сети объединены отдельным облачным роутером, который подключен к внешней сети:

Затем мы попросили настроить маршрутизацию таким образом, чтобы ВМ, которые заказываются в сети k8s_l3vpn (192.168.200.0/24), получали маршруты вида:

            -   to: 0.0.0.0/0                 via: 192.168.200.1             -   to: 10.13.1.0/24                 via: 192.168.200.252             -   to: 192.168.204.0/24                 via: 192.168.200.252             -   to: 192.168.205.0/24                 via: 192.168.200.252

В результате получилась такая схема: 

  • доступ во внешнюю сеть k8s-external-access реализован через основной шлюз 192.168.200.1;

  • доступ к «серым» подсетям организован через шлюз 192.168.200.252.

На этом подготовительные работы были закончены.

Подготовка и настройка модуля cloud-provider-openstack в Deckhouse

Мы создали сервисного пользователя с доступом к проекту, в котором заказываются ВМ.

Сделать это можно в личном кабинете Selectel: Профиль и настройки → Управление пользователями → Добавить пользователя → Сервисный пользователь. Там нужно указать имя, пароль и выдать права администратора необходимого проекта:

Затем мы создали keypair, чтобы при необходимости подключаться к ВМ по ключу:

openstack keypair create --public-key ~/.ssh/id-rsa.pub --type ssh deckhouse

Также можно загрузить свой образ, с которым будет бутстрапиться новая ВМ с помощью openstack image create.

Чтобы настроить OpenStack CLI под созданного пользователя, мы скачали скрипт в разделе Облачная платформаДоступ, выбрав там нужного пользователя:

И выполнили:

source rc.sh

Для работы с OpenStack мы воспользовались модулем Deckhouse cloud-provider-openstack. Вот его конфигурация:

apiVersion: deckhouse.io/v1alpha1 kind: ModuleConfig metadata:   name: cloud-provider-openstack spec:   enabled: true   settings:     connection:       authURL: <OS_AUTH_URL из rc.sh>       domainName: <OS_PROJECT_DOMAIN_NAME из rc.sh>       password: <пароль сервисного пользователя>       region: <OS_REGION_NAME из rc.sh>       tenantID: <OS_TENANT_ID из rc.sh>       username: <имя сервисного пользователя>     instances:       sshKeyPairName: deckhouse # Имя keypair, созданного ранее.     internalNetworkNames:     - k8s_l3vpn # Имя сети, которая подключена к роутеру L3VPN и в которой будут находиться ВМ.     podNetworkMode: DirectRouting     zones:     - ru-3a   version: 1

Со всеми доступными параметрами модуля можно ознакомиться в разделе документации «OpenStack: настройки».

Сначала мы создали flavor с нужными параметрами:

openstack flavor create c4m8d50 --ram 8192 --disk 50 --vcpus 4 --private

Затем InstanceClass:

apiVersion: deckhouse.io/v1 kind: OpenStackInstanceClass metadata:   name: cloud-worker spec:   flavorName: c4m8d50   imageName: ubuntu-22-04-cloud-amd64 # Берем существующий (openstack image list) или загруженный на шаге ранее.   mainNetwork: k8s_l3vpn

И, наконец, NodeGroup:

apiVersion: deckhouse.io/v1 kind: NodeGroup metadata:   name: cloud-worker spec:   chaos:     mode: Disabled   cloudInstances:     classReference:       kind: OpenStackInstanceClass        name: cloud-worker # Указываем имя InstanceClass, созданного ранее.     maxPerZone: 10 # Максимальное кол-во узлов в зоне.     minPerZone: 1 # Минимальное кол-во узлов в зоне.     zones:     - ru-3a   disruptions:     approvalMode: Automatic   nodeTemplate:     labels:       node-role/cloud-worker: ""     taints:     - effect: NoExecute       key: dedicated       value: cloud-worker   nodeType: CloudEphemeral

Через 2–3 минуты после создания NodeGroup узлы начинают заказываться с учетом параметра minPerZone и добавляться в кластер. За процессом можно следить в панели Selectel:

И в кластере:

~ $ kubectl -n d8-cloud-instance-manager get machine NAME                                STATUS    AGE cloud-worker-af1ba977-7d4d4-lltnf   Running   5d3h

Если при создании возникают ошибки, связанные с недостаточностью прав или некорректным подключением к API, их можно наблюдать в логах контроллера:

~ $ kubectl -n d8-cloud-instance-manager logs -l app=machine-controller-manager -c controller

Когда временные окружения сворачиваются и ресурсы в кластере освобождаются, Cluster Autoscaler удаляет облачные ВМ.

Если требуется удалить ненужную ВМ вручную, нужно выполнить два шага.

  1. Получаем список машин:

 kubectl ‑n d8-cloud‑instance‑manager get machine NAME STATUS AGE cloud‑worker‑af1ba977–7d4d4-lltnf Running 25d
  1. Удаляем ненужную:

 kubectl -n d8-cloud-instance-manager delete machine cloud-worker-af1ba977-7d4d4-lltnf

Заключение

С помощью модуля cloud-provider-openstack, который входит в состав платформы Deckhouse, мы превратили обычный bare-metal-кластер в гибридный. В нем можно создавать различные группы узлов под специфические цели с непостоянной нагрузкой и масштабировать узлы в зависимости от потребностей.

Хотя в статье рассматривается вариант развертывания гибридного кластера в Selectel, связку «Deckhouse + модуль cloud-provider-openstack» можно использовать где угодно, в том числе и на собственной инфраструктуре.

P.S.

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


ссылка на оригинал статьи https://habr.com/ru/company/flant/blog/721268/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *