Гибридный 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:
domainName:
password: <пароль сервисного пользователя>
region:
tenantID:
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 удаляет облачные ВМ.
Если требуется удалить ненужную ВМ вручную, нужно выполнить два шага.
Получаем список машин:
kubectl ‑n d8-cloud‑instance‑manager get machine NAME STATUS AGE cloud‑worker‑af1ba977–7d4d4-lltnf Running 25d
Удаляем ненужную:
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.
Читайте также в нашем блоге: