Введение

Если вы когда-нибудь создавали Kubernetes-кластеры вручную, то знаете, насколько это утомительно: подготовка VM, установка зависимостей, настройка сети, инициализация кластера, добавление worker-нод... И это только начало — потом нужно поддерживать, обновлять и масштабировать всё это хозяйство. Cluster API решает эту проблему, применяя философию Kubernetes к управлению самими кластерами. Вместо императивных команд вы описываете желаемое состояние в YAML-манифестах, а Cluster API автоматически создает, настраивает и поддерживает ваши кластеры.

В этой статье я расскажу, как запустить Cluster API (CAPI) на кластере Proxmox, который работает на Orange Pi 5 Plus с архитектурой ARM64. Для интеграции с Proxmox VE будем использовать Cluster API Provider Proxmox (CAPMOX) от IONOS Cloud.

В результате мы получим полностью автоматизированное развёртывание Kubernetes-кластера, где Cluster API будет создавать виртуальные машины в Proxmox и сам устанавливать на них Kubernetes.

Почему это интересно?

  • Orange Pi 5 Plus — это доступное и производительное ARM-устройство, которое отлично подходит для домашних лабораторий.

  • Proxmox VE позволяет удобно управлять виртуальными машинами и контейнерами.

  • Cluster API делает возможным управлять Kubernetes-кластерами как “инфраструктурой как код”.

Далее не много теории, кому не интересно можно пролистать сюда

Что такое Cluster API?

Cluster API (CAPI) — это проект Kubernetes SIG Cluster Lifecycle, который предоставляет декларативные API и контроллеры для управления жизненным циклом Kubernetes-кластеров.

Главная идея:

Управлять кластерами Kubernetes так же, как и любыми другими ресурсами внутри Kubernetes, используя подход Infrastructure as Code.

Основные принципы Cluster API

  1. Декларативное управление - вы описываете желаемое состояние кластера в YAML-манифестах, а CAPI автоматически приводит инфраструктуру к этому состоянию.

  2. Kubernetes-native подход - все операции выполняются через стандартные Kubernetes API. Вам не нужны отдельные CLI или ручные действия — всё через kubectl.

  3. Провайдер-агностичность - Cluster API поддерживает разные инфраструктуры: AWS, Azure, Yandex, Proxmox, Docker и другие. Один и тот же подход работает везде.

  4. Масштабируемость - Можно управлять десятками кластеров из одного места — вашего management cluster.

Архитектура Cluster API

Cluster API состоит из нескольких ключевых компонентов, каждый из которых выполняет свою задачу:

  • Management Cluster — управляющий кластер

  • Core Provider — это набор основных контроллеров и CRD, которые образуют ядро Cluster API

  • Infrastructure Provider — провайдер инфраструктуры

  • Bootstrap Provider — провайдер начальной настройки

  • Control Plane Provider — провайдер управляющей плоскости

  • Workload Cluster — рабочий кластер

Основные компоненты Cluster API

1. Management Cluster (Управляющий кластер)

Что это: Kubernetes-кластер, который управляет всеми остальными. В нём запускаются контроллеры Cluster API и провайдеров инфраструктуры.

Функции:

  • Хранит описание (манифесты) управляемых кластеров

  • Запускает контроллеры CAPI и следит за их состоянием

  • Координирует создание, обновление и удаление кластеров

  • Мониторит состояние управляемых кластеров

Простыми словами: Это “мозг системы” — главный кластер, который управляет жизненным циклом всех остальных. В то же время, если management cluster упадёт, то все workload-кластеры продолжат работать как обычно, а доступ к ним сохранится при наличии kubeconfig. Однако без работающего management cluster вы не сможете создавать новые кластеры, масштабировать существующие или обновлять их конфигурацию — он нужен именно для управления, а не для работы приложений.

Важно понимать: management cluster сам по себе не обязан быть большим и мощным.

  • Он может состоять всего из одной ноды,

  • Запускаться прямо в виртуалке на том же Proxmox,

  • Работать локально на ноутбуке через Kind или k3s.

