k8s/research/longhorn.md
2026-07-15 11:14:21 +03:00

21 KiB
Raw Permalink Blame History

Longhorn — исследование для развёртывания в кластере

Что такое Longhorn

Longhorn — распределённое блочное хранилище для Kubernetes (CNCF-проект, изначально Rancher).
Предоставляет PersistentVolume через CSI-драйвер с репликацией данных между нодами, инкрементальными снапшотами и встроенным бэкапом.


На каких нодах нужны диски

Longhorn Manager запускается как DaemonSet на нодах кластера. Каждая нода, где работает Longhorn Manager, может хранить реплики томов.

Применительно к этому кластеру:

Нода Группа Роль в Longhorn
k8s-master-01 (10.203.0.97) control_plane Может участвовать (тейнт уже снят), но нежелательно в production
k8s-worker-NN workers Основные ноды для хранилища — диски должны быть здесь
k8s-manager-01 (10.203.0.92) manager_nodes Не входит в кластер, диски не нужны

Вывод: диски нужны на worker-нодах. Желательно не смешивать роль control plane и хранилища.


Минимальное количество нод

Режим Нод с дисками Репликация Отказоустойчивость
Dev / тест 1 1 Нет
Minimum HA 3 2 Выдерживает отказ 1 ноды
Production HA 3 3 Выдерживает отказ 2 нод
Extended HA 5+ 3 Рекомендуется для критичных данных

Почему именно 3 ноды — минимум для стабильной работы

Longhorn по умолчанию размещает реплики тома на разных нодах (replica node anti-affinity).

  • При replication=3 требуются 3 разные ноды, иначе Longhorn деградирует том или откажет в создании.
  • При replication=2 достаточно 2 нод, но потеря любой из них оставит данные без резерва — том продолжит работу, но уязвим.
  • 3 ноды + replication=3 — классическая кворум-схема: можно потерять 1 ноду и данные остаются защищёнными.

Практические варианты для этого кластера:

  • Рекомендуется: 3 worker-ноды + control plane (без хранилища)
  • Допустимо (временно): 2 worker-ноды + control plane с Longhorn — итого 3 ноды с дисками, но смешение ролей нежелательно

Минимальное количество дисков на ноде

  • Минимум: 1 диск на ноду. Longhorn работает с одним диском.
  • Рекомендуется: 1 выделенный диск (отдельно от ОС-диска /dev/sda).
  • Longhorn поддерживает несколько дисков на одной ноде — реплики балансируются между ними автоматически.

ОС-диск vs выделенный диск

Параметр ОС-диск Выделенный диск
Изоляция от системы Нет Да
minimalAvailableStoragePercentage ≥25% 10%
Риск DiskPressure Высокий Низкий
Рекомендация Только dev/тест Production

Минимальная жизнеспособная production-конфигурация:

3 worker-ноды × 1 выделенный диск = 3 диска суммарно

Принципы репликации

Longhorn реплицирует данные посинхронно (synchronous replication) между репликами при записи.

Pod (write) → Longhorn Engine → Replica 1 (node-1 /dev/sdb)
                              → Replica 2 (node-2 /dev/sdb)
                              → Replica 3 (node-3 /dev/sdb)
  • Запись подтверждается только когда все реплики записали данные.
  • При отказе реплики Longhorn автоматически перестраивает её на другой ноде (Rebuild).
  • Значение replication задаётся на уровне StorageClass или отдельного тома.

Рекомендуемые настройки anti-affinity

Настройка Значение Смысл
replicaNodeLevelSoftAntiAffinity false Запрет размещения 2 реплик на одной ноде (hard rule)
replicaDiskLevelSoftAntiAffinity true Разрешить несколько реплик на одной ноде, но на разных дисках

Prerequisites — что нужно установить на все ноды кластера

Пакеты (Rocky Linux 9)

dnf install -y iscsi-initiator-utils nfs-utils cryptsetup
Пакет Зачем
iscsi-initiator-utils iSCSI-стек для подключения томов
nfs-utils NFS-поддержка для RWX-томов и бэкапов
cryptsetup LUKS2-шифрование томов (опционально)

Сервисы

systemctl enable --now iscsid

Kernel modules

iscsi_tcp   — iSCSI over TCP
dm_crypt    — Device-mapper шифрование

Добавить в /etc/modules-load.d/longhorn.conf:

iscsi_tcp
dm_crypt

Утилиты (должны быть в PATH)

bash, curl, findmnt, grep, awk, blkid, lsblk — как правило, уже присутствуют на Rocky Linux 9.


SELinux workaround (Rocky Linux 9 — обязательно)

Rocky Linux 9 с container-selinux > 2.189.0 блокирует iscsiadm через SELinux, что приводит к бесконечному циклу attach/detach томов.

Ручной патч (на каждой ноде)

echo '(allow iscsid_t self (capability (dac_override)))' > /tmp/local_longhorn.cil
semodule -vi /tmp/local_longhorn.cil

Автоматически через DaemonSet (после установки Longhorn)

kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/master/deploy/prerequisite/longhorn-iscsi-selinux-workaround.yaml

Firewall (firewalld)

