Перейти к основному содержанию
Zцех
  • Имя пользователя
  • Главная
  • Материалы
    • Кейсы
    • Инструкции
    • Статьи
    • Заметки
    • Обзоры
  • Тематики
  • О компании
  • Контакты
  1. Главная

Сборка HA-кластера на базе Proxmox

25/08/2026НАПИСАНО ЧЕЛОВЕКОМ — ОТРЕЦЕНЗИРОВАНО И СВЕРСТАНО ИИ

HA-кластер Proxmox с общим NVMe-хранилищем

В современных реалиях внедрение каких-то фундаментальных решений требует основательного подхода.

Многие вендоры ушли с рынка РФ. Лицензии официально недоступны.

Исходные данные были такие:

  • компания среднего размера;
  • несколько офисов;
  • около 300 пользователей в сети;
  • 1С;
  • терминальные серверы;
  • домен отсутствует;
  • централизованного хранилища резервных копий нет;
  • самого централизованного резервного копирования, по большому счёту, тоже нет.

Нужно было из всего этого постепенно собрать более-менее современную инфраструктуру, которую можно нормально обслуживать и которая при выходе из строя одного сервера не положит сразу половину компании.

С чего начали

Был выбран достаточно классический вариант:

3 ноды виртуализации  
           +  
    общее хранилище  
           +  
    отдельное хранилище резервных копий

Осталось выбрать технологии.

VMware практически сразу отпадал из-за проблем с лицензированием.

Hyper-V — Windows only, чего совсем не хотелось, да и с лицензиями опять возникают те же вопросы.

Из российских платформ виртуализации те решения, которые мы смотрели, либо представляли собой сильно переработанные варианты уже существующих open source-продуктов за довольно серьёзные деньги, либо собственные разработки на базе KVM — опять же с далеко не самой скромной стоимостью.

Различные решения на базе Xen тоже рассматривались, но в нашем случае сочетание самой платформы, управления и необходимой поддержки не показалось достаточно привлекательным.

Оставался самый очевидный вариант — Proxmox VE.

Из коробки умеет кластер, HA, виртуальные машины, контейнеры, при необходимости допиливается напильником, а в интернете огромное количество документации, гайдов и просто чужого опыта о том, как всё это готовить.

На нём и остановились.

Железо под Proxmox

Нагрузка ожидалась не слишком большая, но стабильная.

При этом в распоряжении уже находились три практически одинаковых сервера, которые до этого использовались как самостоятельные машины:

  • под 1С (на win2019 1c сервер и mssql);
  • под терминальный сервер (win2019);
  • под файловую 1С (win2019) — да-да, было и такое.

После всех апгрейдов итоговая конфигурация каждой машины получилась примерно такой:

CPU:  Intel Xeon Gold 6248R  
    RAM:  512 ГБ

Для наших задач этого было более чем достаточно.

Причём мощности рассчитывались так, чтобы при выходе одной из нод из строя какое-то время можно было спокойно жить на двух оставшихся — до ремонта или замены третьей.

То есть HA нужен был прежде всего на уровне вычислительных нод:

PVE01 ─┐  
          │  
    PVE02 ─┼── Proxmox Cluster  
          │  
    PVE03 ─┘

Если одна машина умирает, её виртуальные машины можно поднять на оставшихся.

Что делать с хранилищем

С хранилищем ситуация оказалась сложнее.

Первый очевидный вариант для Proxmox-кластера — Ceph.

Для трёхнодового Proxmox-кластера мы сознательно выбрали NVMe-oF(изначально iscsi) вместо Ceph.

Ceph отлично масштабируется и умеет переживать отказ целого storage-узла, но на трёх серверах за это приходится платить повышенной задержкой, тройной репликацией данных, дополнительной нагрузкой на CPU, RAM, сеть и сами накопители.

С NVMe-oF схема значительно проще:

Proxmox → RDMA → NVMe-oF → ZFS → NVMe

В результате получаем:

  • ниже latency;
  • выше производительность одной VM;
  • меньше накладных расходов;
  • эффективнее используется дисковая ёмкость;
  • проще диагностика и обслуживание;
  • ресурсы Proxmox-нод не тратятся на работу Ceph.

