K8s кластер на базе Talos в OpenStack
Хабр, привет! Я Максим, технический директор в облаке Амвера и в этой статье я хотел бы поделиться опытом развертывания кластера 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.
Создание кластера
Процесс создания узлов с 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
--protocol-port 6443 talos-control-plane-pool openstack loadbalancer member create --subnet-id shared-subnet --address --protocol-port 6443 talos-control-plane-pool openstack loadbalancer member create --subnet-id shared-subnet --address --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
talosctl --talosconfig talosconfig config node Развернем 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= # ID подсети, из которой балансировщик будет выделять IP
floating-network-id= # ID сети в которой существует вышеуказанная подсеть
flavor-id= # 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=true
OpenStack 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 плагина.