Добавить на ноды кластера:

Порт Протокол Зачем
2049 tcp NFS (для RWX томов и бэкапов)
111 tcp/udp portmapper (NFS)

Порт 10250/tcp (kubelet API) уже открыт в существующей роли k8s_control_plane.


Установка — Helm chart (рекомендуемый метод)

helm repo add longhorn https://charts.longhorn.io
helm repo update

helm install longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --create-namespace \
  --version 1.7.2 \
  --set defaultSettings.defaultReplicaCount=3 \
  --set defaultSettings.replicaNodeLevelSoftAntiAffinity=false \
  --set defaultSettings.minimalAvailableStoragePercentage=10

Ключевые Helm-параметры

Параметр Рекомендуемое значение Описание
defaultSettings.defaultReplicaCount 3 Реплик по умолчанию на новый том
defaultSettings.replicaNodeLevelSoftAntiAffinity false Запрет реплик на одной ноде
defaultSettings.minimalAvailableStoragePercentage 10 (dedicated) / 25 (OS disk) Резерв свободного места
defaultSettings.storageOverProvisioningPercentage 100 Overprovisioning (200 = двойной запас)

Проверка готовности нод (preflight)

Longhorn предоставляет утилиту longhornctl:

# Скачать
curl -sSfL -o longhornctl https://github.com/longhorn/cli/releases/latest/download/longhornctl-linux-amd64
chmod +x longhornctl

# Проверить prerequisites
./longhornctl check preflight

# Автоматически установить зависимости
./longhornctl install preflight

StorageClass после установки

Longhorn создаёт StorageClass longhorn автоматически:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn
provisioner: driver.longhorn.io
parameters:
  numberOfReplicas: "3"
  staleReplicaTimeout: "2880"
  fromBackup: ""
reclaimPolicy: Delete
volumeBindingMode: Immediate

Итоговые минимумы для production

Параметр Минимум (stable) Рекомендуется
Нод с дисками 3 3+
Дисков на ноду 1 (выделенный) 12
Репликация 2 3
Пакеты open-iscsi + nfs-utils + cryptsetup
SELinux патч Обязательно на Rocky Linux 9
Отдельный диск от ОС Рекомендуется


Масштабирование: добавление дисков и нод

Сценарий A: добавление диска к существующей ноде

Как это работает

Longhorn не отслеживает диски автоматически — каждый новый диск нужно явно зарегистрировать через Longhorn UI или kubectl. После регистрации диск мгновенно становится доступен для новых томов.

Подготовка диска (на уровне ОС)

# 1. Отформатировать (ext4 или xfs — обязательно extent-based)
mkfs.xfs /dev/sdb

# 2. Создать точку монтирования
mkdir -p /mnt/longhorn-disk2

# 3. Получить UUID (надёжнее device-name)
blkid /dev/sdb

# 4. Добавить в /etc/fstab (UUID, nofail — обязательно)
echo "UUID=<uuid> /mnt/longhorn-disk2 xfs defaults,nofail 0 2" >> /etc/fstab

# 5. Смонтировать
mount -a

Важно: не использовать symlink в пути — Longhorn-поды не разрешают символические ссылки корректно.

Регистрация диска в Longhorn

Через kubectl (рекомендуется для Ansible):

kubectl patch nodes.longhorn.io <node-name> -n longhorn-system \
  --type merge \
  -p '{"spec":{"disks":{"disk2":{"path":"/mnt/longhorn-disk2","allowScheduling":true,"diskType":"filesystem"}}}}'

Через UI: Nodes → выбрать ноду → Edit node and disks → Add Disk.

Автоматический ребалансинг реплик на новый диск?

Нет. Существующие реплики не переезжают автоматически на новый диск.

  • Новый диск начинает использоваться только для новых томов.
  • Если включена функция Replica Auto Balance (режим best-effort), Longhorn постепенно перемещает часть реплик для выравнивания нагрузки между дисками.
  • Настройка: Longhorn UI → Settings → Replica Auto Balance → best-effort.

Сложности при добавлении диска

Сложность Причина Решение
Диск не виден Longhorn Не смонтирован до регистрации mount | grep /mnt/longhorn-disk2
Ошибка дублирования Тот же filesystem UUID уже в кластере Проверить lsblk -f перед добавлением
Disk не используется allowScheduling: false Включить через UI или patch
Резерв места слишком велик storageReserved ≥ объёму диска Понизить до 10% от объёма

Теги дисков (routing для специфичных воркеров)

Можно пометить диск тегом (например ssd, fast) и указывать его в StorageClass:

# StorageClass
parameters:
  diskSelector: "ssd"

Тогда реплики создаются только на дисках с нужными тегами.


Сценарий B: добавление ноды к кластеру

Автоматическое обнаружение

Когда новая нода присоединяется к Kubernetes, Longhorn обнаруживает её автоматически через DaemonSet — никаких ручных действий не требуется. Longhorn-manager pod поднимается на новой ноде и создаёт Longhorn Node CR.

По умолчанию Longhorn сразу создаёт диск по пути из настройки Default Data Path (/var/lib/longhorn).