Для большого кластера Ceph выглядит значительно интереснее. Но когда нод всего три и требуется быстрое общее хранилище, отдельный ZFS storage с NVMe-oF оказался для нас рациональнее.

Репликация хранилища в реальном времени нам не требовалась. Бизнес допускал простой до суток, если с основной системой хранения произойдёт что-то действительно серьёзное.

Поэтому было решено не усложнять инфраструктуру ради отказоустойчивости, которая нам фактически не требовалась.

Схема получилась такая:

Proxmox Cluster  
         │  
         ▼  
    основное общее хранилище  
         │  
         ├── запасная платформа  
         │   на складе  
         │  
         └── горячий резерв дисков

То есть на уровне Proxmox-нод у нас HA есть.

На уровне основного хранилища — нет.

Это сознательно принятая точка отказа, потому что простой до суток в случае серьёзной аварии для нас был допустим.

Если вам требуется полноценный HA вплоть до хранилища без такого окна простоя, схема уже должна быть другой.

Диски

Для основной дисковой подсистемы выбрали:

6 × NVMe SSD по 8 ТБ

В ZFS собрали пул из трёх зеркал:

ZFS pool  
    │  
    ├── mirror  
    │   ├── NVMe 8 TB  
    │   └── NVMe 8 TB  
    │  
    ├── mirror  
    │   ├── NVMe 8 TB  
    │   └── NVMe 8 TB  
    │  
    └── mirror  
       ├── NVMe 8 TB  
       └── NVMe 8 TB

Полезный объём получался около:

24 ТБ

Почему именно пул из зеркал, а не RAIDZ, здесь подробно обсуждать не будем.

Нам была важнее предсказуемость производительности и задержек, чем возможность получить несколько больший полезный объём.

Почему ZFS, а не аппаратный RAID

От аппаратного RAID тоже решили отказаться.

Использовали ZFS.

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

  • контроль целостности;
  • снапшоты;
  • сжатие;
  • дедупликацию;
  • нормальное управление самим пулом.

Дедупликацию сначала рассматривали, но в итоге отказались от неё из-за огромного расхода оперативной памяти.

А вот сжатие оставили.

На наших данных оно работало вполне прилично и в среднем обеспечивало коэффициент примерно:

x1.7

То есть экономия места уже получалась вполне заметной.

Первая версия хранилища — XigmaNAS

Первая итерация storage была собрана на XigmaNAS.

Выбор готового дистрибутива был вполне осознанным.

Нужно было учитывать не только то, кто систему собирает, но и квалификацию людей, которым потом придётся всё это администрировать.

Поэтому хотелось получить решение, где для базовых операций не требуется каждый раз лезть глубоко в Linux и вспоминать, какой именно параметр ZFS нужно сейчас поменять.

На шести NVMe собрали наш ZFS-пул из трёх зеркал.

Внутри создали отдельный блочный том:

zvol_01

И уже его начали отдавать Proxmox.

Первый вариант был через iSCSI:

6 × NVMe  
       │  
       ▼  
    ZFS pool  
    3 × mirror  
       │  
       ▼  
    zvol_01  
       │  
       ▼  
     iSCSI  
       │  
       ▼  
    Proxmox

И вот здесь нас ждал первый сюрприз.

По iSCSI получили примерно:

1000–1200 МБ/с

линейного чтения и записи.

Вроде бы не ужас.

Но при локальном тестировании сам ZFS-пул спокойно выдавал в среднем около:

6 ГБ/с

То есть теряли мы слишком много.

Прикинули скорости, задержки и начали смотреть, чем можно заменить iSCSI.

Переходим на NVMe over Fabrics

Сетевые карты у нас были Mellanox и поддерживали RDMA.

Это сразу делало достаточно интересным вариант с NVMe over Fabrics через RDMA.

Решили не придумывать велосипед и для новой версии storage взяли свежую Ubuntu 26.04.

В ней были доступны актуальные версии ZFS и необходимые нам возможности.

Сеть хранения спроектировали отдельным физическим контуром.

