
В современных реалиях внедрение каких-то фундаментальных решений требует основательного подхода.
Многие вендоры ушли с рынка РФ. Лицензии официально недоступны.
Исходные данные были такие:
- компания среднего размера;
- несколько офисов;
- около 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 GbEStorage:
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-сетью
Если сильно упростить:
- Сделали физически отдельную сеть хранения.
- Поставили Mellanox 25GbE на Proxmox-ноды.
- Поставили Mellanox 100GbE на storage.
- Использовали MikroTik CRS510.
- Проверили аппаратную коммутацию через switch chip.
- Использовали jumbo frame.
- Включили Ethernet Flow Control.
- Не пускали через этот сегмент ничего, кроме storage/RDMA.
- Проверяли скорость не только с одной ноды, но и с нескольких одновременно.
Последний пункт оказался очень важным.
Если бы мы протестировали только одну ноду:
~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С на UbuntuPostgreSQL
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, добавить второе полностью синхронное хранилище и довести отказоустойчивость до совершенно другого уровня.
Но это стоило бы существенно дороже и практически ничего не дало бы компании при наших требованиях.
В итоге сделали не максимально навороченное решение, а то, которое закрывало реальную задачу.
И оно работает.
- Войдите, чтобы оставлять комментарии