Проверка после появления ноды

# Убедиться, что нода появилась в Longhorn
kubectl get node.longhorn.io -n longhorn-system

# Проверить диск на ноде
kubectl get node.longhorn.io <node-name> -n longhorn-system -o yaml
# Ищем: spec.disks, status.diskStatus — должны быть schedulable: true

Ребалансинг существующих реплик на новую ноду?

По умолчанию — нет. Существующие реплики не переезжают на новую ноду автоматически.

Чтобы включить ребалансинг:

Longhorn UI → Settings → Replica Auto Balance → best-effort
Режим Поведение
disabled (по умолчанию) Реплики не перемещаются
least-effort Минимальное перемещение — только для восстановления fault-tolerance
best-effort Равномерное распределение по всем нодам

Ноды с Выделенными дисками (не /var/lib/longhorn)

Если диск подключён как /dev/sdb и смонтирован в /mnt/longhorn, нужно:

  1. Подготовить и смонтировать диск на новой ноде (аналогично Сценарию A).
  2. Зарегистрировать диск в Longhorn вручную или через аннотацию ноды (до или после присоединения к кластеру):
kubectl annotate node <node-name> \
  node.longhorn.io/default-disks-config='[{"path":"/mnt/longhorn","allowScheduling":true}]'

Сложности при добавлении ноды

Сложность Причина Решение
Нода есть в K8s, но не в Longhorn DaemonSet не запустился (taint, ресурсы) Проверить kubectl get pods -n longhorn-system -o wide
Нода есть в Longhorn, но не планирует реплики allowScheduling: false или нет свободного места Включить scheduling, проверить space
Реплики не переехали Auto Balance выключен Включить best-effort
Existing volumes не используют новую ноду Replication count не обновлён Обновить replica count (см. ниже)
Prerequisites не установлены Нет iscsid, nfs-utils Запустить роль prereqs перед join

Критично: перед добавлением ноды к кластеру на ней обязаны быть установлены iscsi-initiator-utils, nfs-utils и применён SELinux-патч (для Rocky Linux 9). Иначе Longhorn Manager pod запустится, но тома не смогут монтироваться на этой ноде.


Сценарий C: миграция 1 нода → 3 ноды (увеличение репликации)

Ситуация

Старт: 1 worker-нода, replication=1 — данные есть, избыточности нет.
Цель: 3 ноды, replication=3 — полная HA.

Окно риска

Пока replica count увеличивается с 1 до 3, том находится в состоянии Degraded: старая реплика работает, новые перестраиваются. В этот момент:

  • Том доступен для чтения и записи (без даунтайма).
  • Если нода со старой единственной репликой упадёт во время перестройкиданные потеряны.

Поэтому перед увеличением replica count — сделать снапшот или бэкап.

Процедура

# 1. Убедиться, что новые ноды видны Longhorn
kubectl get node.longhorn.io -n longhorn-system

# 2. Включить Auto Balance (опционально, для автоматического выравнивания)
# Longhorn UI → Settings → Replica Auto Balance → best-effort

# 3. Обновить replica count для существующих томов
kubectl patch volume <volume-name> -n longhorn-system \
  --type merge \
  -p '{"spec":{"numberOfReplicas":3}}'

# 4. Мониторинг перестройки
kubectl get volume <volume-name> -n longhorn-system \
  -o jsonpath='{.status.state} {.status.replicaCount}'
# Ожидаем: "healthy 3"

Время перестройки (ориентир)

Объём тома Время rebuild
10 GiB 25 минут
100 GiB 1020 минут
1 TiB 14 часа

Типичные проблемы при переходе 1→3

Проблема Симптом Решение
Том завис в Degraded replicaCount не растёт > 1 часа Проверить ноды: space, scheduling, taints
Replica count остался 1 spec.numberOfReplicas=3, но status.replicaCount=1 Новые ноды unschedulable? kubectl get node.longhorn.io
Только 2 реплики создались Третья нода без свободного места Добавить диск или ноду с бо́льшим объёмом
Data Locality: guaranteed мешает Том не перемещается Сменить на best-effort на период миграции

Обновить StorageClass для новых томов

Изменить numberOfReplicas в StorageClass, чтобы все новые PVC создавались сразу с нужной репликацией:

kubectl patch storageclass longhorn \
  -p '{"parameters":{"numberOfReplicas":"3"}}'

Это не влияет на уже существующие тома — только на новые.


Итоговая таблица: сводка по масштабированию

Действие Автоматически? Даунтайм? Главный риск Что сделать
Добавить диск на ноду Нет (ручная регистрация) Нет Диск не смонтирован до регистрации Смонтировать → зарегистрировать через kubectl/UI
Добавить ноду в кластер Да (DaemonSet) Нет Prerequisites не установлены Запустить prereqs-роль до join
Ребалансинг реплик Нет (нужно включить) Нет Реплики остаются на старых нодах/дисках Включить Replica Auto Balance: best-effort
Поднять replica count 1→3 Нет (вручную) Нет (том в Degraded) Потеря данных при падении ноды во время rebuild Снапшот перед изменением, мониторинг rebuild

Источники