То есть через неё не ходит:

  • пользовательский трафик;
  • management;
  • трафик виртуальных машин;
  • backup;
  • интернет.

Только storage.

Схема адресов получилась примерно такая:

Storage: 172.16.10.10/24  
     
    PVE01:   172.16.10.11/24  
    PVE02:   172.16.10.12/24  
    PVE03:   172.16.10.13/24

Сеть хранения

Для Proxmox-нод использовали:

Mellanox 25 GbE

На storage:

Mellanox 100 GbE

В качестве коммутатора был куплен:

MikroTik CRS510-8XS-2XQ

На тот момент это оказался одним из самых доступных новых коммутаторов с нужным нам набором высокоскоростных портов.

С ним, правда, потом тоже выяснилось несколько интересных моментов.

Но об этом чуть дальше.

Настраиваем NVMe-oF/RDMA target

Ниже примерная конфигурация.

Предполагается, что ZFS-пул у вас уже создан и внутри него существует:

zvol_01

Допустим, наш ZFS-пул называется:

tank

Тогда блочное устройство будет выглядеть примерно так:

/dev/zvol/tank/zvol_01

Именно ZVOL мы будем отдавать через NVMe-oF.

Физические NVMe-диски, входящие в ZFS-пул, клиентам напрямую не отдаём.

Схема:

NVMe  
    │  
    ▼  
    ZFS pool  
    │  
    ▼  
    zvol_01  
    │  
    ▼  
    NVMe-oF / RDMA  
    │  
    ▼  
    Proxmox

Ставим пакеты

На storage:

sudo apt update  
     
    sudo apt install -y \  
     nvme-cli \  
     rdma-core \  
     infiniband-diags \  
     perftest \  
     libibverbs1 \  
     ibverbs-utils \  
     nvmetcli

Загружаем необходимые модули

Создаём:

sudo tee /etc/modules-load.d/nvmet.conf <<'EOF'  
    nvmet  
    nvmet-rdma  
    rdma_cm  
    ib_core  
    ib_uverbs  
    EOF

Применяем:

sudo systemctl restart systemd-modules-load

Проверяем:

lsmod | grep nvmet  
    lsmod | grep rdma

При необходимости можно загрузить вручную:

sudo modprobe nvmet  
    sudo modprobe nvmet-rdma  
    sudo modprobe rdma_cm  
    sudo modprobe ib_core  
    sudo modprobe ib_uverbs

Настраиваем сетевой интерфейс storage

Допустим, RDMA-интерфейс называется:

ens16

Создаём netplan:

sudo tee /etc/netplan/50-rdma.yaml <<'EOF'  
    network:  
     version: 2  
     renderer: networkd  
     
     ethernets:  
       ens16:  
         addresses:  
           - 172.16.10.10/24  
         mtu: 9600  
         optional: true  
    EOF

Применяем:

sudo netplan apply

Проверяем:

ip addr show ens16

Проверяем ZVOL

Проверяем, что наш том действительно существует:

ls -l /dev/zvol/tank/zvol_01

Это должно быть блочное устройство.

И именно:

/dev/zvol/tank/zvol_01

мы дальше экспортируем через NVMe-oF.

Получаем Host NQN Proxmox-нод

На каждой Proxmox-ноде:

cat /etc/nvme/hostnqn

Получаем три Host NQN:

PVE01 → HOST_NQN_1  
    PVE02 → HOST_NQN_2  
    PVE03 → HOST_NQN_3

Их нужно разрешить на target.

Скрипт настройки NVMe-oF Target

Создаём:

