
Введение
Если вы когда-нибудь создавали 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
Декларативное управление - вы описываете желаемое состояние кластера в YAML-манифестах, а CAPI автоматически приводит инфраструктуру к этому состоянию.
Kubernetes-native подход - все операции выполняются через стандартные Kubernetes API. Вам не нужны отдельные CLI или ручные действия — всё через kubectl.
Провайдер-агностичность - Cluster API поддерживает разные инфраструктуры: AWS, Azure, Yandex, Proxmox, Docker и другие. Один и тот же подход работает везде.
Масштабируемость - Можно управлять десятками кластеров из одного места — вашего 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 кластеров одновременно.
Как компоненты взаимодействуют
Процесс создания кластера
Пользователь создает манифест
Cluster
в Management кластереCore Provider анализирует запрос и создает связанные ресурсы (Machine, MachineSet)
Infrastructure Provider получает запрос на создание инфраструктуры и провиженит VM в Proxmox
Bootstrap Provider генерирует cloud-init конфигурацию для установки и настройки Kubernetes
Control Plane Provider инициализирует и настраивает control plane узлы (первый узел → join остальных)
Core Provider координирует создание worker узлов через MachineDeployment
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 провайдера |
|
|
Infrastructure провайдер |
|
|
Bootstrap провайдер |
|
|
Control plane провайдер |
|
|
Addon провайдер |
|
|
IPAM провайдер |
|
Дополнительные флаги:
Параметр |
Описание |
Пример |
---|---|---|
|
Namespace для установки |
|
|
Namespace для мониторинга |
|
|
Путь к файлу конфигурации |
|
|
Ждать готовности провайдеров |
|
|
Таймаут ожидания |
|
Примеры использования:
Полная установка с версиями:
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
обычно занят основным диском VMscsi1
безопасный выбор для cloud-init ISOscsi
шина полностью поддерживается на 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'ом в репозиторий