Главное, чтобы он был доступен и мог управлять другими кластерами.

2. Core Provider (Основной провайдер)

Что это:
Центральный компонент Cluster API, который предоставляет базовую логику и оркестрацию всех операций с кластерами.

Состоит из:

  • Cluster API Controller Manager — основной контроллер-оркестратор

  • Custom Resource Definitions (CRDs) — определения ресурсов Kubernetes

  • Webhook сервер — компонент для проверки корректности и автоматического изменения конфигурации ресурсов

Основные CRD:

# Cluster - описание целого кластера
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster

# Machine - отдельная виртуальная машина/узел
apiVersion: cluster.x-k8s.io/v1beta1
kind: Machine

# MachineSet - группа идентичных машин (как ReplicaSet)
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineSet

# MachineDeployment - декларативные обновления машин (как Deployment)
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment

Функции:

  • управление полным жизненным циклом кластеров

  • координация работы всех провайдеров (infrastructure, bootstrap, control plane)

  • обеспечение согласованности желаемого и текущего состояния

  • автоматическое восстановление при сбоях (self-healing)

  • реализация паттернов controller и reconciliation loop

Простыми словами:
Это "дирижёр оркестра" — координирует всех остальных провайдеров и следит за общей картиной.
Важно: Core Provider входит в базовую поставку cluster-api и устанавливается первым.

3. Infrastructure Provider (провайдер инфраструктуры)

Что это:
Компонент, отвечающий за взаимодействие с конкретной инфраструктурой (облаком или гипервизором).

Функции:

  • создаёт виртуальные машины и сети

  • управляет их жизненным циклом (запуск, остановка, удаление)

  • работает через API выбранного провайдера

  • обеспечивает абстракцию от специфики инфраструктуры

  • автоматизирует подготовку окружения для кластеров

Простыми словами:
Это "руки Cluster API", которые создают ресурсы там, где нужно. Каждый провайдер знает, как "разговаривать" со своей инфраструктурой.

Важно:

  • Для каждого типа инфраструктуры нужен свой провайдер

  • Провайдеры унифицируют работу с разными платформами

  • В нашем случае используется Proxmox Provider (CAPMOX)

Популярные провайдеры:
AWS, Azure, GCP, VMware, OpenStack, Metal3, Docker

4. Bootstrap Provider (провайдер начальной настройки)

Что это:
Компонент, который превращает "чистую" VM в полноценную Kubernetes-ноду.

Функции:

  • генерирует конфигурацию для инициализации узла

  • выполняет первичную настройку ОС и Kubernetes

  • подключает ноды к кластеру

  • обеспечивает безопасную передачу секретов и сертификатов

  • управляет процессом join новых узлов

Простыми словами:
Это "пусковая установка" для каждой новой VM. Получает голую машину — возвращает готовый Kubernetes-узел.

Популярные Bootstrap Providers:

  • Kubeadm — стандартный провайдер (по умолчанию)

  • Talos — immutable ОС, управляется через API

  • K3s — облегченный Kubernetes

  • MicroK8s — snap-based дистрибутив

  • RKE2 — Rancher Kubernetes Engine

  • k0s — zero-deps дистрибутив

Важно: Выбор bootstrap provider определяет, какая версия и дистрибутив Kubernetes будет использоваться в кластере.

В нашем случае используется kubeadm bootstrap provider.

5. Control Plane Provider (провайдер управляющей плоскости)

Что это:
Компонент, который управляет control plane — "мозгом" Kubernetes-кластера (API server, etcd, controller-manager, scheduler).

Функции:

  • создаёт и настраивает управляющие ноды

  • управляет масштабированием control plane (HA-режим)

  • контролирует rolling updates мастер-нод

  • следит за состоянием и здоровьем control plane компонентов

  • обеспечивает отказоустойчивость управляющего слоя

Простыми словами:
Это "главврач" для мастер-нод. Следит, чтобы "мозг" кластера всегда был здоров и доступен.