sudo tee /usr/local/bin/setup-nvmet.sh <<'EOF'  
    #!/usr/bin/env bash  
     
    set -euo pipefail  
     
    SUBSYSTEM_NQN="nqn.2025-01.com.example:nvme-target"  
     
    HOST_NQNS=(  
     "REPLACE-WITH-PVE01-HOST-NQN"  
     "REPLACE-WITH-PVE02-HOST-NQN"  
     "REPLACE-WITH-PVE03-HOST-NQN"  
    )  
     
    RDMA_IP="172.16.10.10"  
    RDMA_PORT="4420"  
     
    PORT_ID="1"  
     
    ZVOL="/dev/zvol/tank/zvol_01"  
     
    CONFIGFS="/sys/kernel/config/nvmet"  
     
    SUBSYSTEM_DIR="${CONFIGFS}/subsystems/${SUBSYSTEM_NQN}"  
    PORT_DIR="${CONFIGFS}/ports/${PORT_ID}"  
     
    [[ -d "${CONFIGFS}" ]] || {  
       echo "nvmet configfs is not mounted" >&2  
       exit 1  
    }  
     
    [[ -b "${ZVOL}" ]] || {  
       echo "ZVOL not found or is not a block device: ${ZVOL}" >&2  
       exit 1  
    }  
     
    [[ ! -e "${SUBSYSTEM_DIR}" ]] || {  
       echo "Target configuration already exists" >&2  
       exit 1  
    }  
     
    mkdir "${SUBSYSTEM_DIR}"  
     
    echo 0 > "${SUBSYSTEM_DIR}/attr_allow_any_host"  
     
    # Разрешаем подключение трём Proxmox-нодам  
     
    for HOST_NQN in "${HOST_NQNS[@]}"; do  
     
       HOST_DIR="${CONFIGFS}/hosts/${HOST_NQN}"  
     
       mkdir -p "${HOST_DIR}"  
     
       ln -s \  
         "${HOST_DIR}" \  
         "${SUBSYSTEM_DIR}/allowed_hosts/${HOST_NQN}"  
     
    done  
     
    # Создаём namespace  
     
    NAMESPACE_DIR="${SUBSYSTEM_DIR}/namespaces/1"  
     
    mkdir "${NAMESPACE_DIR}"  
     
    echo "${ZVOL}" > "${NAMESPACE_DIR}/device_path"  
     
    echo 1 > "${NAMESPACE_DIR}/enable"  
     
    # Создаём RDMA port  
     
    mkdir "${PORT_DIR}"  
     
    echo rdma > "${PORT_DIR}/addr_trtype"  
     
    echo ipv4 > "${PORT_DIR}/addr_adrfam"  
     
    echo "${RDMA_IP}" > "${PORT_DIR}/addr_traddr"  
     
    echo "${RDMA_PORT}" > "${PORT_DIR}/addr_trsvcid"  
     
    # Связываем subsystem с портом  
     
    ln -s \  
     "${SUBSYSTEM_DIR}" \  
     "${PORT_DIR}/subsystems/${SUBSYSTEM_NQN}"  
     
    echo "NVMe-oF/RDMA target configured"  
    echo "Target: ${RDMA_IP}:${RDMA_PORT}"  
    echo "ZVOL: ${ZVOL}"  
     
    EOF

Делаем исполняемым:

sudo chmod +x /usr/local/bin/setup-nvmet.sh

Скрипт очистки NVMe-oF

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

sudo tee /usr/local/bin/cleanup-nvmet.sh <<'EOF'  
    #!/usr/bin/env bash  
     
    set -euo pipefail  
     
    SUBSYSTEM_NQN="nqn.2025-01.com.example:nvme-target"  
     
    HOST_NQNS=(  
     "REPLACE-WITH-PVE01-HOST-NQN"  
     "REPLACE-WITH-PVE02-HOST-NQN"  
     "REPLACE-WITH-PVE03-HOST-NQN"  
    )  
     
    PORT_ID="1"  
     
    CONFIGFS="/sys/kernel/config/nvmet"  
     
    SUBSYSTEM_DIR="${CONFIGFS}/subsystems/${SUBSYSTEM_NQN}"  
    PORT_DIR="${CONFIGFS}/ports/${PORT_ID}"  
     
    rm -f \  
     "${PORT_DIR}/subsystems/${SUBSYSTEM_NQN}"  
     
    NAMESPACE_DIR="${SUBSYSTEM_DIR}/namespaces/1"  
     
    if [[ -d "${NAMESPACE_DIR}" ]]; then  
       echo 0 > "${NAMESPACE_DIR}/enable"  
       rmdir "${NAMESPACE_DIR}"  
    fi  
     
    for HOST_NQN in "${HOST_NQNS[@]}"; do  
     
       rm -f \  
         "${SUBSYSTEM_DIR}/allowed_hosts/${HOST_NQN}"  
     
    done  
     
    if [[ -d "${PORT_DIR}" ]]; then  
       rmdir "${PORT_DIR}"  
    fi  
     
    if [[ -d "${SUBSYSTEM_DIR}" ]]; then  
       rmdir "${SUBSYSTEM_DIR}"  
    fi  
     
    for HOST_NQN in "${HOST_NQNS[@]}"; do  
     
       HOST_DIR="${CONFIGFS}/hosts/${HOST_NQN}"  
     
       if [[ -d "${HOST_DIR}" ]]; then  
           rmdir "${HOST_DIR}"  
       fi  
     
    done  
     
    echo "NVMe-oF target cleaned up"  
     
    EOF

