Proxmox VE Cluster: від теорії до продакшену
Proxmox Virtual Environment — це платформа на базі Debian Linux, що поєднує KVM-віртуалізацію та LXC-контейнеризацію в єдиному веб-інтерфейсі. Поодинокий гіпервізор — це завжди single point of failure. Кластер вирішує цю проблему, але за умови що ти розумієш як він реально працює всередині.
Як Proxmox влаштований на низькому рівні
Перед тим як говорити про кластер — треба зрозуміти що відбувається на одній ноді.
Шар 1 — Залізо і ядро
Proxmox встановлюється прямо на bare metal. Ніякого гіпервізора між залізом і ядром немає. Це Debian з кастомним ядром pve-kernel, в яке вбудовано ZFS, KVM-модуль (/dev/kvm) і VFIO для PCI passthrough. KVM і є гіпервізор — але він живе як модуль Linux.
# Переконатись що KVM завантажений
lsmod | grep kvm
# kvm_intel або kvm_amd — залежно від процесора
Шар 2 — Процес на кожну VM
Коли ти запускаєш VM — Proxmox форкає окремий процес qemu-system-x86_64. Кожна VM = один Linux-процес. Цей процес через /dev/kvm просить ядро виконати guest-код напряму на CPU через VT-x/AMD-V — без емуляції. Тому KVM VM такі швидкі.
# Побачиш по одному процесу на кожну запущену VM
ps aux | grep qemu-system
LXC-контейнери — зовсім інша історія. Вони не емулюють залізо взагалі. Просто clone() системний виклик з новими namespace і cgroup. Контейнер бачить ізольований процесний простір і мережу, але ядро хоста спільне. Старт LXC — ~100ms. Старт KVM VM — кілька секунд.
Шар 3 — Системні сервіси
pvedaemon — мозок вузла. REST API сервер на внутрішньому порту 85. Він запускає і зупиняє VM, керує сховищем, виконує завдання. Якщо він падає — Web UI перестає відповідати, але вже запущені VM продовжують жити — їх процеси незалежні від pvedaemon.
pveproxy — тільки проксі. Приймає HTTPS на порт 8006, робить TLS-термінацію і передає запити до pvedaemon. Веб-інтерфейс (Ext.js) живе тут.
systemctl status pvedaemon pveproxy
Де живуть конфіги
/etc/pve/ — це не звичайна директорія. Це FUSE-файлова система pmxcfs, яка реплікується між усіма нодами кластера в реальному часі через Corosync. Змінив конфіг VM на node01 → через мілісекунди зʼявилось на node02 і node03.
/etc/pve/
├── qemu-server/ # конфіги KVM VM (101.conf, 102.conf...)
├── lxc/ # конфіги LXC контейнерів
├── storage.cfg # визначення сховищ (cluster-wide)
├── datacenter.cfg # глобальні налаштування кластера
├── corosync.conf # конфіг кластеру
├── ha/
│ ├── resources.cfg # які VM захищені HA
│ └── groups.cfg # групи нод для HA
└── nodes/
└── pve01/ # конфіги специфічні для ноди
Все що в /etc/pve — автоматично синхронізується. Те що поза ним (/etc/network/interfaces тощо) — ні.
Критичний нюанс: якщо кластер втратив кворум — /etc/pve переходить в read-only на всіх нодах. Ти не зможеш запустити нову VM, змінити мережу, нічого. Це навмисна поведінка — захист від split-brain.
Архітектура кластера
Що таке кворум і чому мінімум 3 ноди
Кворум — це стан коли більшість вузлів бачать один одного і можуть приймати рішення. Формула проста:
мінімально необхідна кількість голосів = floor(total_votes / 2) + 1
При 3 нодах: кворум = 2. Впала одна нода → лишилось 2/3 → кластер живий, HA спрацьовує.
При 2 нодах: кворум = 2. Впала одна нода → лишилось 1/2 → кворуму немає, кластер заморожує всі зміни, HA не мігрує VM.
Це не баг — це захист від split-brain.
Split-brain: чому це найгірше що може статись
Split-brain — коли мережа між нодами розривається і обидві частини вирішують що вони “живі”. Обидві намагаються змонтувати той самий диск спільного сховища в read-write. Результат — гарантована корупція файлової системи всередині VM. ZFS pool після цього не відновити.
Proxmox запобігає цьому через кворум: якщо у тебе менше половини голосів — ти нічого не робиш. Меншість мовчить, більшість керує.
Що робити якщо фізично тільки 2 сервери
QDevice (Corosync Qdevice) — зовнішній арбітр кворуму. Розгортається на окремій малесенькій машині (VPS, Raspberry Pi) — вона не несе VM, тільки голосує при розриві між нодами.
# На окремій машині (арбітр)
apt install corosync-qnetd
corosync-qnetd-certutil -i
# На мастер-ноді кластера
pvecm qdevice setup 192.168.1.100 # IP арбітра
Після цього pvecm status покаже Expected votes: 3 при двох фізичних нодах.
Важливо: QDevice і його хост мають бути в іншій мережі або локації. Якщо він в тій самій стійці що й обидві ноди — при відключенні стійки втрачаєш всі три голоси одночасно.
Мережева інфраструктура: де найчастіше все ламається
Що треба ізолювати фізично
| Трафік | Вимоги | Чому окремо |
|---|---|---|
| Corosync heartbeat | <2ms latency, low jitter | Один dropped packet = нода вважається мертвою |
| ZFS replication / Ceph | 10GbE+, high bandwidth | Flooding цього трафіку вбиває Corosync latency |
| Live migration (VM RAM) | висока пропускна здатність | При великих VM може забити канал Corosync |
| VM traffic (public) | залежить від задачі | Ізоляція безпеки та QoS |
| IPMI/BMC | окремий management VLAN | Потрібен навіть коли ОС повністю впала |
Якщо є тільки два фізичних порти — мінімум роби VLAN trunk і окремий VLAN для Corosync. Але краще — окремі NIC.
Migration network: нюанс який часто забувають
За замовчуванням трафік live migration VM іде через той самий інтерфейс що і Corosync. При міграції великої VM (64GB RAM) це може забити канал — Corosync пакети дропаються, нода виглядає мертвою, HA вирішує мігрувати ще більше VM. Каскадний збій.
Виправлення в /etc/pve/datacenter.cfg:
migration: type=insecure,network=10.0.1.0/24
Або через UI: Datacenter → Options → Migration Settings.
insecure означає відсутність додаткового шифрування поверх — якщо мережа фізично ізольована, це нормально. Для WAN — використовуй secure (SSH tunnel, але повільніше).
Corosync: налаштування таймаутів
Файл /etc/corosync/corosync.conf, секція totem:
totem {
version: 2
cluster_name: pve-prod
transport: knet
# Час очікування токену між нодами (мс). Дефолт: 1000.
# На WAN між дата-центрами — збільш до 5000-20000.
token: 5000
# token * token_retransmits = реальний таймаут до оголошення ноди мертвою
token_retransmits_before_loss_const: 10
join: 100
consensus: 1200
max_messages: 20
# Для WAN — обовʼязково knet з компресією
knet_compression_model: lz4
knet_compression_threshold: 100
}
Правило для token: має бути мінімум 10× максимальної RTT між нодами.
- LAN (~0.3ms RTT) →
token: 5000— запас з надлишком - Між містами (~15ms RTT) →
token: 20000 - Між країнами (~60ms RTT) →
token: 80000+consensus: 90000
Після зміни — перезапуск через systemctl restart corosync тільки якщо кластер живий на більшості нод. Ніколи не роби це одночасно на всіх.
Що робити при high latency або нестабільному звʼязку між локаціями
Симптом: ноди постійно виходять і заходять у кластер
journalctl -u corosync --since "1 hour ago" | grep -E "FAILED|left|joined"
Якщо бачиш totem: FAILED to receive the leave message або node X left the cluster — latency перевищує token таймаут, або jitter вбиває пакети.
Алгоритм діагностики
1. Виміряй реальну latency саме на тому IP що в corosync.conf:
ping -c 100 -i 0.1 192.168.10.2 | tail -5
# avg > 5ms або mdev (jitter) > 2ms — треба тюнити
2. Перевір чи Corosync не ділить NIC з іншим трафіком:
# Ненульовий dropped — або buffer overflow, або collision
watch -n1 'ip -s link show eth0'
3. Збільш таймаути пропорційно latency — формула вище.
4. Як тимчасово зупинити автоматичні міграції:
Якщо між локаціями нестабільний звʼязок і ти не хочеш щоб Proxmox починав автоматично мігрувати VM при кожному кліпанні каналу — заморозь HA policy:
# Через CLI (заморожує прийняття рішень CRM)
pvesh set /cluster/ha/config --no-shutdown-policy freeze
Або через UI: Datacenter → HA → Resources → змінити policy на ignored для конкретних VM.
WARNING: Якщо вимкнеш фенсинг і при цьому нода “зависне” а не впаде — HA не зможе безпечно перезапустити VM на іншій ноді. Це trade-off між доступністю і безпекою даних.
Fencing і STONITH: як Proxmox переконується що нода мертва
Коли HA manager бачить що нода недоступна — він не одразу мігрує VM. Спочатку переконується що нода точно зупинила свої VM — інакше split-brain зі спільним сховищем.
Якщо фенсинг не налаштований — HA чекає і нічого не робить. Звідси і “VM не мігрує 10 хвилин після падіння ноди” — це не баг, це безпека.
Типи фенсинг агентів:
Hardware IPMI/iDRAC/iLO → fence_ipmilan (найнадійніше)
PDU / розетка → fence_apc_snmp
Proxmox API (self) → fence_pve
Налаштування через UI: Datacenter → HA → Fencing → Add.
Перевірка без реального перезапуску:
fence_ipmilan -a 192.168.1.100 -u admin -p secret -o status
Watchdog: як нода вбиває сама себе
Коли HA активований, кожна нода відкриває /dev/watchdog. Якщо LRM перестає оновлювати watchdog (бо нода зависла, ОС крашнулась) — апаратний watchdog примусово перезавантажує сервер через кілька секунд. Це self-fencing — нода сама себе вбиває щоб CRM міг безпечно запустити її VM деінде.
cat /proc/sys/kernel/watchdog
ls /dev/watchdog*
Datacenter Manager: що він реально контролює
Datacenter у Proxmox Web UI — це не просто “група нод”. Тут зберігаються речі які автоматично розповсюджуються на всі ноди через pmxcfs:
Storage definitions — якщо додаєш NFS в Datacenter → Storage, він стає доступним на всіх нодах автоматично. Якщо додаєш storage тільки на одній ноді — він видимий тільки там.
HA Groups і Resources — тут визначаєш які VM є HA-захищеними і на які ноди вони можуть мігрувати. VM без HA-ресурсу не буде автоматично перезапущена при падінні ноди.
Resource Mapping (PVE 8+) — абстракція для PCI пристроїв (GPU, HBA, USB) на рівні кластера. Описуєш “GPU у slot 1” на кожній ноді під спільною назвою — тоді VM з GPU passthrough можна мігрувати між нодами.
SDN (Software Defined Networking) — VXLAN-зони, VNet, subnet. Замість того щоб вручну прописувати bridge на кожній ноді — робиш один раз у Datacenter, конфіг реплікується через pmxcfs.
Datacenter-level Firewall — ipsets, aliases, security groups. Правила з datacenter-рівня застосовуються до всіх VM і нод якщо увімкнені.
Покрокове створення кластера
Крок 1 — Ініціалізація на першій ноді
Datacenter → Cluster → Create Cluster
- Вкажи імʼя кластера (наприклад
pve-prod) - Вибери мережевий інтерфейс для Corosync (Link 0) — обовʼязково виділений, не той де йде VM-трафік
- Додай Link 1 для резервування (інший фізичний комутатор)
Крок 2 — Отримання Join Information
Datacenter → Cluster → Join Information → скопіюй весь текст (Information String).
Крок 3 — Приєднання другої і третьої ноди
На кожній ноді що додається: Datacenter → Cluster → Join Cluster
- Встав Information String
- Введи пароль root від першої ноди (для первинного обміну SSH-ключами)
- Вибери локальні лінки для Corosync
Застереження: під час join веб-інтерфейс ноди що додається перезавантажиться — відбувається заміна локального
/etc/pveна кластерну pmxcfs. Нода що приєднується не повинна мати запущених VM з ID які вже є в кластері.
Перевірка після join
pvecm status # загальний статус і кворум
pvecm nodes # список нод з голосами
corosync-cfgtool -s # статус Corosync кілець
Що відбувається при падінні ноди: покроково
1. node02 перестає відповідати на Corosync heartbeat
2. Через token timeout (~5-6 сек дефолт) node01 і node03 оголошують node02 мертвою
3. Corosync перераховує голоси: 2/3 — кворум є
4. CRM отримує подію "node02 left"
5. CRM чекає grace period (60 сек) — раптом нода сама повернеться
6. Якщо фенсинг налаштований — CRM надсилає IPMI команду "вимкни node02"
7. Після підтвердження фенсингу — CRM дає команду LRM запустити VM з node02
8. LRM форкає нові qemu-system процеси для цих VM
Якщо фенсинг не налаштований — крок 6 пропускається, але CRM чекає набагато довше перш ніж мігрувати.
Сховище у кластері
Сам по собі кластер не переміщує дані дисків автоматично якщо у тебе локальні диски. Для live migration (без зупинки VM) потрібне правильне сховище.
| Тип | Технологія | Плюси | Мінуси |
|---|---|---|---|
| Локальне з реплікацією | ZFS Storage Replication | Швидкі локальні NVMe/SSD | Реплікація за розкладом, при падінні ноди — втрата даних за останні N хвилин |
| Спільне мережеве | NFS / iSCSI | Простота, live migration | Single point of failure (NFS сервер) |
| Розподілене | Ceph | Справжній HA, live migration за секунди | Потребує 10GbE+, мінімум 3 OSD ноди |
Оновлення нод без downtime
# 1. Міграція всіх VM з ноди
for vmid in $(qm list | awk 'NR>1 {print $1}'); do
qm migrate $vmid pve02 --online
done
# 2. Переводимо ноду в maintenance mode
ha-manager crm-command node-maintenance enable pve01
# 3. Оновлення
apt update && apt dist-upgrade -y
# 4. Перезавантаження якщо змінилось ядро
if [ -f /var/run/reboot-required ]; then reboot; fi
# 5. Перевірка після ребуту
pvecm status
ha-manager status
# 6. Виводимо з maintenance
ha-manager crm-command node-maintenance disable pve01
Діагностика: команди які завжди під рукою
# Загальний статус кластера і кворуму
pvecm status
# Список нод з голосами
pvecm nodes
# Детальний статус Corosync кілець
corosync-cfgtool -s
# Список нод з кількістю голосів
corosync-quorumtool -l
# HA статус всіх ресурсів
ha-manager status
# Статус реплікації ZFS
pvesr status
# Логи кластерних подій (де шукати проблеми першим ділом)
journalctl -u pve-cluster -u corosync --since "30 min ago"
# Перевірка синхронізації часу (різниця >5с = Corosync не зʼєднається)
chronyc tracking
timedatectl status
Чеклист перед запуском в продакшен
[ ] Мінімум 3 ноди або 2 ноди + QDevice в окремій локації
[ ] Окремий фізичний інтерфейс або VLAN для Corosync
[ ] Link 0 + Link 1 для Corosync (різні фізичні комутатори)
[ ] Окрема мережа для storage/replication трафіку
[ ] Окрема мережа для live migration (datacenter.cfg)
[ ] NTP/chrony синхронізований на всіх нодах
[ ] Фенсинг налаштований і протестований (IPMI або PDU)
[ ] HA Groups і Resources визначені для критичних VM
[ ] corosync token timeout відповідає реальній RTT мережі
[ ] Протестований failover: вимкни одну ноду і перевір HA
[ ] Proxmox Backup Server або VZDump з перевіреним відновленням
#Proxmox #Virtualization #Infrastructure #HA #Corosync #DevOps