Типы Control Plane Providers:

  • Kubeadm — стандартный провайдер (самый популярный)

  • Talos — для immutable control plane

  • K3s — упрощенный control plane

  • Managed — для облачных managed Kubernetes (EKS, GKE, AKS)

Важно:

  • В production рекомендуется минимум 3 control plane ноды для HA

  • Control plane и worker ноды могут использовать разные providers

В нашем случае используется kubeadm control plane provider.

6. Workload Cluster (рабочий кластер)

Что это:
Целевой Kubernetes-кластер, в котором развертываются и выполняются ваши продуктивные приложения.

Функции:

  • размещает рабочие нагрузки (Pods, Deployments, Services)

  • управляется декларативно через манифесты из management cluster

  • автоматически масштабируется и обновляется

  • изолирован от управляющего слоя для повышения безопасности

  • может располагаться в разных облаках или регионах

Простыми словами:
Это "боевой" кластер, где живут ваши приложения. Management cluster его создает и настраивает, а workload cluster просто работает.

Важно: Один management cluster может управлять множеством workload кластеров одновременно.

Как компоненты взаимодействуют

Процесс создания кластера

  1. Пользователь создает манифест Cluster в Management кластере

  2. Core Provider анализирует запрос и создает связанные ресурсы (Machine, MachineSet)

  3. Infrastructure Provider получает запрос на создание инфраструктуры и провиженит VM в Proxmox

  4. Bootstrap Provider генерирует cloud-init конфигурацию для установки и настройки Kubernetes

  5. Control Plane Provider инициализирует и настраивает control plane узлы (первый узел → join остальных)

  6. Core Provider координирует создание worker узлов через MachineDeployment

  7. Workload кластер становится готов к развертыванию приложений

Схема взаимодействия

Management Cluster
├── Core Provider (cluster-api-controller-manager)
├── Infrastructure Provider (capmox-controller-manager)  
├── Bootstrap Provider (kubeadm-bootstrap-controller-manager)
└── Control Plane Provider (kubeadm-control-plane-controller-manager)
     │
     │ (API calls)
     ▼
Proxmox Infrastructure
├── Control Plane VMs (обычно 1 или 3+ для HA)
└── Worker VMs (масштабируемо)
     │
     │ (kubeconfig)
     ▼
Workload Cluster (новый кластер Kubernetes)
└── Приложения пользователя

Жизненный цикл ресурсов

Cluster (Кластер)

  • Создание: Координирует создание всех компонентов инфраструктуры

  • Масштабирование: Управляет горизонтальным добавлением/удалением узлов

  • Обновление: Координирует версионные апгрейды (Kubernetes, ОС, компонентов)

  • Мониторинг: Отслеживает состояние готовности всех узлов

  • Удаление: Очистка всех связанных ресурсов и инфраструктуры

Machine (Машина)

  • Provisioning: Создание VM через Infrastructure Provider

  • Bootstrapping: Установка и конфигурация Kubernetes через Bootstrap Provider

  • Running: Рабочее состояние узла с активным kubelet

  • Draining: Безопасная эвакуация подов перед обслуживанием

  • Deleting: Корректное удаление VM и очистка ресурсов

MachineDeployment (Развертывание машин)

  • Работает аналогично Kubernetes Deployment, но для физических машин

  • Обеспечивает декларативные обновления с контролем версий

  • Управляет rolling updates узлов с настраиваемой стратегией

  • Поддерживает горизонтальное автомасштабирование

  • Автоматически заменяет неисправные узлы (machine health checking)

Важные особенности

Reconciliation Loop:
Каждый провайдер работает по принципу "желаемое vs текущее состояние" и постоянно приводит систему к нужному состоянию.

Event-driven архитектура:
Компоненты реагируют на изменения в Kubernetes API через watch механизм, что обеспечивает быструю реакцию на события.

Fail-safe механизмы:

  • Автоматическое восстановление неисправных узлов

  • Проверка здоровья машин (machine health checks)

  • Graceful shutdown при удалении ресурсов

Multi-cluster management:
Один Management кластер может одновременно управлять десятками Workload кластеров в разных окружениях.