Права:

sudo chmod +x /usr/local/bin/cleanup-nvmet.sh

Добавляем systemd

Чтобы target автоматически поднимался после загрузки:

sudo tee /etc/systemd/system/nvmet.service <<'EOF'  
    [Unit]  
    Description=NVMe-oF Target Configuration  
     
    After=network-online.target sys-kernel-config.mount  
    Wants=network-online.target  
    Requires=sys-kernel-config.mount  
     
    [Service]  
    Type=oneshot  
    RemainAfterExit=yes  
     
    ExecStart=/usr/local/bin/setup-nvmet.sh  
    ExecStop=/usr/local/bin/cleanup-nvmet.sh  
     
    [Install]  
    WantedBy=multi-user.target  
    EOF

Перечитываем конфигурацию:

sudo systemctl daemon-reload

Добавляем в автозагрузку:

sudo systemctl enable nvmet.service

Запускаем:

sudo systemctl start nvmet.service

Проверяем:

sudo systemctl status nvmet.service

Подключаем Proxmox к NVMe-oF

Теперь переходим на одну из Proxmox-нод.

Ставим:

apt update  
    apt install -y nvme-cli rdma-core

Загружаем модуль:

modprobe nvme_rdma

Добавляем в автозагрузку:

echo "nvme_rdma" > /etc/modules-load.d/nvme-rdma.conf

Ищем target:

nvme discover \  
     -t rdma \  
     -a 172.16.10.10 \  
     -s 4420

Подключаем:

nvme connect \  
     -t rdma \  
     -n nqn.2025-01.com.example:nvme-target \  
     -a 172.16.10.10 \  
     -s 4420

Проверяем:

nvme list

Должно появиться новое устройство, например:

/dev/nvme0n1

Конкретное имя у вас, естественно, может отличаться.

Эту процедуру повторяем на всех трёх Proxmox-нодах.

Автоматическое подключение

Чтобы после перезагрузки нода снова находила target:

echo "discover -t rdma -a 172.16.10.10 -s 4420" \  
     >> /etc/nvme/discovery.conf

И включаем механизм автоподключения nvme-cli, если он присутствует в используемой версии системы:

systemctl enable nvmf-autoconnect.service

После перезагрузки обязательно проверяем:

nvme list

Не надо считать настройку законченной только потому, что ручной nvme connect один раз успешно отработал.

Создаём Volume Group

Общий ZVOL у нас один.

Все три Proxmox-ноды видят через NVMe-oF один и тот же блочный том:

                 zvol_01  
                       │  
                  NVMe-oF/RDMA  
                       │  
           ┌───────────┼───────────┐  
           │           │           │  
           ▼           ▼           ▼  
         PVE01       PVE02       PVE03

На одной из нод создаём Volume Group:

vgcreate nvme_vg /dev/nvme0n1

На остальных двух vgcreate уже не выполняем.

Они должны увидеть тот же самый VG на общем блочном устройстве.

После этого хранилище можно добавить через интерфейс Proxmox как общее LVM-хранилище для кластера.

Важно понимать, что это не три независимых диска.

Это:

один zvol_01  
         ↓  
    один nvme_vg  
         ↓  
    три Proxmox-ноды

Что получилось по скорости

