Хабр, привет! Я Максим, технический директор в облаке Амвера и в этой статье я хотел бы поделиться опытом развертывания кластера kubernetes, который под капотом использует OpenStack. В этой статья я хочу пошагово рассказать про путь развертывания, подсветив те места, которые вызвали у меня затруднения.
Про Amvera Cloud
Amvera — это облако для простого деплоя приложений через git push. Встроенный CI/CD, бэкапы и мониторинг позволяют развернуть проект тремя командами в IDE и не думать о настойке инфраструктуры. Amvera проще, чем использование VPS или Kubernetes-кластера. Все проекты мы запускаем в Kubernetes. Данная статья о том, как мы разворачивали кластер для нашей международной зоны доступности в Варшаве.
Подготовка образа
Talos Linux - это операционная система на базе Linux, которая специально была разработана для запуска Kubernetes. Базовый образ содержит минимум сторонних и по факту не нужных куберу сервисов, которые присутствуют в других дистрибутивах Linux. Более того, вся конфигурация узла содержится в специальном файле конфигурации, который мы рассмотрим позже.
Команда разработчиков Talos позаботилась о том, что их ОС может развертываться на разных платформах и подготовила специальный конструктор образа. Чтобы получить образ для OpenStack выполним следующие шаги:
- Hardware Type - выбираем "Cloud Server" 
- Choose Talos Linux Version - версия ОС. На момент развертывания кластера автором, последняя версия была 1.8.3. Всегда лучше выбирать последнюю стабильную версию. 
- Cloud - тут выбираем, в каком облаке будем разворачивать. В моём случае это OpenStack. 
- Machine Architecture - архитектура процессора, на котором будет разворачивается кластер (или конкретный узел). 
- System Extensions - это самый интересный пункт. Базовый Talos не содержит в себе многих привычных модулей ядра, они должны быть добавлены через расширения. Так, если планируется использовать Longhorn, нужно добавить "iscsi-tools" и "util-linux-tools". Нужно заранее подумать о том, что потребуется разворачивать на нодах с данным образом и не забыть включить нужные расширения, иначе можно столкнуться с ошибками при запуске подов. 
- Customization - можно указать дополнительные параметры запуска ядра, но я оставляю это поле пустым. 
- Schematic Ready - мы добрались до страницы, с которой можно загрузить образ, который будет содержать все указанные на этапе 5 расширения. Мой облачный провайдер поддерживает загрузку только raw образов, поэтому я скачивал "Disk Image". 
- Как только образ загрузится, грузим его в OpenStack. 
Создание ВМ для администрирования
Из соображений безопасности и удобства конфигурации будущих узлов с Talos, создадим виртуальную машину, с которой будем настраивать кластер. Я выбрал ВМ с установленной на нее ОС Ubuntu 24.04. ВМ должна быть подключена к той-же сети, в которой ранее создавались порты и иметь внешний IP для доступа по SSH.
Нам потребуется установить две CLI - одну для работы с Openstack, другую для работы с Talos. Для этого выполним простые действия:
apt update
# Opensatck CLI
apt install python3-openstackclient
apt install python3-octaviaclient
# Talos CLI
curl -sL https://talos.dev/install | shТак-же потребуется поставить kubectl.
Создание k8s кластера
Процесс создания узлов с Talos в OpenStack довольно подробно рассмотрено в их документации. Важно отметить, что ваш облачный провайдер должен поддерживать создание сетевого LoadBalancer. В нашем случае ребята из ProCloud, которых мы выбрали для базы иностранной зоны доступности, выдали ранний доступ к этой фиче, которая в скором времени будет доступна всем желающим. Для доступа к консоли OpenStack вам так-же необходимо запросить права доступа у вашего провайдера.
Как могут выглядеть креды доступа в OpenStack
export OS_AUTH_URL=https://some.url
export OS_PROJECT_NAME="my-project"
export OS_USER_DOMAIN_ID="default"
export OS_PROJECT_DOMAIN_ID="default"
export OS_USERNAME="username"
export OS_PASSWORD="password"
export OS_REGION_NAME="region"
export OS_INTERFACE=public
export OS_IDENTITY_API_VERSION=3
export OS_VOLUME_API_VERSION=3.63
export OS_COMPUTE_API_VERSION=2.87Настройка сети
- 
Создание балансировщика для control plane узлов. # Создание балансировщика В proCloud # Использование в vip-subnet-id IPv6 это особенность провайдера. При возможности лучше использовать сразу IPv4 без additional-vip openstack loadbalancer create --vip-subnet-id IPv6 --additional-vip subnet-id=IPv4-2 --flavor amph-failover-standard --name talos-control-plane # Создание listener openstack loadbalancer listener create --name talos-control-plane-listener --protocol TCP --protocol-port 6443 talos-control-plane # Pool and health monitoring openstack loadbalancer pool create --name talos-control-plane-pool --lb-algorithm ROUND_ROBIN --listener talos-control-plane-listener --protocol TCP openstack loadbalancer healthmonitor create --delay 5 --max-retries 4 --timeout 10 --type TCP talos-control-plane-pool
- 
Создание сети, подсети и портов. Через графический интерфейс я заранее создал сеть talos-k8s и подсеть с включенным DHCP. Не забыв так-же создать роутер, чтобы подключить эту сеть к внешней сети (иначе ваши узлы будут без доступа в интернет, что не очень хорошо). openstack port create --network talos-k8s talos-control-plane-1 openstack port create --network talos-k8s talos-control-plane-2 openstack port create --network talos-k8s talos-control-plane-3В исходном руководстве ещё для каждой ноды создается отдельный floating ip, но на мой взгляд это избыточно, так как чтобы "ходить" на отдельные ноды достаточно локальной сети и балансировщика. 
- 
Смотрим, какие IP адреса присвоились портам на шаге 2 и создаем на основе них member(ов) у балансировщика. # Создание members для каждого порта с IP. openstack loadbalancer member create --subnet-id shared-subnet --address <PRIVATE IP OF talos-control-plane-1 PORT> --protocol-port 6443 talos-control-plane-pool openstack loadbalancer member create --subnet-id shared-subnet --address <PRIVATE IP OF talos-control-plane-2 PORT> --protocol-port 6443 talos-control-plane-pool openstack loadbalancer member create --subnet-id shared-subnet --address <PRIVATE IP OF talos-control-plane-3 PORT> --protocol-port 6443 talos-control-plane-pool
Создание и конфигурация ВМ с TalosOS
- Создадим ВМ с загрузочным образом Talos, который мы подготовили и присоединив заранее созданный порт. У нас в Амвере большое количество пользователей, хостящих свои боты, сайты и API. Кластер должен быть рассчитан на десятки тысяч подов, поэтому для control plane я выбрал ВМ с 4 vCPU, 8GB RAM и 64GB самого быстрого SSD. Выбор размера ВМ в основном обуславливается требованиями etcd. 
- После запуска ВМ, можно открыть предоставляемую хостингом VNC консоль и убедиться, что узел запустился и перешел в maintenance mode. 
- Выполним команду - talosctl gen config talos-k8s-openstack-tutorial https://${LB_PUBLIC_IP}:6443чтобы получить шаблон файла конфигурации. Важно, чтобы переменная- LB_PUBLIC_IPсодержала внешний адрес вашего созданного балансировщика.
- По итогу будет создано три файла: controlplane.yaml, talosconfig, worker.yaml. 
- 
Отредактируем конфигурацию controlplane, установив необходимые параметры (в зависимости от используемых плагинов могут потребоваться дополнительные изменения): cluster: clusterName: amvera externalCloudProvider: enabled: true
- Применим конфиг через - talosctl apply-config --insecure -n 192.168.0.10 --file ./controlplane.yaml, где после -n стоит IP адрес узла во внутренней сети (тот, который был выдан порту, что мы присоединили к ВМ).
- Создадим ещё две ВМ и применим к ним тот-же самый конфиг. 
- 
Теперь отредактируем файл worker.yaml cluster: clusterName: amvera externalCloudProvider: enabled: true # Для узлов, где будет запущен longhorn machine: kubelet: extraMounts: - destination: /var/lib/longhorn type: bind source: /var/lib/longhorn options: - bind - rshared - rw disks: - device: /dev/sdb partitions: - mountpoint: /var/lib/longhorn
- Создадим ВМ (порт в openstack уже можно создать вместе с ней динамически) и применяем к ней конфиг - talosctl apply-config --insecure -n 192.168.0.15 --file ./worker.yaml
Развертывание etcd
- 
Добавим узлы в файл конфигурации для talosctl talosctl --talosconfig talosconfig config endpoint <control plane 1 IP> talosctl --talosconfig talosconfig config node <control plane 1 IP>
- 
Развернем etcd: talosctl --talosconfig talosconfig bootstrap
- Через какое-то время все узлы будут запущены и KUBELET должен перейти в статус Healthy. 
- Остается получить конфиг для доступа в кластер через - talosctl --talosconfig talosconfig kubeconfig .
- 
Теперь, скопируем наш kubeconfig в .kube/config и проверим, что наши узлы кластера видны и запущены через kubectl get nodes 
Установка Cloud Provider OpenStack
Для того, чтобы наш кластер kubernetes мог ходить в OpenStack и создавать там диски или балансировщики, необходимо поставить Cloud Provider OpenStack. Там есть совершенно разные плагины, лично меня интересовал только OpenStack Cloud Controller Manager для создания балансировщиков и Cinder CSI Plugin, чтобы при создании PV, диски сами создавались в OpenStack и монтировались к нужному узлу.
Для работоспособности необходимо создать файл cloud-config с конфигурацией и кредами от OpenStack
[Global]
auth-url=OS_AUTH_URL
username=OS_USERNAME
password=OS_PASSWORD
tenant-name=OS_PROJECT_NAME
domain-name=default
project-domain-name=OS_PROJECT_DOMAIN_ID
user-domain-name=OS_USER_DOMAIN_ID
region=OS_REGION_NAME
[LoadBalancer]
lb-version=v2
subnet-id=<subnet_id> # ID подсети, из которой балансировщик будет выделять IP 
floating-network-id=<floating_network_id> # ID сети в которой существует вышеуказанная подсеть 
flavor-id=<flavor_id> # ID тарифа балансировщика
member-subnet-id=<member_subnet_id> # ID сети, в которой будут создаваться member. В моем случае это подсеть сети talos-k8s.
create-monitor=true
monitor-delay=5s
monitor-timeout=3s
monitor-max-retries=3
[BlockStorage]
trust-device-path=false
ignore-volume-az=trueOpenStack Cloud Controller Manager
Чтобы поставить этот модуль достаточно выполнить команды из документации.
- 
Создать секрет из файла cloud-config описанного выше. kubectl create secret -n kube-system generic cloud-config --from-file=cloud.conf
- 
Пометить namespace для необходимых прав доступа, создать RBAC ресурсы и openstack-cloud-controller-manager daemonset. kubectl label namespace kube-system pod-security.kubernetes.io/enforce=privileged kubectl apply -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/controller-manager/cloud-controller-manager-roles.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/controller-manager/cloud-controller-manager-role-bindings.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes/cloud-provider-openstack/master/manifests/controller-manager/openstack-cloud-controller-manager-ds.yaml
- Теперь если попробовать создать в кубере Service с типом LoadBalancer, то он должен через как-то время создать балансировщик в OpenStack и автоматически его настроить и подключить. 
Если основная сеть для балансировщика у вашего провайдера это IPv6, то IPv4 балансировщики в кубере через стандартный controller manager создавать не получится.
Чтобы обойти эту проблему, я создал fork основного репозитория, где добавил возможность указывать параметр additional-vip subnet-id.
В таком случае в cloud-config для параметра subnet-id указывается IPv6 подсеть, и в новый параметр additional-vips-subnet-id указывается уже IPv4 посдеть.
Сinder csi plugin
Установка производится так-же через применение манифестов, которые можно найти в репозитории в manifests/cinder-csi-plugin
 kubectl -f manifests/cinder-csi-plugin/ applyМожно теперь создать StorageClass:
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ssd-lite
provisioner: cinder.csi.openstack.org
allowVolumeExpansion: true
parameters:
  type: SSD_Lite # Тип диска у провайдера
  availability: WAW-1 # Регион провайдераТеперь, при создании PV и PVC заданного класса они будут автоматически создаваться в OpenStack и монтироваться к той ноде, на которой запущен Pod. Стоит отметить, что количество дисков, которые могут быть примонтированы к одной ВМ ограничено и точные ограничения стоит уточнять у Вашего провайдера.
Заключение
В данной статье я рассмотрел процесс создания и настройки кластера кубернетис, который теперь будет использоваться в облаке Амвера в зарубежном регионе. Были рассмотрены основные моменты конфигурации с которыми могут столкнуться начинающие администраторы. Так-же важно было подсветить возможность использования Cloud Provider OpenStack плагина.
 
          