Начало установки

Здесь я опишу по шагам как я пришел к конечной цели. ARM64 стала популярным выбором для home lab'ов благодаря производительности и доступности. Многие энтузиасты покупают Orange Pi, Raspberry Pi 5 для экспериментов с Kubernetes. Железо доступное, энергоэффективное, а производительность впечатляет. Но много подводных камней от начала создания ВМ в Proxmox (ошибка Bus 'ide.0' not found шина ide не поддерживается в Proxmox для ARM64) до развертывания ClusterAPI, но все это решается.

Исходное состояние

  • Должен быть настроенный кластер Proxmox VE. Здесь я не буду описывать как установить Proxmox на Orange PI 5 plus

  • Подготовлен шаблон ВМ для использования в Cluster API

Подготовка шаблона ВМ

Основные требования к шаблону:

  • Операционная система: Ubuntu 20.04 LTS или Ubuntu 22.04 LTS (рекомендуется)

  • Cloud-init поддержка: Обязательно должен быть установлен и настроен cloud-init

  • QEMU Guest Agent: Должен быть установлен для корректной работы с Proxmox API

  • SSH доступ: Настроенный SSH сервер

  • Предустановленные компоненты для Kubernetes (kubelet, kubeadm, kubectl, containerd)

ВМ можно создать в UI интерфейсе, накликав мышкой, я буду делать все в командной строке. Нужно зайти на ноду Proxmox и выполнить следующие команды от пользователя root.

# Перейдем в директорию с образами
cd /var/lib/vz/template/iso

# Скачаем образ
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-arm64.img

# Создаем VM с ID 5005, именем k8s-ubuntu
# 2GB RAM, 2 CPU cores, привязка к ядрам 4-7
# Архитектура ARM64, машинный тип virt, UEFI BIOS
qm create 5005 --name k8s-ubuntu \
 --memory 2048 \
 --cores 2 \
 --affinity 4-7 \
 --arch aarch64 \
 --machine virt \
 --bios ovmf \
 --net0 virtio,bridge=vmbr0 \
 --serial0 socket \
 --vga serial0

# Включаем агента (это обязательно)
qm set 5005 --agent enabled=1

# Импортируем готовый образ Ubuntu ARM64
qm importdisk 5005 jammy-server-cloudimg-arm64.img local

# Подключаем импортированный диск как SCSI0
qm set 5005 --scsi0 local:5005/vm-5005-disk-0.raw

# Устанавливаем контроллер SCSI
qm set 5005 --scsihw virtio-scsi-pci

# Делаем диск загрузочным
qm set 5005 --boot order=scsi0

# Создаем EFI диск для UEFI загрузки
qm set 5005 --efidisk0 local:1,format=raw,efitype=4m,pre-enrolled-keys=0

# Настраиваем пользователя, пароль, SSH ключ и сеть
qm set 5005 \
 --ciuser fill \
 --cipassword ********* \
 --sshkey ~/.ssh/id_ed25519.pub \
 --ipconfig0 ip=dhcp

# Добавляем диск для Cloud-Init
qm set 5005 --scsi2 local:cloudinit

# Увеличиваем основной диск до 20GB
qm resize 5005 scsi0 20G

# Запускаем ВМ
qm start 5005

qm terminal 5005 
# После появления "starting serial terminal on interface serial0 (press Ctrl+O to exit)" нажмите ввод

Вводим логин и пароль. Выполняем команды от root

# Обновляем пакеты
apt update

# Устанавливаем QEMU Guest Agent для лучшей интеграции с Proxmox
apt install qemu-guest-agent

# Устанавливаем containerd как container runtime
apt install containerd

# Устанавливаем зависимости для добавления репозитория Kubernetes
apt install -y apt-transport-https ca-certificates curl gpg

# Добавляем GPG ключ репозитория Kubernetes v1.32
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# Добавляем репозиторий Kubernetes
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

# Обновляем список пакетов
apt update