После перехода с iSCSI на NVMe-oF/RDMA дисковая подсистема начала стабильно выдавать около:

3000 МБ/с

на линейном чтении и записи с одной ноды.

И это уже практически физический предел одного 25GbE-интерфейса.

Теоретический максимум:

25 Гбит/с ÷ 8 = 3,125 ГБ/с

Дальше часть полосы всё равно съедают накладные расходы протоколов.

Так что результат нас вполне устраивал.

Для сравнения:

Локальный ZFS pool: ~6000 МБ/с  
     
    iSCSI:               ~1000–1200 МБ/с  
     
    NVMe-oF/RDMA:        ~3000 МБ/с

Разница получилась более чем заметная.

Теперь немного про RDMA и MikroTik

С RDMA-сетью получилась отдельная история.

По факту на MikroTik нам не пришлось строить какую-то космическую QoS-конфигурацию.

Но здесь очень важно понимать, почему именно у нас это сработало.

Первым делом мы убедились, что коммутация нужных портов действительно идёт аппаратно через switch chip с hardware offload.

Сам по себе hardware offload RDMA, естественно, не настраивает.

Он нужен для того, чтобы такой объём трафика не начал ходить через CPU самого коммутатора.

Дальше использовали обычный Ethernet Flow Control.

Без PFC.

Почему без PFC

В большинстве гайдов по RDMA вам сразу расскажут про:

  • PFC;
  • QoS;
  • приоритеты;
  • lossless Ethernet;
  • очереди.

Всё это действительно имеет смысл.

Но наша сеть хранения была полностью отдельной.

Через неё шёл только storage/RDMA-трафик.

Никакого другого трафика там просто не было.

Поэтому в нашей конкретной схеме обычного Flow Control оказалось достаточно.

И здесь есть очень большая оговорка:

ТОЛЬКО ЕСЛИ ЧЕРЕЗ ЭТУ СЕТЬ НЕ ХОДИТ НИКАКОГО ДРУГОГО ТРАФИКА.

В чём вообще проблема

Нода подключена к коммутатору через:

25 GbE

Storage:

100 GbE

То есть storage физически может генерировать поток быстрее, чем одна конкретная нода способна его принять.

В какой-то момент приёмная сторона перестаёт успевать.

Буфер заполняется.

И нужно сказать передающей стороне:

притормози

При обычном Ethernet Flow Control для этого используются PAUSE frames.

Упрощённо:

Storage 100 GbE  
         │  
         │ слишком быстро  
         ▼  
       Switch  
         │  
         ▼  
    PVE01 25 GbE  
         │  
         ▼  
      очередь  
         │  
         ▼  
       PAUSE

Проблема в том, что обычный Flow Control не умеет сказать:

притормози только вот этот конкретный тип трафика.

Он воздействует на весь трафик соответствующего Ethernet-канала.

Если через сеть идёт только RDMA — нам всё равно.

Тормозить там больше нечего.

А вот если бы через этот же интерфейс одновременно шли:

RDMA  
    +  
    management  
    +  
    backup  
    +  
    трафик виртуальных машин

то паузы начал бы получать и весь остальной трафик.

Вот для решения этой проблемы уже используются PFC, QoS и различные очереди.

Суть — разметить определённые классы трафика и управлять ими независимо.

Но если у вас физически выделенная сеть и в ней есть только RDMA, то в нашем случае преимущества от такой сложной схемы практически не было.

Поэтому её и не делали.

Но MikroTik всё-таки преподнёс сюрприз

Другая проблема выяснилась уже во время нагрузочного тестирования.

С одной ноды всё было отлично:

PVE01 → ~3000 МБ/с

Запускаем нагрузку одновременно со второй:

PVE01 → ~3000 МБ/с  
    PVE02 → ~1500 МБ/с  
     
    Итого → ~4500 МБ/с

А локально дисковая система спокойно выдаёт:

~6000 МБ/с

Начали разбираться.

Получается примерно следующая схема:

                 STORAGE  
                     100 GbE  
                        │  
                        ▼  
                  MikroTik CRS510  
                     /       \  
                    /         \  
                25 GbE       25 GbE  
                  │             │  
                  ▼             ▼  
                PVE01         PVE02

