K8s кластер на базе Talos в OpenStack

Хабр, привет! Я Максим, технический директор в облаке Амвера и в этой статье я хотел бы поделиться опытом развертывания кластера kubernetes, который под капотом использует OpenStack. В этой статья я хочу пошагово рассказать про путь развертывания, подсветив те места, которые вызвали у меня затруднения.

Про Amvera Cloud

Amvera—это облако для простого деплоя приложений через git push. Встроенный CI/CD, бэкапы и мониторинг позволяют развернуть проект тремя командами в IDE и не думать о настойке инфраструктуры. Amvera проще, чем использование VPS или Kubernetes-кластера. Все проекты мы запускаем в Kubernetes. Данная статья о том, как мы разворачивали кластер для нашей международной зоны доступности в Варшаве.

Подготовка образа

Talos Linux — это операционная система на базе Linux, которая специально была разработана для запуска Kubernetes. Базовый образ содержит минимум сторонних и по факту не нужных куберу сервисов, которые присутствуют в других дистрибутивах Linux. Более того, вся конфигурация узла содержится в специальном файле конфигурации, который мы рассмотрим позже.

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

  1. Hardware Type — выбираем «Cloud Server»

  2. Choose Talos Linux Version — версия ОС. На момент развертывания кластера автором, последняя версия была 1.8.3. Всегда лучше выбирать последнюю стабильную версию.

  3. Cloud — тут выбираем, в каком облаке будем разворачивать. В моём случае это OpenStack.

  4. Machine Architecture — архитектура процессора, на котором будет разворачивается кластер (или конкретный узел).

  5. System Extensions — это самый интересный пункт. Базовый Talos не содержит в себе многих привычных модулей ядра, они должны быть добавлены через расширения. Так, если планируется использовать Longhorn, нужно добавить «iscsi-tools» и «util-linux-tools». Нужно заранее подумать о том, что потребуется разворачивать на нодах с данным образом и не забыть включить нужные расширения, иначе можно столкнуться с ошибками при запуске подов.

  6. Customization — можно указать дополнительные параметры запуска ядра, но я оставляю это поле пустым.

  7. Schematic Ready — мы добрались до страницы, с которой можно загрузить образ, который будет содержать все указанные на этапе 5 расширения. Мой облачный провайдер поддерживает загрузку только raw образов, поэтому я скачивал «Disk Image».

  8. Как только образ загрузится, грузим его в 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

Настройка сети

  1. Создание балансировщика для 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
    
  2. Создание сети, подсети и портов.

    Через графический интерфейс я заранее создал сеть 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, но на мой взгляд это избыточно, так как чтобы «ходить» на отдельные ноды достаточно локальной сети и балансировщика.

  3. Смотрим, какие 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

  1. Создадим ВМ с загрузочным образом Talos, который мы подготовили и присоединив заранее созданный порт. У нас в Амвере большое количество пользователей, хостящих свои боты, сайты и API. Кластер должен быть рассчитан на десятки тысяч подов, поэтому для control plane я выбрал ВМ с 4 vCPU, 8GB RAM и 64GB самого быстрого SSD. Выбор размера ВМ в основном обуславливается требованиями etcd.

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

  3. Выполним команду talosctl gen config talos-k8s-openstack-tutorial https://${LB_PUBLIC_IP}:6443 чтобы получить шаблон файла конфигурации. Важно, чтобы переменная LB_PUBLIC_IP содержала внешний адрес вашего созданного балансировщика.

  4. По итогу будет создано три файла: controlplane.yaml, talosconfig, worker.yaml.

  5. Отредактируем конфигурацию controlplane, установив необходимые параметры (в зависимости от используемых плагинов могут потребоваться дополнительные изменения):

    cluster:
      clusterName: amvera
      externalCloudProvider:
        enabled: true
  6. Применим конфиг через talosctl apply-config --insecure -n 192.168.0.10 --file ./controlplane.yaml, где после -n стоит IP адрес узла во внутренней сети (тот, который был выдан порту, что мы присоединили к ВМ).

  7. Создадим ещё две ВМ и применим к ним тот-же самый конфиг.

  8. Теперь отредактируем файл 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
  9. Создадим ВМ (порт в openstack уже можно создать вместе с ней динамически) и применяем к ней конфиг talosctl apply-config --insecure -n 192.168.0.15 --file ./worker.yaml

Развертывание etcd

  1. Добавим узлы в файл конфигурации для talosctl

    talosctl --talosconfig talosconfig config endpoint 
    
    talosctl --talosconfig talosconfig config node 
    
  2. Развернем etcd:

    talosctl --talosconfig talosconfig bootstrap
  3. Через какое-то время все узлы будут запущены и KUBELET должен перейти в статус Healthy.

  4. Остается получить конфиг для доступа в кластер через talosctl --talosconfig talosconfig kubeconfig .

  5. Теперь, скопируем наш kubeconfig в .kube/config и проверим, что наши узлы кластера видны и запущены через kubectl get nodes

    a0832a4c385ed3d2cf146a8d9f231889.png

Установка 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

Чтобы поставить этот модуль достаточно выполнить команды из документации.

  1. Создать секрет из файла cloud-config описанного выше.

    kubectl create secret -n kube-system generic cloud-config --from-file=cloud.conf
  2. Пометить 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
  3. Теперь если попробовать создать в кубере 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 плагина.

© Habrahabr.ru