# Устанавливаем kubelet (агент узла), kubeadm (инструмент настройки), kubectl (CLI)
apt-get install -y kubelet kubeadm kubectl

# Включаем и запускаем kubelet
systemctl enable --now kubelet

# Создаем файл с настройками ядра для Kubernetes
cat > /etc/sysctl.d/99-kubernetes.conf << EOF
# Kubernetes required settings
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
# Optional: disable swap accounting
vm.swappiness = 0
EOF

# Применяем настройки
sysctl --system

# Отключаем swap временно
swapoff -a

# Отключаем swap навсегда (комментируем строки в fstab)
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

# Создаем директорию для конфигурации
mkdir -p /etc/containerd

# Генерируем конфигурацию по умолчанию
containerd config default > /etc/containerd/config.toml

# Включаем SystemdCgroup для совместимости с kubelet
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

# Перезапускаем и включаем containerd
systemctl restart containerd
systemctl enable containerd

Теперь можно выйти из ВМ, остановить ее и конвертировать в шаблон

qm stop 5005

qm template 5005

У нас готовый к использованию шаблон, идем дальше

Подготовка менеджмент-кластера

Cluster API всегда разворачивается из управляющего (management) кластера. Этот кластер нужен только для того, чтобы развернуть и управлять workload-кластерами. Сам он в продакшене не участвует, поэтому его можно поднять локально — на ноутбуке, рабочей станции или в отдельной VM.

Вариантов запуска менеджмент-кластера несколько:

  • Minikube — удобно для быстрого старта, но ограничено одной нодой.

  • kind — Kubernetes в Docker-контейнерах, простой и быстрый способ, подходит для локальной разработки.

  • k3s / rke2 — лёгкий Kubernetes с упрощённой установкой, можно развернуть в VM или LXC.

  • kubeadm — классический способ, если хочется руками поднять «настоящий» кластер

Я выбрал kind, потому что:

  • не требует установки виртуализации или отдельных VM

  • быстро создаётся и удаляется

  • удобно использовать для тестов и работы с Cluster API

Установка kind

На ноутбуке (macOS):