Когда очередь на интерфейсе первой ноды заполняется, появляется сигнал притормозить передачу.

Но весь трафик со storage приходит в коммутатор через один 100GbE-интерфейс.

В результате торможение начинает влиять не только на поток, предназначенный первой ноде, но и на часть трафика, которая должна идти второй.

Упрощённо:

PVE01 не успевает  
           ↓  
         PAUSE  
           ↓  
    тормозится поток со стороны storage  
           ↓  
    заодно страдает PVE02

Поэтому при одновременной нагрузке двух нод вместо ожидаемых значений получили суммарно примерно:

4500 МБ/с

Буферы MikroTik

Всё упёрлось уже не в ZFS и не в NVMe.

Проблема оказалась в особенностях работы коммутатора и размере внутренних буферов его switch chip.

Точных официальных данных по размеру буферов конкретно для нашего сценария найти не удалось.

Но по косвенным данным и поведению под нагрузкой они заметно меньше, чем у более дорогих коммутаторов, изначально рассчитанных на подобные storage-нагрузки.

Условно те же серверные Dell в таких сценариях имеют значительно более серьёзные возможности по буферизации.

Можно было заменить коммутатор и получить ещё более красивые цифры.

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

Нам нужна была рабочая инфраструктура, а не мировой рекорд fio.

Полученной производительности для наших задач хватало с большим запасом.

Поэтому MikroTik оставили.

Что в итоге делали с RDMA-сетью

Если сильно упростить:

  1. Сделали физически отдельную сеть хранения.
  2. Поставили Mellanox 25GbE на Proxmox-ноды.
  3. Поставили Mellanox 100GbE на storage.
  4. Использовали MikroTik CRS510.
  5. Проверили аппаратную коммутацию через switch chip.
  6. Использовали jumbo frame.
  7. Включили Ethernet Flow Control.
  8. Не пускали через этот сегмент ничего, кроме storage/RDMA.
  9. Проверяли скорость не только с одной ноды, но и с нескольких одновременно.

Последний пункт оказался очень важным.

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

~3000 МБ/с

можно было бы решить, что сеть работает практически идеально.

Ограничение MikroTik стало заметно только при одновременной нагрузке нескольких серверов.

Backup-сервер

С сервером резервного копирования поступили гораздо проще.

Там никаких NVMe-oF и RDMA уже не требовалось.

Собрали ещё один storage на базе XigmaNAS:

4 × HDD по 20 ТБ

В ZFS сделали пул из двух зеркал:

Backup ZFS pool  
    │  
    ├── mirror  
    │   ├── HDD 20 TB  
    │   └── HDD 20 TB  
    │  
    └── mirror  
       ├── HDD 20 TB  
       └── HDD 20 TB

Полезный объём:

~40 ТБ

И отдали его Proxmox по обычному NFS.

Для резервных копий никаких преимуществ от усложнения схемы мы не видели.

Нужен большой объём, достаточно нормальная скорость и максимально простое восстановление.

NFS с этим прекрасно справляется.

Сеть виртуальных машин

Сеть непосредственно для виртуальных машин построили на:

10 GbE

Для неё использовали отдельные сетевые карты.

В качестве коммутатора выступил ещё один:

MikroTik CRS510-8XS-2XQ

Его уже подключили к центральному коммутатору компании через:

40 Gb DAC

Таким образом storage-сеть и обычная сеть виртуальных машин физически друг от друга отделены.

Примерно:

              ┌── Storage/RDMA 25/100 GbE  
                 │  
    Proxmox Nodes ┤  
                 │  
                 └── VM Network 10 GbE  
                            │  
                            ▼  
                    Core network  
                         40 Gb

Что получилось в итоге

В результате получили достаточно современную инфраструктуру, причём за относительно разумные деньги — если не смотреть на стоимость NVMe SSD.

В основе практически полностью open source:

Proxmox VE  
       │  
       ├── KVM  
       ├── LXC  
       │  
       ▼  
    NVMe-oF/RDMA  
       │  
       ▼  
    ZFS

Три мощные ноды позволяют пережить отказ одного физического сервера.

