
Содержание:
Почему вообще появился этот материал
Доброго времени суток! Всё ещё продолжаю быть преподавателем по Astra Linux в одном очень хорошем учебном центре. Иногда слушатели курсов подбрасывают интересные задачи, а иногда наводят на интересные мысли. Сегодня именно такой случай.
Всё началось довольно обыденно:
- А можно, на этой вашей Астре, поднять обычный трёхузловой кластер виртуализации? - Можно конечно, Астра - она же Linux, а на линухе можно всё. У Астры даже готовые продукты есть: Vmmanager и (Брест) AIC, поднимайте не хочу. И техподдержка поможет, если нужно. - К сожалению, эти продукты для наших "изделий" избыточны. Хотелось бы чего то не такого громоздкого и желательно сертифицированного.
И вот тут начало приходить осознание. Астра позиционирует себя, как Enterprise решение (холивары на эту тему можете начинать в комментариях). И её решения действительно ориентированы на крупные или средние компании.
Мнение автора на тему
Переходим на российское ПО "потому, что (вставить нужное)". Например потому, что такие требования к крупному бизнесу и компаниям - полное импортозамещение. НО:
Российская операционная система Astra Linux (Debian).
Российская облачная платформа виртуализации
БрестAstra Infrastructure Cloud (Opennebula).Российское программно-определяемое хранилище SDS TROK (LINSTOR).
Российская платформа контейнеризации Боцман (Kubernetes).
Система управления процессами Ansible в России - Astra Automation (Ansible AWX).
Для чистой совести: Астра вносит в указанные продукты существенные изменения и доработки. Не все продукты Астры "вдохновлены" сторонними решениями. Есть и самобытные продукты, написанные с нуля (например, RuBackup и Vmmanager). Также никто не отменяет техподдержку, которую компания оказывает по своим продуктам.
Но это не тема данной статьи, а просто мысли автора на тему.
Для небольших компаний (и маленьких развертываний) у Астры решений чуть меньше.
В свое время "мелкомягкие" очень удачно заняли рынок, подсадив на себя в т.ч. и малый бизнес. А всё за счет решений, направленных на небольшие развертывания.
Небольшое развертывание хочет небольшой масштабируемый кластер из трех (а еще лучше двух) узлов и какую-нибудь понятную и удобную хранилку. В Астре такого решения сейчас нет. Поэтому приходится собирать его самостоятельно на проверенных годами технологиях.
Сразу отмечу, что в задачу небольшого (и даже большого) развертывания идеально вписывается Proxmox, но
Астра его еще не форкнула, чтобы продавать, сертифицированного под ФСТЭК Proxmox сейчас на рынке нет.
Требования к кластеру виртуализации
Общее отказоустойчивое хранилище (блочное).
Высокая доступность виртуальных машин.
Автоматическое восстановление при сбое .
Собран только из компонентов сертифицированного репозитория main.
Должен работать на максимальном (
Смоленск) уровне защищенности ОС.
Выбор компонентов
Стек виртуализации
Особого выбора по поводу стека виртуализации и не было. На установочном диске и сертифицированном репозитории есть следующие:
KVM/Qemu + Libvirt + Virsh + Virt-Manager
Общее хранилище
Изначально идея была очень простой - Ceph.
Какие вообще альтернативы ?
Но душа хотела извращений праздника, поэтому был рассмотрен вариант в DRBD и gfs2. В целом решение интересное и более привычное обычному пользователю, который переходит с vmware.
Два тестовых стенда:
KVM + GFS2/DRBD + ISCSI: 2 узла хранения и 3 узла виртуализации
Буду отделять узлы хранения (storage) от узлов виртуализации (compute). В целом, их можно и не разделять. Но всё же нужно заложить возможность масштабирования и отказоустойчивости.
┌─────────────┐ ┌─────────────┐ │ DRBD-узел │◄──►│ DRBD-узел │ ← Синхронная репликация блочных устройств │ (drbd1) │ │ (drbd2) │ └──────┬──────┘ └──────┬──────┘ │ │ └──────────────────┘ │ iSCSI Target (Pacemaker) │ ┌─────────┴───────┐──────────────────┐ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ KVM-узел 1 │ │ KVM-узел 2 │ │ KVM-узел 3 │ │ (kvm1) │ │ (kvm2) │ │ (kvm3) │ └─────────────┘ └─────────────┘ └─────────────┘ └───────────────┬───────────────┘ ▼ GFS2 (кластерная ФС)
KVM + CEPH: 3 узла хранения и 3 узла виртуализации
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ CEPH-узел 1 │ │ CEPH-узел 2 │ │ CEPH-узел 3 │ │ (storage1) │◄──►│ (storage2) │◄──►│ (storage3) │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────────────────┼──────────────────┘ ▼ CEPH Cluster (RADOS) │ ┌──────────────────┼──────────────────┐ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ KVM-узел 1 │ │ KVM-узел 2 │ │ KVM-узел 3 │ │ (kvm1) │ │ (kvm2) │ │ (kvm3) │ └─────────────┘ └─────────────┘ └─────────────┘
Учетные данные, имена станций и сети
Для простоты используем следующие учетные данные:
user: sa password: password
Имена станций:
drbd1 -> узел хранения данных №1 drbd2 -> узел хранения данных №2 kvm1 -> узел виртуализации №1 kvm2 -> узел виртуализации №2 kvm3 -> узел виртуализации №3
Две сети:
storage (движение трафика хранилки) -> 10.10.10.0/24 -> Isolate Network manager(движение трафика pacemaker) -> 172.16.10.0/24 -> Nat Network
Я ставлю это в виртуальной среде, поэтому буду использовать проект virtual BMC для реализации IPMI интерфейсов. Ccылки на virtualbmc: первая, вторая.
Node | Storage-net-ip | Manager-Net-ip | ipmi-address |
|---|---|---|---|
drbd1 | 10.10.10.11 | 172.16.10.11 | 10.10.10.1:6231 |
drbd2 | 10.10.10.12 | 172.16.10.12 | 10.10.10.1:6232 |
drbd | 10.10.10.10 | - | - |
kvm1 | 10.10.10.21 | 172.16.10.21 | 10.10.10.1:6233 |
kvm2 | 10.10.10.22 | 172.16.10.22 | 10.10.10.1:6234 |
kvm3 | 10.10.10.23 | 172.16.10.23 | 10.10.10.1:6235 |
ceph1 | 10.10.10.31 | 172.16.10.31 | - |
ceph2 | 10.10.10.32 | 172.16.10.32 | - |
ceph3 | 10.10.10.33 | 172.16.10.33 | - |
В файле /etc/hosts будут записи из Manager Network.
Настройка хранилища на DRDB под управлением Pacemaker
Про Pacemaker и Corosync
У pacemaker отличная официальная документация и lab-гайды.
Pacemaker - это менеджер ресурсов нашего кластера, он отвечает за их правильный запуск, за управление их клонами и так далее. А Corosync - удобный способ взаимодействия разных экземпляров Pacemaker.
Выжимка из официальной документации Astra Linux
В состав ОС входит набор программного обеспечения Pacemaker и Corosync, используемого для построения кластерных систем высокой доступности.
Основные особенности Pacemaker и Corosync:
обнаружение и восстановление после сбоев узлов и служб;
независимость от подсистемы хранения — не требуется общее хранилище;
независимость от типов ресурсов — все что может быть выполнено путем запуска сценария, может быть кластеризовано;
поддержка кластеров любого размера;
поддержка кворумных и ресурсозависимых кластеров;
поддержка избыточной конфигурации;
автоматическая репликация конфигурации, может быть обновлена с любого узла кластера;
возможность задания порядка запуска ресурсов независимо от того, на каком узле они находятся;
поддержка ресурсов, запускаемых на множестве узлов, — клонов;
поддержка ресурсов с мульти-режимами работы (master/slave, primary/secondary).
С точки зрения кластера все используемые сущности: службы, точки монтирования, тома и разделы — это ресурсы, поэтому в данном руководстве под словом «ресурс» понимается все, что находится под управлением кластера.
И про DRBD
DRBD (Distributed Replicated Block Device) - это программная система репликации данных для Linux, работающая как «сетевой RAID-1». Она обеспечивает высокую доступность (HA), зеркалируя блочные устройства (жесткие диски, разделы, LVM) между серверами по сети. DRBD синхронно или асинхронно копирует данные, позволяя при сбое основного узла мгновенно переключиться на резервный, обеспечивая непрерывность работы.
Установка пакетов и открытие портов
Для организации хранилища виртуальных машин я выбрал отказоустойчивую схему из двух узлов на drbd.
Список пакетов и метапакетов, которые нужно установить:
pacemaker
pcs
astra-resource-agents
chrony
ipmitool
linux-6.12-generic
drbd-utils
dlm-controld
Я включил в список пакетов ядро 6.12 по той причине, что там находятся модули ядра, которые нужны для версии drbd 9 (ссылка, где это обсуждают). Плюс на момент релиза Астры 1.8.4 ядро 6.12 - самое новое, которое доступно. Поэтому у меня будут команды по установке и удалению ядер.
Следующие команды выполняем на каждом узле drbd.
Устанавливаем пакеты:
$ sudo apt install pacemaker pcs astra-resource-agents chrony $ sudo apt install ipmitool $ sudo apt install linux-6.12-generic \ linux-astra-modules-6.12.47-1-generic \ linux-headers-6.12-generic $ sudo apt install targetcli-fb $ sudo apt install drbd-utils drbd-6.12-generic $ sudo apt install dlm-controld
Перезагружаем систему и загружаемся с новым ядром. Удаляем старое:
$ sudo apt remove linux-6.1 $ sudo apt remove linux-6.1-generic $ sudo apt remove linux-image-6.1.152-1-generic $ sudo apt autoremove
Я поставил службу chrony (для точной синхронизации системных часов).
Сервера ntp - внутренние. Полезная информация про chrony.
Настраиваем службу:
$ echo "confdir /etc/chrony/conf.d server 192.168.2.254 iburst server 192.168.29.254 iburst server 192.168.28.254 iburst server 192.168.32.254 iburst sourcedir /run/chrony-dhcp sourcedir /etc/chrony/sources.d keyfile /etc/chrony/chrony.keys driftfile /var/lib/chrony/chrony.drift ntsdumpdir /var/lib/chrony logdir /var/log/chrony maxupdateskew 100.0 rtcsync makestep 1 3 leapsectz right/UTC " | sudo tee /etc/chrony/chrony.conf $ sudo systemctl restart chrony
Если у вас на станции установлен firewalld, то нужно открыть порты, которые используются службами pacemaker, drbd, dlm:
$ sudo firewall-cmd --permanent --add-service=high-availability $ sudo firewall-cmd --permanent --add-port=7788/tcp $ sudo firewall-cmd --permanent --add-port=21064/tcp $ sudo firewall-cmd --reload
- TCP ports: 2224 (for the `pcsd` daemon), 3121, and 21064. - UDP ports: 5404 and 5405 (for Corosync cluster communication).
Настройка кластера PCS drbdcluster
Далее настраиваем кластер. В целом настройка такая же, как и в документации Астры и на вики.
На каждом узле выполняю команду:
$ sudo usermod -p $(openssl passwd "password") hacluster $ sudo pcs cluster destroy
Далее на одном из узлов (не имеет значения будет это узел drbd1 или drbd2, главное, чтобы была связность между хостами по имени):
$ sudo pcs host auth drbd1 drbd2 -u hacluster -p "password" $ sudo pcs cluster setup drbdcluster drbd1 drbd2 --force $ sudo pcs cluster start --all $ sudo pcs cluster enable --all
После этого команда pcs будет работать на каждом узле и вносить изменения в кластер "drbdcluster". Поэтому команду "pcs" можно запускать на любом узле кластера.
Кластер создан.
Настройка механизмов Fencing и STONITH
Fencing - это процесс изоляции узла. В нашем случае это IPMI консоль которая управляет нашим виртуальным сервером.
IPMI - это устройство (fence device), с помощью которого выполняется концепция STONITH ("Выстрели другому узлу в голову") для физического сервера.
STONITH позволяет приводить узлы к известному состоянию в случае сбоя (например, выключить узел, когда он завис). Почитать дополнительно можно тут и тут.
Проверим, что наш кластер доступен и принимает команды по IPMI:
$ ipmitool -I lanplus -U admin -P password \ -H 10.10.10.1 -p 6231 power status
Создадим ресурсы для STONITH:
$ sudo pcs stonith create fence-drbd1 fence_ipmilan \ ip="10.10.10.1" ipport="6231" \ username="admin" \ password="password" \ pcmk_host_list="drbd1" \ lanplus=1 op monitor interval=60s $ sudo pcs stonith create fence-drbd2 fence_ipmilan \ ip="10.10.10.1" ipport="6232" \ username="admin" \ password="password" \ pcmk_host_list="drbd2"\ lanplus=1 op monitor interval=60s
Создадим ресурсы drbd:
1. Для начала на каждом узле создадим описание ресурсов.
Содержимое файла /etc/drbd.d/drbd_stor1.res:
resource drbd_stor1 { net { # allow-two-primaries yes; protocol C; fencing resource-and-stonith; } options { quorum majority; on-no-quorum suspend-io; } startup { wfc-timeout 30; degr-wfc-timeout 60; } handlers { fence-peer "/usr/lib/drbd/crm-fence-peer.9.sh"; after-resync-target "/usr/lib/drbd/crm-unfence-peer.9.sh"; } connection-mesh { hosts drbd1 drbd2; } on drbd1 { address 10.10.10.11:7788; node-id 0; volume 0 { device /dev/drbd0; disk /dev/vdb; meta-disk internal; } } on drbd2 { address 10.10.10.12:7788; node-id 1; volume 0 { device /dev/drbd0; disk /dev/vdb; meta-disk internal; } } }
2. На каждом узле кластера "drbdcluster" (drbd1, drbd2) проинициализируем диски drbd:
$ sudo drbdadm create-md drbd_stor1 $ echo drbd | sudo tee /etc/modules-load.d/drbd.conf $ sudo drbdadm up drbd_stor1
3. На узле drbd1 диск назначаем primary. Делаем это для того, чтобы произошла первая синхронизация. Далее за выбор primary будет отвечать pacemaker:
$ sudo drbdadm -- --force primary drbd_stor1
4. Ждем синхронизации дисков:
$ sudo drbdadm status drbd_stor1 role:Primary disk:UpToDate drbd2 role:Secondary replication:SyncSource peer-disk:Inconsistent done:74.00
5. После успешной синхронизации:
$ sudo drbdadm status drbd_stor1 role:Secondary disk:UpToDate drbd2 role:Secondary peer-disk:UpToDate
6. И создаем ресурсы pacemaker, чтобы дальше он управлял устройствами DRBD:
$ sudo pcs resource create storage_drbd \ ocf:linbit:drbd drbd_resource=drbd_stor1 \ op monitor interval=1 $ sudo pcs resource promotable storage_drbd \ promoted-max=1 promoted-node-max=1 \ clone-max=2 clone-node-max=1 \ notify=true $ sudo pcs resource cleanup storage_drbd $ sudo pcs status --full
7. Создадим cluster IP, который будет переезжать вместе с iscsi target:
$ sudo pcs resource create ClusterIP \ ocf:heartbeat:IPaddr2 ip=10.10.10.10 \ cidr_netmask=24 nic=enp2s0 op monitor interval=30s
8. Настраиваем iscsi target (вдохновение искал тут). Установим пакет:
$ sudo apt install targetcli-fb
9. Создаем ресурсы ISCSI для pacemaker:
$ sudo pcs resource create "p_iSCSITarget" ocf:heartbeat:iSCSITarget \ iqn="iqn.2026-02.iscsi.drbd" portals="10.10.10.10:3260" \ op monitor interval="10s" $ sudo pcs resource create "p_iSCSI_lun1" ocf:heartbeat:iSCSILogicalUnit \ target_iqn="iqn.2026-02.iscsi.drbd" lun="1" path="/dev/drbd0" \ op monitor interval="10s"
10. Далее добавляем ресурсы в одну группу g-iscsi и ограничиваем их для запуска на одном и том же хосте:
$ sudo pcs resource group add g-iscsi p_iSCSITarget $ sudo pcs resource group add g-iscsi p_iSCSI_lun1 $ sudo pcs resource group add g-iscsi ClusterIP $ sudo pcs constraint order promote \ storage_drbd-clone then start g-iscsi $ sudo pcs constraint colocation g-iscsi with \ promoted storage_drbd-clone score=INFINITY
11. Проверяем, что всё корректно работает:
$ sudo pcs status Cluster name: drbdcluster Cluster Summary: * Stack: corosync (Pacemaker is running) * Current DC: drbd1 (version 3.0.0-3.0.0) - partition with quorum * Last updated: Sat Feb 14 09:28:55 2026 on drbd1 * Last change: Fri Feb 13 14:06:09 2026 by root via root on drbd1 * 2 nodes configured * 7 resource instances configured Node List: * Online: [ drbd1 drbd2 ] Full List of Resources: * fence-drbd1 (stonith:fence_ipmilan): Started drbd1 * fence-drbd2 (stonith:fence_ipmilan): Started drbd2 * Clone Set: storage_drbd-clone [storage_drbd] (promotable): * Promoted: [ drbd1 ] * Unpromoted: [ drbd2 ] * Resource Group: g-iscsi: * p_iSCSITarget (ocf:heartbeat:iSCSITarget): Started drbd1 * p_iSCSI_lun1 (ocf:heartbeat:iSCSILogicalUnit): Started drbd1 * ClusterIP (ocf:heartbeat:IPaddr2): Started drbd1 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
Настройка KVM узлов
Подготовка узлов
Подготовим узлы, установим нужные пакеты, добавим пользователям группы и откроем порты. Для KVM требования по ядру нет, но для единообразия буду ставить 6.12.
1. Устанавливаем пакеты:
$ sudo apt install pacemaker pcs astra-resource-agents chrony $ sudo apt install ipmitool $ sudo apt install linux-6.12-generic \ linux-astra-modules-6.12.47-1-generic linux-headers-6.12-generic $ sudo apt install drbd-utils drbd-6.12-generic $ sudo apt install gfs2-utils $ sudo apt install dlm-controld $ sudo apt install astra-kvm
2. Перезагружаем систему и загружаемся с новым ядром:
$ sudo apt remove linux-6.1 $ sudo apt remove linux-6.1-generic $ sudo apt remove linux-image-6.1.152-1-generic $ sudo apt autoremove
Пакет astra-kvm в обязательном порядке устанавливает firewalld, поэтому нужно обязательно добавить разрешения для корректной работы служб:
$ sudo firewall-cmd --permanent --add-service=high-availability $ sudo firewall-cmd --permanent --add-port=7788/tcp $ sudo firewall-cmd --permanent --add-port=21064/tcp $ sudo firewall-cmd --permanent --add-service=libvirt $ sudo firewall-cmd --permanent --add-port=49152-49215/tcp $ sudo firewall-cmd --reload
3. Снова настраиваем кластера pacemaker: один для хранилища, а другой для kvm.
Можно всё было бы сделать в рамках одного кластера, но тогда нужно не забыть прописать ограничения по запуску ресурсов.
$ sudo pcs host auth kvm1 kvm2 kvm3 -u \ hacluster -p "password" $ sudo pcs cluster setup kvmcluster kvm1 kvm2 kvm3 --force $ sudo pcs stonith create fence-kvm1 fence_ipmilan \ ip="10.10.10.1" ipport="6233" username="admin" \ password="password" pcmk_host_list="kvm1" lanplus=1 op monitor interval=60s $ sudo pcs stonith create fence-kvm2 fence_ipmilan \ ip="10.10.10.1" ipport="6234" username="admin" \ password="password" pcmk_host_list="kvm2" lanplus=1 op monitor interval=60s $ sudo pcs stonith create fence-kvm3 fence_ipmilan \ ip="10.10.10.1" ipport="6235" username="admin" \ password="password" pcmk_host_list="kvm3" lanplus=1 op monitor interval=60s
4. Настроим iscsi initiator (подглядел тут):
$ sudo apt install open-iscsi
5. В /etc/iscsi/iscsid.conf вносим следующие изменения:
node.startup = automatic node.leading_login = No node.session.auth.username = iqn.2026-02.iscsi.drbd
6. А в /etc/iscsi/initiatorname.iscsi следующие:
InitiatorName=iqn.2026-02.iscsi.kvm<номер узла>
7. Подключаем iscsi диск:
$ sudo systemctl start iscsi $ sudo iscsiadm -m discovery -t st -p drbd $ sudo iscsiadm -m node -l
8. Проверка дисков:
$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sda 8:0 0 50G 0 disk vda 253:0 0 20G 0 disk ├─vda1 253:1 0 600M 0 part /boot/efi └─vda2 253:2 0 19.4G 0 part /
Появился диск sda - на нем в дальнейшем и буду делать GFS2.
Создание кластерной файловой системы
Чтобы кластерная файловая система корректно работала, нужно завести менеджер блокировок.
1. Настройка dlm - нужен для корректной работы gfs2 (документация по dlm):
$ sudo pcs resource create dlm ocf:pacemaker:controld \ op monitor interval="60" timeout="60" $ sudo pcs resource group add g-storage dlm $ sudo pcs resource clone g-storage \ meta interleave=true target-role=Starte
2. Настройка gfs2 (документация по gfs2):
$ sudo mkfs.gfs2 -t kvmcluster:gfs2 \ -p lock_dlm -j 3 \ /dev/sda $ sudo pcs resource create gfs2 \ ocf:heartbeat:Filesystem directory="/labs" fstype=gfs2 \ device="/dev/sda" op monitor interval=20 timeout=40 \ op start timeout=60 interval=0 \ op stop timeout=60 interval=0 $ sudo pcs resource group add g-storage gfs2
Здесь:
kvmcluster -> имя моего кластера
gfs2 -> тип файловой системы
lock_dlm -> менеджер блокировок
-j 3 -> количество журналов файловой системы (по числу узлов)
Отличная статья для прочтения по установке компонентов виртуализации.
Немного про настройку root
Pacemaker для запуска виртуальных машин использует пользователя root, но в астре root уже не торт и его ограничивают, поэтому нужно обязательно накинуть ему группы libvirt, libvirt-qemu, libvirt-admin.
Самое забавное, что при обновлении системы и компонентов виртуализации эти группы у него будут удалены, так что после обновления системы нужно быть готовым к неожиданным последствиям.
Чтобы была возможность миграции виртуальных машин - разрешаем доступ по ssh между узлами.
1. Команды выполняем на каждом узле:
$ sudo usermod -a -G kvm,libvirt,libvirt-qemu,libvirt-admin root $ sudo usermod -a -G kvm,libvirt,libvirt-qemu,libvirt-admin $USER $ ssh-keygen $ ssh-copy-id kvm1 $ ssh-copy-id kvm2 $ ssh-copy-id kvm3
При тестировании миграции vm было выявлено, что агенты pacemaker запускаются от имени root. Требуется, чтобы пользователь root мог ходить на узлы кластера (в нашем случае как "sa").
Добавляем следующие команды:
$ sudo bash << END ssh-keygen ssh-copy-id sa@kvm1 ssh-copy-id sa@kvm2 ssh-copy-id sa@kvm3 END
Настройка ресурсов KVM для Pacemaker
Для удобства добавлю переменную LIBVIRT_DEFAULT_URI, чтобы не добавлять "qemu:///system" для каждой команды virsh:
$ echo 'export LIBVIRT_DEFAULT_URI="qemu:///system"' >> ~/.bashrc source ~/.bashrc
1. Открываем порты:
порт 49152 по tcp для миграции в явном виде,
порт 5900 по tcp, чтобы в будущем поставить виртуальную машину и иметь к ней доступ по spice.
$ sudo firewall-cmd --add-port=5900/tcp --permanent $ sudo firewall-cmd --add-port=49152/tcp --permanent $ sudo firewall-cmd --reload
2. Метки безопасности
Размещаем машины в каталоге labs. Чтобы Астра могла там создавать виртуальные, выставляем метки безопасности:
$ sudo mkdir -p /labs/{iso,disk,xml} $ sudo pdpl-file 3:63:-1:ccnr /labs/ $ sudo pdpl-file 3:63:-1:ccnr -R /labs/disk/
3. Установка системы
Производим установку системы с помощью команд из консоли, пока что без привязки к кластеру pacemaker, т.к. нам нужно получить:
файл template.qcow2, который будет шаблоном диска для ВМ,
файл template.xml, чтобы использовать его как шаблон конфигурации ВМ.
$ sudo mkdir /labs/{iso,disk,xml} $ virt-install \ --name tempalte \ --ram 2048 \ --vcpus 2 \ --disk path=/labs/disk/template.qcow2,size=20,format=qcow2 \ --cdrom /labs/iso/installation-1.8.4.48-30.10.25_09.18.iso \ --os-variant debian12 \ --network network=default \ --graphics spice,listen=0.0.0.0 \ --video qxl \ --channel spicevmc,target_type=virtio,name=com.redhat.spice.0
4. Подключаемся к виртуальной машине с помощью remote-viewer:
Под винду тоже есть приложение.
$ remote-viewer spice://kvm1:5900
Далее идет обычная настройка виртуальной машины. Под вашу задачу настраиваете шаблон самостоятельно. Я бы еще добавил установку qemu-guest-agent в этот шаблон виртуальной машины.
5. Сохраняем описание машины в файл для того, чтобы потом на его основе определить другие:
$ virsh dumpxml astra-vm | sudo tee /labs/xml/template.xml
6. Сделаем первую машину astra-vm на основе файла template.xml. Отдадим её под управление pacemaker:
$ sudo cp /labs/xml/template.xml /labs/xml/astra-vm.xml $ sudo cp /labs/disk/template.qcow2 /labs/disk/template.qcow2
В файле /labs/disk/template.qcow2 я меняю "template" на "astra-vm". Это касается секции с именем машины и диском. Также я удаляю строку, где указан uuid машины - libvirt сгенерирует их сам. Также удаляю явное указание mac адресов.
7. Создаем ресурс pacemaker:
$ sudo pcs resource create astra-vm \ ocf:heartbeat:VirtualDomain \ hypervisor="qemu:///system" \ config="/labs/xml/astra-vm.xml" \ migration_transport="ssh" \ migration_user="sa" meta \ allow-migrate="true"
Вывод команды sudo pcs status:
$ sudo pcs status Cluster name: kvmcluster Cluster Summary: * Stack: corosync (Pacemaker is running) * Current DC: kvm1 (version 3.0.0-3.0.0) - partition with quorum * Last updated: Sat Feb 14 09:21:32 2026 on kvm1 * Last change: Sat Feb 14 09:21:29 2026 by hacluster via hacluster on kvm2 * 3 nodes configured * 11 resource instances configured Node List: * Online: [ kvm1 kvm2 kvm3 ] Full List of Resources: * ClusterIP (ocf:heartbeat:IPaddr2): Started kvm1 * Clone Set: g-storage-clone [g-storage]: * Started: [ kvm1 kvm2 kvm3 ] * fence-kvm1 (stonith:fence_ipmilan): Started kvm2 * fence-kvm2 (stonith:fence_ipmilan): Started kvm3 * fence-kvm3 (stonith:fence_ipmilan): Started kvm1 * astra-vm (ocf:heartbeat:VirtualDomain): Started kvm3 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
В дополнение можно проверить, что машина будет корректно перезапускаться на другом узле в случае "неприятностей":
$ sudo pcs stonith fence kvm3
Вот что получится:
sa@kvm1:~$ sudo pcs status Cluster name: kvmcluster Cluster Summary: * Stack: corosync (Pacemaker is running) * Current DC: kvm1 (version 3.0.0-3.0.0) - partition with quorum * Last updated: Sat Feb 14 10:20:51 2026 on kvm1 * Last change: Sat Feb 14 09:21:29 2026 by hacluster via hacluster on kvm2 * 3 nodes configured * 11 resource instances configured Node List: * Online: [ kvm1 kvm2 ] * OFFLINE: [ kvm3 ] Full List of Resources: * ClusterIP (ocf:heartbeat:IPaddr2): Started kvm1 * Clone Set: g-storage-clone [g-storage]: * Started: [ kvm1 kvm2 ] * Stopped: [ kvm3 ] * fence-kvm1 (stonith:fence_ipmilan): Started kvm2 * fence-kvm2 (stonith:fence_ipmilan): Started kvm1 * fence-kvm3 (stonith:fence_ipmilan): Started kvm2 * astra-vm (ocf:heartbeat:VirtualDomain): Starting kvm1 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
Настройка общего блочного хранилища Ceph
Установка пакетов и открытие портов
Список пакетов и метапакетов которые нужно установить:
ceph
ceph-mgr
ceph-osd
ceph-mon
chrony
$ sudo apt install ceph chrony
Если был дополнительно установлен firewalld, то открываем порты:
$ sudo firewall-cmd --permanent --add-service=ceph $ sudo firewall-cmd --permanent --add-service=ceph-mon $ sudo firewall-cmd --reload
Ставим ceph вручную
Дисклеймер Автор не является экспертом по настройке и эксплуатации хранилища ceph.
Я не волшебник, я только учусь.
Настройка общего хранилища ceph на данном этапе его развития происходит с помощью утилиты cephadm и настраивается в контейнерной среде podman или docker. В целом для Астры такой подход применим... но только если мы не используем МКЦ или МРД.
Развертывание ceph через cephadm в Астре в режиме защищенности выше "базового" не работает.
Не работает, потому что контейнеры ceph сделаны на базе rocky linux, который ничего не знает про систему безопасности parcec.
(Я нашел обходные пути и ставил нулевые метки на диски которые нужны для ceph, но сейчас не про это).
Будем устанавливать сeph вручную.
Официальная документация дистрибутива или официальная документация ceph.
Развертывание Ceph
Пример развертывания распределённого хранилища на базе кластера Ceph из трёх узлов:
ceph1, ceph2, ceph3.
На узлах будут запущены службы:
MONиOSD- на всех узлах;MGR- только наceph1(но можно держать копию на других узлах)
Конфигурация предназначена для ознакомления и тестирования.
На боевом объекте не рекомендуется размещать службы MON и OSD на одном узле.
Условия и параметры среды
В каждом узле:
vda- ОСvdb- диск под данные Ceph
У меня будет две сети Public/Cluster:
node1: 172.16.10.31/10.10.10.11 node2: 172.16.10.32/10.10.10.12 node3: 172.16.10.33/10.10.10.13
Порядок развёртывания:
Инициализация первого MON
Добавление остальных MON
Добавление службы MGR
Развёртывание OSD
1. Инициализация первого MON
Генерация UUID кластера:
$ uuidgen пример: f98c5e15-6736-41e9-966d-e38798029719`
Создание
/etc/ceph/ceph.conf:
[global] fsid = f98c5e15-6736-41e9-966d-e38798029719 mon initial members = ceph1,ceph2,ceph3 mon host = [v2:172.16.10.31:3300/0,v1:172.16.10.31:6789/0] public network = 172.16.10.0/24 cluster network = 10.10.10.0/24 auth_allow_insecure_global_id_reclaim = false osd_pool_default_pg_autoscale_mode = on
Создание ключей:
$ sudo ceph-authtool --create-keyring /tmp/ceph.mon.keyring \ --gen-key -n mon. --cap mon 'allow *' $ sudo ceph-authtool \ --create-keyring /etc/ceph/ceph.client.admin.keyring \ --gen-key -n client.admin \ --cap mon 'allow *' --cap osd 'allow *' \ --cap mds 'allow *' --cap mgr 'allow *' $ sudo ceph-authtool /tmp/ceph.mon.keyring \ --import-keyring /etc/ceph/ceph.client.admin.keyring $ sudo ceph-authtool \ --create-keyring /var/lib/ceph/bootstrap-osd/ceph.keyring \ --gen-key -n client.bootstrap-osd \ --cap mon 'profile bootstrap-osd' \ --cap mgr 'allow r' $ sudo ceph-authtool /tmp/ceph.mon.keyring \ --import-keyring /var/lib/ceph/bootstrap-osd/ceph.keyring
Генерация MON-карты:
$ sudo monmaptool --create \ --add node1 172.16.10.31 \ --fsid f98c5e15-6736-41e9-966d-e38798029719 /tmp/monmap
Инициализация и запуск MON:
$ sudo mkdir -p /var/lib/ceph/mon/ceph-ceph1 $ sudo ceph-mon --mkfs -i ceph1 \ --monmap /tmp/monmap \ --keyring /tmp/ceph.mon.keyring $ sudo chown -R ceph:ceph /var/lib/ceph/mon $ sudo systemctl enable ceph-mon.target $ sudo systemctl enable ceph-mon@ceph1 $ sudo systemctl start ceph-mon@ceph1
Проверка:
$ sudo ceph mon enable-msgr2 $ sudo ceph -s
2. Добавлен��е остальных MON (node2, node3)
На
node1обновить конфигурацию:
mon initial members = ceph1,ceph2,ceph3 mon host = 10.10.10.31,10.10.10.32,10.10.10.33
$ ssh-keygen $ ssh-copy-id ceph1 $ ssh-copy-id ceph2 $ -copy-id ceph3
На ceph2 и ceph3:
$ ssh sa@10.10.10.31 "cat /etc/ceph/ceph.conf" | sudo tee /etc/ceph/ceph.conf $ ssh sa@10.10.10.31 "sudo -S cat /etc/ceph/ceph.client.admin.keyring" | sudo tee /etc/ceph/ceph.client.admin.keyring $ sudo ceph mon getmap -o /tmp/ceph.map $ sudo ceph auth get mon. -o /tmp/ceph.mon.keyring
Инициализация ceph2 / ceph3: (то же для node3)
$ sudo ceph-mon -i ceph2 --mkfs \ --monmap /tmp/ceph.map --keyring /tmp/ceph.mon.keyring $ sudo chown -R ceph:ceph /var/lib/ceph/mon/ceph-ceph2 $ sudo systemctl enable --now ceph-mon@ceph2
3. Добавление службы MGR
На
ceph1:
$ sudo mkdir /var/lib/ceph/mgr/ceph-ceph1 $ sudo ceph auth get-or-create mgr.$(hostname -s) \ mon 'allow profile mgr' \ osd 'allow *' mds 'allow *' \ -o /var/lib/ceph/mgr/ceph-ceph1/keyring $ sudo chown -R ceph:ceph /var/lib/ceph/mgr $ sudo systemctl enable ceph-mgr@ceph1 --now
В целом добавление MGR можно сделать и на других узлах ceph, но в конкретный момент времени он будет работать только на одном. Также это добавит отказоустойчивость для MGR.
4. Развертывание OSD (ceph1, ceph2, ceph3)
На ceph2 и ceph3:
$ ssh sa@10.10.10.31 "sudo -S cat /var/lib/ceph/bootstrap-osd/ceph.keyring" | sudo tee /var/lib/ceph/bootstrap-osd/ceph.keyring
Инициализация OSD на каждом узле:
$ sudo ceph-volume lvm create --data /dev/vdb
Проверка:
$ sudo ceph -s cluster: id: f98c5e15-6736-41e9-966d-e38798029719 health: HEALTH_OK services: mon: 3 daemons, quorum ceph1,ceph2,ceph3 (age 7m) mgr: ceph1(active, since 5m), standbys: ceph2, ceph3 osd: 3 osds: 3 up (since 23s), 3 in (since 36s) data: pools: 1 pools, 1 pgs objects: 2 objects, 449 KiB usage: 62 MiB used, 150 GiB / 150 GiB avail pgs: 1 active+clean
Добавление хранилища Ceph в кластер KVM
Отмечу, что мне очень помогла эта статья и я во многом опираюсь на нее.
1. Создаем пул ceph для хранения дисков виртуальных машин:
$ sudo ceph osd pool create libvirt-pool
2. Выдаем права на этот пул и создаем ключи для аутентификации:
$ sudo ceph auth \ get-or-create "client.libvirt" \ mon "profile rbd" \ osd "profile rbd pool=libvirt-pool" | \ tee ceph.client.libvirt.keyring
3. Копируем на хосты минимальную конфигурацию кластера ceph и ключи админа, чтобы с узлов kvm тоже можно было управлять кластером:
$ sudo ceph config generate-minimal-conf | \ tee ceph.conf $ cat ceph.conf | ssh kvm1 \ sudo tee /etc/ceph/ceph.conf $ cat ceph.conf | ssh kvm2 \ sudo tee /etc/ceph/ceph.conf $ cat ceph.conf | ssh kvm3 \ sudo tee /etc/ceph/ceph.conf
$ cat /etc/ceph/ceph.client.admin.keyring | ssh kvm1 \ sudo tee /etc/ceph/ceph.client.admin.keyring $ cat /etc/ceph/ceph.client.admin.keyring | ssh kvm2 \ sudo tee /etc/ceph/ceph.client.admin.keyring $ cat /etc/ceph/ceph.client.admin.keyring | ssh kvm3 \ sudo tee /etc/ceph/ceph.client.admin.keyring
4. На каждом узле KVM установим пакеты, необходимые для работы с хранилищем ceph:
$ sudo apt install libvirt-daemon-driver-storage-rbd $ sudo apt install ceph-common $ sudo systemctl restart libvirtd
5. На узле kvm1 подключим libvirt-pool
Сгенерируем идентификатор секрета, он будет одинаковый на каждом узле KVM:
$ uuidgen
uuidgen -> 9bfab6ca-faad-42eb-8109-b59f08261c4a
Создадим секрет для подключения дисков ceph:
$ cat > "libvirt-secret.xml" <<EOF <secret ephemeral='no' private='no'> <uuid>9bfab6ca-faad-42eb-8109-b59f08261c4a</uuid> <usage type='ceph'> <name>client.libvirt secret</name> </usage> </secret> EOF $ virsh secret-define --file libvirt-secret.xml $ virsh secret-set-value \ --secret "9bfab6ca-faad-42eb-8109-b59f08261c4a" \ --base64 "$(sudo ceph auth get-key client.libvirt)"
Создадим описание пула для libvirt с данными из нашего секрета:
cat > "libvirt-ceph.xml" <<EOF <pool type="rbd"> <name>libvirt-pool</name> <source> <name>libvirt-pool</name> <host name='ceph1' port='6789' /> <host name='ceph2' port='6789' /> <host name='ceph3' port='6789' /> <auth username='libvirt' type='ceph'> <secret uuid='9bfab6ca-faad-42eb-8109-b59f08261c4a'/> </auth> </source> </pool> EOF
Запустим пул и добавим в автозагрузку:
$ virsh pool-define libvirt-ceph.xml $ virsh pool-autostart libvirt-ceph $ virsh pool-start libvirt-ceph
Информация о пуле:
$ virsh pool-info libvirt-pool Name: libvirt-pool UUID: 164d3ad2-d1e5-41e3-8d68-be6e94679416 State: running Persistent: yes Autostart: yes Capacity: 149.99 GiB Allocation: 0.00 B Available: 149.93 GiB
6. Отправим libvirt-secret.xml и libvirt-ceph.xml на хосты kvm2, kvm3, чтобы там создать тот же пул для ceph:
$ virsh pool-dumpxml libvirt-pool | tee libvirt-ceph.xml $ virsh secret-dumpxml \ --secret 9bfab6ca-faad-42eb-8109-b59f08261c4a | \ tee libvirt-secret.xml $ scp libvirt-secret.xml libvirt-ceph.xml kvm2: $ scp libvirt-secret.xml libvirt-ceph.xml kvm3:
На узлах KVM2, KVM3:
$ virsh secret-define libvirt-secret.xml $ virsh pool-define libvirt-ceph.xml $ virsh secret-set-value \ --secret "9bfab6ca-faad-42eb-8109-b59f08261c4a" \ --base64 "$(sudo ceph auth get-key client.libvirt)" $ virsh pool-start libvirt-pool $ virsh pool-autostart libvirt-pool $ virsh pool-info libvirt-pool
7. Загружаем в хранилище ceph образ iso, ставим систему и отдаем под управление pacemaker:
$ sudo rbd import --image-format 2 /labs/iso/installation-1.8.4.48-30.10.25_09.18.iso libvirt-pool/installation-1.8.4.48-30.10.25_09.18.iso $ virt-install \ --name template \ --ram 2048 \ --vcpus 2 \ --disk vol=libvirt-pool/installation-1.8.4.48-30.10.25_09.18.iso,device=cdrom,bus=sata \ --disk pool=libvirt-pool,size=20 \ --boot cdrom \ --os-variant debian12 \ --network network=default \ --graphics spice,listen=0.0.0.0 \ --video qxl \ --channel spicevmc,target_type=virtio,name=com.redhat.spice.0
8. На каждом узле создаем каталог для хранения конфигурации виртуальной машины:
$ sudo mkdir /etc/pacemaker/vm-xml $ virsh dumpxml astra-vm2 | \ sudo tee /etc/pacemaker/vm-xml/astra-vm2.xml
9. И отправляем конфиги на остальные хосты:
$ cat /etc/pacemaker/vm-xml/astra-vm2.xml | \ ssh kvm2 sudo tee /etc/pacemaker/vm-xml/astra-vm2.xml $ cat /etc/pacemaker/vm-xml/astra-vm2.xml | \ ssh kvm3 sudo tee /etc/pacemaker/vm-xml/astra-vm2.xml
10. После чего создаем ресурс pacemaker:
$ sudo pcs resource create astra-vm2 \ ocf:heartbeat:VirtualDomain \ hypervisor="qemu:///system" \ config="/etc/pacemaker/vm-xml/astra-vm2.xml" \ migration_transport="ssh" \ migration_user="sa" meta \ allow-migrate="true"
Настройка SBD (опционально)
Дополнительно бы хотелось отметить механизм Storage Protection and SBD, который позволяет добиться изоляции сбойных улов на основе общего блочного устройства, что позволяет отказаться от IPMI.
1. Создадим общий диск, который будем подключать к узлам KVM:
$ sudo ceph osd pool create sbd-pool $ sudo rbd create sbd-disk --size 100M --pool sbd-pool
2. После чего добавим этот диск для подключения на каждом kvm узле. Пишем следующую строку в файл /etc/ceph/rbdmap:
sbd-pool/sbd-disk id=admin,keyring=/etc/ceph/ceph.client.admin.keyring
3. Перезагружаем сервис rbdmap:
$ sudo systemctl reload rbdmap
После этого в системе появится диск rbd0:
sblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sda 8:0 0 50G 0 disk /labs rbd0 251:0 0 100M 0 disk vda 253:0 0 20G 0 disk ├─vda1 253:1 0 600M 0 part /boot/efi └─vda2 253:2 0 19.4G 0 part /
Здесь нужно немного отойти от начальной концепции, где мы используем только диск main. Теперь нам нужны два компонента: SBD и Watchdog, а Watchdog живет только в репозиториях debian. Поэтому мы, за кадром, подключим репозитории Debian 12 и установим нужные пакеты:
5. Ставим пакеты watchdog и sbd. И добавляем модуль softdog в автозагрузку:
$ sudo apt install watchdog sbd $ sudo modprobe watchdog $ echo softdog | sudo tee /etc/modules-load.d/softdog.conf $ sudo modprobe softdog
Также пришлось сходить к файлу /usr/lib/modprobe.d/blacklist_linux_6.12.47-1-generic.conf и удалить из него строку blacklist softdog. После чего выполнить команду:
$ sudo update-initramfs -k all -u
Инициализируем на диске /dev/rbd0 работу sbd:
$ sudo sbd -d /dev/rbd0 create $ sudo sbd -d /dev/rbd0 dump $ sudo pcs stonith create fence_sbd fence_sbd \ devices="/dev/rbd0" power_timeout=20
Еще это можно проверить, уронив сеть хранилища:
$ sudo iptables -A OUTPUT -d 10.10.10.0/24 -j DROP $ sudo iptables -A INPUT -s 10.10.10.0/24 -j DROP
Выводы
В рамках работы были рассмотрены и реализованы две архитектуры отказоустойчивого хранения для виртуализации на базе Astra Linux:
DRBD + GFS2 + Pacemaker
Ceph (ручное развёртывание)
Обе архитектуры обеспечивают высокую доступность виртуальных машин, однако ориентированы на разные сценарии эксплуатации и масштаб инфраструктуры.
Архитектура на базе iSCSI / DRBD / GFS2
Решение с использованием DRBD и GFS2 ориентировано прежде всего на:
небольшие кластеры (2–4 гипервизора)
ограниченный бюджет
существующую инфраструктуру хранения
Важно отметить, что в большинстве производственных сред iSCSI применяется при наличии уже готового «покупного» СХД от вендора. В таком случае:
отказоустойчивость хранения обеспечивается самим массивом,
кластер гипервизоров использует только общую файловую систему (например, GFS2),
DRBD не требуется.
Таким образом, для организаций с уже внедрённой СХД практическое значение имеет именно часть, связанная с:
настройкой GFS2,
интеграцией с Pacemaker,
корректной конфигурацией fencing.
В этом сценарии кластер масштабируется только по количеству гипервизоров, но не по хранилищу — оно остаётся ограниченным возможностями СХД.
Архитектура на базе Ceph
В отличие от предыдущего подхода, Ceph представляет собой распределённую систему хранения, масштабируемую горизонтально.
Ключевая особенность: увеличение объёма и производительности достигается добавлением новых серверов (OSD-узлов), а не заменой существующего оборудования.
Это делает Ceph более подходящим решением для:
растущих инфраструктур,
частных облаков,
сценариев с увеличением нагрузки.
В отличие от iSCSI + GFS2:
отсутствует единая точка хранения,
обеспечивается автоматическое распределение данных,
поддерживается репликация на уровне объекта,
расширение не требует простоя системы.
Однако это достигается ценой:
более высокой сложности настройки,
необходимости минимум трёх узлов,
повышенных требований к сетевой инфраструктуре,
значительных накладных расходов на обслуживание.
Сравнение масштабируемости
Параметр | DRBD / GFS2 / iSCSI | Ceph |
|---|---|---|
Минимум узлов | 2 | 3 |
Масштабирование хранения | Ограничено | Горизонтальное |
Добавление ёмкости | Замена/расширение СХД | Добавление серверов |
Точка хранения | Централизованная | Распределённая |
Сложность | Средняя | Высокая |
Подходит для малого кластера | Да | Избыточно |
Подходит для роста | Ограниченно | Да |
Практические рекомендации
Если организация уже использует аппаратную СХД, целесообразно применять GFS2 и кластеризацию гипервизоров без внедрения распределённого хранения.
Для небольших инфраструктур с фиксированным объёмом ресурсов рациональнее использовать DRBD-схему.
Для инфраструктур, ориентированных на рост и масштабирование, предпочтительнее использование Ceph.
Выбор архитектуры должен определяться не только техническими характеристиками, но и уровнем компетенции администрирования.
Общий вывод
Обе архитектуры могут успешно использоваться в среде Astra Linux, однако они решают разные задачи.
DRBD и GFS2 — это решение для контролируемой, компактной инфраструктуры.
Ceph — это решение для масштабируемой, распределённой платформы хранения.
Выбор подхода определяется не столько функциональностью, сколько стратегией развития инфраструктуры.