# For M1 / ARM Macs
[ $(uname -m) = arm64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.30.0/kind-darwin-arm64
chmod +x ./kind
mv ./kind /some-dir-in-your-PATH/kind

# проверка
kind --version

Для других архитектур и систем можно посмотреть в официальной документации

Ещё потребуется kubectl:

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/$(uname | tr '[:upper:]' '[:lower:]')/arm64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

Создание кластера

Создадим конфиг kind-config.yaml:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: capi-mgmt
nodes:
  - role: control-plane

Поднимаем кластер:

kind create cluster --config kind-config.yaml

Проверяем:

kubectl cluster-info
kubectl get nodes

Cluster API распространяется как набор контроллеров, которые устанавливаются в менеджмент-кластер и управляют жизненным циклом Kubernetes-кластеров. Для работы нам нужен инструмент clusterctl.

Установка clusterctl

Скачаем бинарник (здесь и далее я буду приводить примеры для MacOS, для других OS ссылки можно взять в официальной документации):

curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.11.0/clusterctl-darwin-arm64 -o clusterctl

#права на запуск 
chmod +x ./clusterctl

#переместим в локальную директорию для  бинарей
sudo mv ./clusterctl /usr/local/bin/clusterctl

#проверка 
clusterctl version

Подготовим настройки для инициализации ClusterAPI

Нужно создать выделенный токен для Proxmox user, это можно сделать в веб-интерфейсе или зайти на ноду Proxmox по ssh и дать команды:

pveum user add capmox@pve
pveum aclmod / -user capmox@pve -role PVEVMAdmin
pveum user token add capmox@pve capi -privsep 0

Полученный токен нужно записать в следующий файл ~/.cluster-api/clusterctl.yaml. В текущей директории пользователя нужно создать:

mkdir ~/.cluster-api

Example ~/.cluster-api/clusterctl.yaml

## -- Controller settings -- ##
PROXMOX_URL: "https://192.168.1.11:8006"                       # The Proxmox VE host
PROXMOX_TOKEN: "capmox@pve!capi"                                # The Proxmox VE TokenID for authentication
PROXMOX_SECRET: "***********"                                    # Сюда пишем полученный токен


## -- Required workload cluster default settings -- ##
PROXMOX_SOURCENODE: "pimox2"                                     # Узел на котором размещен шаблон ВМ 
TEMPLATE_VMID: "5005"                                          # ID шаблона для клонирования
ALLOWED_NODES: "[pimox2]"                                  # Узлы для развертывания ВМ, в моем случае один
VM_SSH_KEYS: "ssh-ed25519 ..., ssh-ed25519 ..."               # The ssh authorized keys used to ssh to the machines.

## -- networking configuration-- ##
CONTROL_PLANE_ENDPOINT_IP: "192.168.1.30"                       # The IP that kube-vip is going to use as a control plane endpoint
NODE_IP_RANGES: "[192.168.1.31-192.168.1.39]"               # The IP ranges for Cluster nodes
GATEWAY: "192.168.1.1"                                         # The gateway for the machines network-config.
IP_PREFIX: "24"                                               # Subnet Mask in CIDR notation for your node IP ranges
DNS_SERVERS: "[8.8.8.8,8.8.4.4]"                              # The dns nameservers for the machines network-config.
BRIDGE: "vmbr1"                                               # The network bridge device for Proxmox VE VMs

## -- xl nodes -- ##
BOOT_VOLUME_DEVICE: "scsi0"                                   # The device used for the boot disk.
BOOT_VOLUME_SIZE: "30"                                       # The size of the boot disk in GB.
NUM_SOCKETS: "2"                                              # The number of sockets for the VMs.
NUM_CORES: "2"                                                # The number of cores for the VMs.
MEMORY_MIB: "4096"                                            # The memory size for the VMs.

EXP_CLUSTER_RESOURCE_SET: "true"                              # This enables the ClusterResourceSet feature that we are using to deploy CNI
CLUSTER_TOPOLOGY: "true"                                      # This enables experimental ClusterClass templating

Тут я привел свои настройки, по комментариям думаю все понятно.

Дальше нам нужно проинициализировать Cluster API в менеджмент кластер, после подготовки всех настроек нужно выполнить команду:

clusterctl init --infrastructure proxmox --ipam in-cluster

Сейчас пройдемся по параметрам инициализации. Для чего нужен --ipam in-cluster я не описал его в начале статьи со всеми провайдерами. И так, IPAM (IP Address Management) провайдер отвечает за управление IP-адресами машин в кластере. Он особенно полезен для non-cloud развертываний, таких как Proxmox или bare metal.

Зачем это нужно:

  • Автоматическое выделение IP — не нужно вручную указывать адреса для каждой VM

  • Управление пулами адресов — можете создать диапазоны IP для разных кластеров

  • Предотвращение конфликтов — система следит, чтобы адреса не пересекались

  • Декларативность — IP-адреса управляются через Kubernetes ресурсы

Альтернатива без IPAM: Придется вручную прописывать IP-адреса в каждом манифесте Machine.

Все параметры clusterctl init

Основной синтаксис:

clusterctl init [flags] [provider1] [provider2] ...

Основные флаги:

Параметр

Описание

Пример

--core

Версия core провайдера

--core cluster-api:v1.6.1

--infrastructure

Infrastructure провайдер

--infrastructure proxmox

--bootstrap

Bootstrap провайдер

--bootstrap kubeadm:v1.6.1

--control-plane

Control plane провайдер

--control-plane kubeadm:v1.6.1

--addon

Addon провайдер

--addon helm

--ipam

IPAM провайдер

--ipam in-cluster

Дополнительные флаги:

Параметр

Описание

Пример

--target-namespace

Namespace для установки

--target-namespace capi-system

--watching-namespace

Namespace для мониторинга

--watching-namespace "" (все)

--config

Путь к файлу конфигурации

--config ~/.cluster-api/clusterctl.yaml

--wait-providers

Ждать готовности провайдеров

--wait-providers

--wait-provider-timeout

Таймаут ожидания

--wait-provider-timeout 5m

Примеры использования:

Полная установка с версиями:

clusterctl init \
  --core cluster-api:v1.6.1 \
  --bootstrap kubeadm:v1.6.1 \
  --control-plane kubeadm:v1.6.1 \
  --infrastructure proxmox:v0.5.0 \
  --ipam in-cluster

Установка в custom namespace:

clusterctl init \
  --infrastructure aws \
  --target-namespace custom-capi-system

Автоматические провайдеры

clusterctl автоматически добавляет cluster-api core провайдер, kubeadm bootstrap провайдер и kubeadm control-plane провайдер, если они не указаны явно.

Это означает, что команда:

clusterctl init --infrastructure proxmox

Эквивалентна:

clusterctl init \
  --core cluster-api \
  --bootstrap kubeadm \
  --control-plane kubeadm \
  --infrastructure proxmox

И так после выполнения команды clusterctl init --infrastructure proxmox --ipam in-cluster мы получили:

Не много подождав можно проверить запущенные провайдеры

Management кластер теперь готов создавать и управлять Kubernetes кластерами на Proxmox инфраструктуре. Достаточно применить нужные манифесты — и система автоматически развернет новый кластер. Теперь сгенерируем манифесты или можно написать с нуля:

clusterctl generate cluster myproxmoxcluster \
    --infrastructure proxmox \
    --kubernetes-version v1.32.0 \
    --control-plane-machine-count 1 \
    --worker-machine-count 1 > cluster.yaml

Содержимое моего файла cluster.yaml

Кластер конфигурируется с одной control-plane и одной worker нодой, но можно легко изменить количество в манифестах через параметры replicas в соответствующих ресурсах.

Запускаем создание кластера:

kubectl apply -f cluster.yaml

На этом этапе я получил первую проблему, которую долго не мог решить, и уже думал закончить эксперименты с ClusterAPI ))) Но нашел решение, в исходнике поменял значение константы и пересобрал Dockerfile. Я сделал issue в репозиторий разработчика, с просьбой поправить этот момент и сделать настраиваемый выбор шины, но ответа так и не получил. На днях у них вышла новая версия 0.7.4 и метод с исправлением константы не работает, я написал еще issue. Так что пока можно использовать версию 0.7.3