Общее NVMe-хранилище обеспечивает достаточную для нас производительность.

Отдельное backup-хранилище решает вопрос с резервными копиями.

Отдельные сети разделяют:

  • storage;
  • виртуальные машины;
  • остальную инфраструктуру.

Получилась схема без какой-то супердорогой проприетарной SAN и без необходимости покупать лицензии на каждый процессор, сокет, виртуальную машину и вдох администратора.

Что в итоге туда переехало

После запуска кластера начали постепенно переносить сервисы.

1С

Рабочая 1С на Ubuntu.

Если не нужны всякие решения с HASP Emulator и прочей экзотикой, можно сделать обычный контейнер и раскатать туда сервер 1С.

Отдельно:

тестовая 1С на Ubuntu

PostgreSQL

PostgreSQL тоже в контейнерах.

При желании можно под отдельные задачи или базы поднимать отдельные экземпляры.

Для наших масштабов накладные расходы от контейнеров совершенно несущественные, зато сервисы оказываются нормально разделены.

Домен

До всей этой истории домена вообще не было.

В итоге подняли два контроллера домена на:

Windows Server 2019

Лицензии на них были приобретены ещё до всех известных событий.

Терминальный сервер

Терминальный сервер тоже остался на:

Windows Server 2019

Там же развернули print server.

Лицензии также уже были.

Мониторинг

Развернули:

Zabbix

После появления нормальной централизованной инфраструктуры не мониторить всё это было бы уже довольно странно.

Телефония

Asterisk

тоже переехал в кластер.

Серверы лицензирования

Различные серверы лицензирования конфигураций 1С.

Большая часть прекрасно живёт в отдельных контейнерах.

Тестовый Битрикс24

Отдельный тестовый сервер Битрикс24 для разработки и проверки изменений перед переносом в рабочую систему.

СКУД

Система контроля и управления доступом.

И дальше постепенно туда же начали переноситься остальные внутренние сервисы.

Что намеренно не вошло в эту статью

Здесь намеренно не привожу тонкие настройки:

  • ZFS;
  • Proxmox;
  • LVM;
  • параметров виртуальных машин;
  • оптимизации PostgreSQL;
  • 1С;
  • Zabbix;
  • отдельных настроек MikroTik;
  • резервного копирования.

Каждая из этих тем сама по себе может занять отдельную статью.

Задача этого материала была другой — показать, как из исходного набора отдельных железных серверов получилась нормальная централизованная инфраструктура, какие решения для этого выбирались и где по дороге пришлось менять первоначальный план.

Причём самым интересным оказался именно storage.

Изначально всё выглядело достаточно просто:

ZFS  
    ↓  
    iSCSI  
    ↓  
    Proxmox

На практике получили:

1000–1200 МБ/с

что совершенно не соответствовало возможностям железа.

Переделали:

ZFS  
    ↓  
    zvol_01  
    ↓  
    NVMe-oF/RDMA  
    ↓  
    25 GbE  
    ↓  
    Proxmox

и получили уже:

~3000 МБ/с

с одной ноды.

Потом нагрузили две ноды одновременно — и нашли новое ограничение уже в коммутаторе.

То есть классическая история:

убрал одно узкое место  
           ↓  
    нашёл следующее  
           ↓  
    проверил, мешает ли оно реальной работе  
           ↓  
    если не мешает — остановился

Можно было купить намного более дорогой коммутатор, построить полноценную lossless fabric, сделать Ceph, добавить второе полностью синхронное хранилище и довести отказоустойчивость до совершенно другого уровня.

Но это стоило бы существенно дороже и практически ничего не дало бы компании при наших требованиях.

В итоге сделали не максимально навороченное решение, а то, которое закрывало реальную задачу.

И оно работает.

Кейс
Инфраструктура и технологии
Linux
Виртуализация
Сети
Хранилища и Бекапы
  • Войдите, чтобы оставлять комментарии
ZЦЕХ 2026 D0 B1 D0 B5 D1 81
D0 BA D0 BE D0 BD
D0 B5 D1 87 D0 BD
D0 BE D1 81 D1 82
D1 8C