При создании VM получаем ошибку:

Bus 'ide.0' not found
TASK ERROR: start failed: QEMU exited with code 1

Корень проблемы:
Proxmox Provider захардкодил в коде использование ide0 шины для cloud-init ISO, но ARM64 архитектура в Proxmox не поддерживает IDE шины. Даже если в template VM настроена SCSI шина, провайдер принудительно пытается создать IDE устройство.

Решение проблемы

Можно пересобрать dockerfile или взять мой готовый образ docker pull filatof/capmox:v0.7.3

Шаг 1: Клонируем репозиторий провайдера

git clone https://github.com/ionos-cloud/cluster-api-provider-proxmox.git
cd cluster-api-provider-proxmox

Шаг 2: Правим константу в исходном коде, файл internal/inject/inject.go

// Файл: internal/inject/inject.go
// Было:
const CloudInitISODevice = "ide0"

// Стало:
const CloudInitISODevice = "scsi1"

Шаг 3: Пересобираем Docker образ

# Сборка для ARM64
docker build --platform linux/arm64 -t filatof/capmox:v0.7.3 .

# Или если собираете на x86_64 для ARM64
docker buildx build --platform linux/arm64 -t filatof/capmox:v0.7.3 .

Шаг 4: Обновляем деплоймент провайдера

kubectl patch deployment capmox-controller-manager \
  -n capmox-system \
  -p '{"spec":{"template":{"spec":{"containers":[{"name":"manager","image":"filatof/capmox:v0.7.3"}]}}}}'

Важные моменты:

Почему именно scsi1:

  • scsi0 обычно занят основным диском VM

  • scsi1 безопасный выбор для cloud-init ISO

  • scsi шина полностью поддерживается на ARM64

Поправили образ Proxmox провайдера, и теперь можно запускать создание кластера:

kubectl apply -f cluster.yaml

ВМ не создаются, получаю следующую ошибку:

Посмотрим так:

kubectl describe machine myproxmoxcluster-control-plane-qt52f

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

cannot reserve 2147483648B of memory on node pimox2: 0B available memory left
  • 2147483648B = 2 ГБ — именно столько просит ProxmoxMachine для запуска ноды.

  • 0B available memory left — провайдер думает, что на узле нет свободной памяти.

Поэтому ресурс ProxmoxMachine уходит в статус Failed с причиной InsufficientResources.

Решение
Добавить параметр schedulerHints в манифест:

apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1
kind: ProxmoxCluster
metadata:
  name: myproxmoxcluster
  namespace: default
spec:
  schedulerHints:
    memoryAdjustment: 0

В спецификации ProxmoxCluster есть параметр

schedulerHints:
    memoryAdjustment: 0

Он определяет, как CAPMox учитывает доступную память на узле при запуске новых виртуальных машин.

  • Положительное значение (memoryAdjustment: 512) Провайдер зарезервирует дополнительно 512 МБ. Это полезно, если вы хотите оставить запас памяти для самого Proxmox и сервисов на хосте.

  • Ноль (memoryAdjustment: 0) Планировщик будет использовать всю доступную память. В этом случае узел максимально загружается, но есть риск, что Proxmox останется без резерва.

  • Отрицательное значение (memoryAdjustment: -512) «Обман» планировщика: он будет считать, что на узле есть больше памяти, чем реально. Можно использовать только для тестов, так как велик риск падения нод из-за OOM.

На ARM-платформах (Orange Pi, Raspberry Pi) часто встречается ситуация, когда CAPMox ошибочно считает, что на узле нет свободной памяти (0B available). В таких случаях установка:

schedulerHints:
  memoryAdjustment: 0

позволяет обойти проверку и успешно создавать кластеры.
Запускаем создание кластера:

kubectl apply -f cluster.yaml

И получаю запущенные ВМ:

Теперь нужно получить kubeconfig для управления воркер кластером, выполним команду:

clusterctl get kubeconfig myproxmoxcluster > kubeconfig

Чтобы посмотреть запущенные поды кластера выполним команду:

KUBECONFIG=kubeconfig kubectl get pod -A

Кластер совсем пустой. Ноды еще не перешли в готовность, потому что не установлен CNI

Установим calico, выполним команду:

KUBECONFIG=kubeconfig kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

Не много подождем пока скачаются образы и запустятся поды. В итоге получаем рабочий кластер

Вывод

Что получилось:
В результате всех экспериментов мы создали полноценную платформу для автоматического развертывания Kubernetes-кластеров на ARM64 архитектуре. Orange Pi 5 Plus база для домашней лаборатории — его производительности достаточно для одновременной работы Management кластера и нескольких Workload кластеров.

Экономия ресурсов:
Cluster API кардинально меняет подход к управлению инфраструктурой. То, что раньше требовало многочасовой ручной работы и высокой вероятности ошибок, теперь выполняется за 5-10 минут одной командой kubectl apply. Декларативный подход превращает инфраструктуру в код — версионируемый, воспроизводимый и предсказуемый.

ARM64 как платформа:
Связка ARM64 + Proxmox + Cluster API оказалась не только работоспособной, но и практичной для реальных задач. Энергоэффективность, доступность железа делают ARM64 серьезной альтернативой x86_64 для домашних лабораторий.

Практическая ценность:
Теперь у нас есть foundation для более сложных сценариев — управление множественными кластерами, быстрое восстановление после сбоев, и полноценного GitOps workflow.


В следующей статье покажу, как сделать процесс развертывания кластера еще проще:

  • CNI (Cilium, Calico) устанавливается автоматически вместе с кластером

  • Управление кластерами через Git с помощью FluxCD

  • Создание кластеров простым commit'ом в репозиторий

Комментарии (0)