Наверное каждый, кто хоть раз озадачивался поиском высокопроизводительного software-defiined хранилища рано или поздно слышал про DRBD, а может даже и имел дело с ним. Правда на пике популярности Ceph и GlusterFS, которые работают в принципе неплохо, а главное сразу и из коробки, все просто немного подзабыли про него. Тем более что предыдущая версия не поддерживала репликацию более чем на два узла, и из-за чего часто встречались проблемы со split-brain, что явно не добавило ему популярности. Решение и правда не новое, но вполне конкурентоспособное. При относительно небольших затратах на CPU и RAM, DRBD предоставляет реально быструю и безопасную синхронизацию на уровне блочного устройства. За все это время LINBIT — разработчики DRBD не стоят на месте и постоянно дорабатывают его. Начиная с версии DRBD9 перестает быть просто сетевым зеркалом и становится чем-то бОльшим. Во первых, идея создания одного распределенного блочного устройства для нескольких серверов отошла на задний план, и теперь LINBIT старается предоставить инструменты оркестрации и управления множеством drbd-устройств в кластере, которые создаются поверх LVM и ZFS-разделов. Например DRBD9 поддерживает до 32 реплик, RDMA, diskless-ноды, а новые инструменты оркестрации позволяют использовать снапшоты, online-миграцию и много чего другого. Несмотря на то что DRBD9 имеет инструменты интеграции с Proxmox, Kubernetes, OpenStack и OpenNebula, на данный момент они находится в некотором переходном режиме, когда новые инструменты еще не везде поддерживаются, а старые уже очень скоро будут объявлены как deprecated. Речь идет о DRBDmanage и Linstor. Я воспользуюсь этим моментом что бы не сильно вдаваться в подробности каждого из них, но более подробно рассмотреть настройку и принципы работы с самим DRBD9. Вам все равно придется c этим разрбраться, хотя бы потому что отказоустойчивая настройка контроллера Linstor, подразумевает его установку на одно их таких устройств. В данной статье я бы хотел рассказать вам о DRBD9 и возможности его использования в Proxmox без сторонних плагинов. Во первых стоит еще раз упомянуть про DRBDmanage, который очень неплохо интегрируется в Proxmox. LINBIT предоставляет готовый плагин DRBDmanage для Proxmox который позволяет использовать все его функции прямо из интерфейса Proxmox. Выглядит это и правда потрясающе, но к сожалению имеет некоторые минусы. В результате чего, LINBIT было принято решение заменить всю сложную логику DRBDmanage на простое приложение, которое связывается с нодами используя обычное tcp-соединение и работает безо всякой там магии. Так появился Linstor. Linstor и правда работает очень хорошо. К сожалению разработчики выбрали java как основной язык для написания Linstor-server, но пусть это не пугает вас, так как Linstor сам по себе занимается только распределением конфигов DRBD и нарезкой LVM/ZFS разделов на нодах. Прочитать про каждое из них и о настройке вышеупомянутого плагина для Proxmox можно на официальной wiki Proxmox К сожалению на момент написания статьи Linstor имеет готовую интеграцию только с Kubernetes. Но в конце года ожидаются драйверы и для остальных систем Proxmox, OpenNebula, OpenStack. Но пока готового решения нет, а старое нам так или иначе не нравится. Попробуем использовать DRBD9 по старинке для организации NFS-доступа на общий раздел. Тем не менее данное решение так-же окажется не без плюсов, ведь NFS-сервер позволит вам организовать конкурентный доступ к файловой системе хранилища с нескольких серверов без необходимости использования сложных кластерных файловых систем с DLM, таких как OCFS и GFS2. При этом вы получите возможность переключать роли Primary/Secondary нод просто мигрируя контейнер с NFS-сервером в интерфейсе Proxmox. Вы так же сможете хранить любые файлы внутри этой файловой системы, так же как виртуальные диски и бэкапы. В случае если вы используете Kubernetes вы сможете организовать ReadWriteMany доступ для ваших PersistentVolumes. Теперь вопрос: почему Proxmox? В принципе для построения подобной схемы мы могли бы использовать и Kubernetes так и обычную схему с кластер-менеджером. Но Proxmox предоставляет готовый, очень многофункциональный и в тоже время простой и интуитивно понятный интерфес практически для всего что нужно. Он из коробки умеет кластеризацию и поддерживает механизм fencing основанный на softdog. А при использовании LXC-контейнеров позволяет добиться минимальных таймаутов при переключении.
Полученное решение не будет иметь единой точки отказа. По сути мы будем использовать Proxmox преимущественно как cluster-manager, где мы сможем рассматривать отдельный LXC-контейнер как сервис запущенный в классическом HA-кластере, лишь с тем отличием, что с контейнером в комплекте идет так же и его корневая система. То есть у вас нет необходимости устанавливать несколько экземаляров сервиса на каждом сервере отдельно, вы можете сделать это только один раз внутри контейнера.
Если вы когда-нибудь работали с cluster-manager software и обеспечением HA для приложений вы поймете что я имею ввиду. Наше решение будет напоминать стандартную схему репликации какой-нибудь базы данных. DRBD9 имеет одну очень крутую функцию которая сильно все упрощает:
drbd-устройство автоматически становиться Primary в тот момент когда оно монтируется на какой-нибудь ноде. В случае если устройство помечено как Primary, любая попытка смонтировать его на другой ноде приведет к ошибке доступа. Таким образом обеспечивается блокировка и гарантированная защита от одновременного доступа к устройству. Почему это все сильно упрощает? Потому что при запуске контейрнера Proxmox автоматически монтирует это устройство и оно становится Primary на этой ноде, а при остановке контейнера наоборот размонтирует и устройство становится опять Secondary.
Таким образом нам больше не нужно беспокоиться о переключении Primary/Secondary устройств, Proxmox будет делать это автоматически, УРА! Ну хорошо, с идеей разобрались теперь перейдем к реализации. По умолчанию в комплекте с ядром Linux поставляется модуль восьмой версии drbd, к сожалению он нам не подходит и нам необходимо установить модуль девятой версии. Подключим репозиторий LINBIT и установим все необходимое: После установки модуля проверим, все ли в порядке с ним: Если вы увидите в выводе команды восьмую версию значит что-то пошло не так и загружен in-tree модуль ядра. Проверьте dkms status что-бы разобраться в чем причина. Каждая нода у нас будет иметь одно и тоже drbd-устройство запущенное поверх обычных разделов. Для начала нам нужно подготовить этот раздел под drbd на каждой ноде. В качестве такого раздела может выступать любое блочное устройство, это может быть lvm, zvol, раздел диска или весь диск целиком. В этой статье я буду использовать отдельный nvme диск с разделом под drbd: /dev/nvme1n1p1 Стоит заметить, что имена устройств имеют свойство иногда меняться, так что лучше сразу взять за привычку использовать постоянный симлинк на устройство. Найти такой симлинк для /dev/nvme1n1p1 можно таким образом: Опишем наш ресурс на всех трех нодах: Желательно для синхронизации drbd использовать отдельную сеть. Теперь создадим метаданные для drbd и запустим его: Повторим эти действия на всех трех нодах и проверим состояние: Сейчас наш диск Inconsistent на всех трех нодах, это потому, что drbd не знает какой диск должен быть взят в качестве оригинала. Мы должны пометить один из них как Primary, что бы его состояние синхронизировалось на остальные ноды: Сразу после этого начнется синхронизация: Нам не обязательно дожидаться ее окончания и мы можем параллельно выполнять дальнейшие шаги. Их можно выполнять на любой ноде, вне зависимости от ее текущего состояния локального диска в DRBD. Все запросы будут автоматически перенаправлены на устройство с UpToDate состоянием. Стоит не забыть активировать автозапуск drbd-сервиса на нодах: Опустим часть настройки кластера Proxmox из трех нод, эта часть хорошо описана в официальной wiki Как я говорил раньше наш NFS-сервер будет работать в LXC-контейнере. Сам контейнер мы будем держать на устройстве /dev/drbd100, которое мы только что создали. Сначала нам нужно создать файловую систему на нем: Proxmox по умолчанию включает multimount protection на уровне файловой системы, в принципе мы можем обойтись и без нее, т.к. DRBD по умолчанию имеет собственную защиту, он просто запретит второй Primary для устройства, но осторожность нам не повредит. Теперь скачаем шаблон Ubuntu: И создадим из него наш контейнер: В данной команде мы указываем что корневая система нашего контейнера будет находиться на устройстве /dev/drbd100 и добавим параметр shared=1 что бы разрешить миграцию контейнера между нодами. Если что-то пошло не так, вы всегда можете поправить это через интерфейс Proxmox или в конфиге контейнера /etc/pve/lxc/101.conf Proxmox распакует шаблон и подготовит корневую систему контейнера для нас. После этого мы можем запустить наш контейнер: По умолчанию Proxmox не разрешает запуск NFS-сервера в контейнере, но есть несколько способов разрешить это. Один из них просто добавить lxc.apparmor.profile: unconfined в конфиг нашего контейнера /etc/pve/lxc/100.conf. Или мы можем разрешить NFS для всех контейнеров на постоянной основе, для этого нужно обновить стандартный шаблон для LXC на всех нодах, добавьте в /etc/apparmor.d/lxc/lxc-default-cgns следующие строки: После изменений перезапустите контейнер: Теперь давайте залогинимся в него: Установим обновления и NFS-сервер: Создадим экспорт: На момент написания статьи proxmox HA-manager имеет баг, который не позволяет HA-контейнеру успешно завершить свою работу, в результате чего, не до конца убитые kernel-space процессы nfs-сервера не дают drbd-устройству уйти в Secondary. В случае если вы уже столкнулись с такой ситуацией не стоит паниковать и просто выполните killall -9 nfsd на ноде, где был запущен контейнер и тогда drbd-устройство должно "отпустить" и оно перейдет в Secondary. Что бы этот баг поправить, выполните следующие команды на всех нодах: Теперь мы можем перейти к кофигурации HA-manager. Создадим отдельную HA-группу для нашего устройства: Наш ресурс будет работать только на нодах указанных для этой группы. Добавим наш контейнер в эту группу: На этом все. Просто, не правда ли? Полученную nfs-шару можно сразу-же подключить в Proxmox, для хранения и запуска других виртуальных машин и контейнеров. Как я отметил выше, всегда желательно использовать отдельную сеть под репликацию. Крайне желательно использовать 10-гигабитные сетевые адаптеры, в противном случае у вас все упрется в скорость портов.
Если репликация вам кажется достаточно медленной попробуйте потюнить некоторые параметры для DRBD. Вот конфиг, который на мой взгляж является оптимальными для моей 10G-сети: Подробнее про каждый параметр вы можете получить информацию из официальной документации DRBD Для ускорения работы NFS-сервера возможно поможет увеличение общего числа запускаемых экземпляров NFS-сервера. По умолчанию — 8, лично мне помогло увеличение этого числа до 64. Что бы этого добиться обновите параметр RPCNFSDCOUNT=64 в /etc/default/nfs-kernel-server.
И перезапустите демоны: Знаете в чем отличие между NFSv3 и NFSv4? Тем не менее когда вы выполняете showmount -e nfs_server используется протокол NFSv3. Proxmox тоже использует NFSv3. NFSv3 так же обычно используется для организации загрузки машин по сети. В общем, если у вас нет особых причин использовать NFSv4, старайтесь использовать NFSv3 так как он менее болезненно переживает любые сбои из-за отсутствия состояния как такового. Примонтировать шару используя NFSv3 можно указав параметр -o vers=3 для команды mount: При желании можно отключить NFSv4 для сервера вообще, для этого добавьте опцию --no-nfs-version 4 в переменную RPCNFSDCOUNT и перезапустите сервер, пример: Подобным образом внутри контейнера может быть настроен и обычный tgt-демон, iSCSI будет выдавать значительно бОльшую производительность для операций ввода-вывода, а контейнер будет работать более гладко ввиду того tgt-сервер работает полностью в пространстве пользователя. Как правило экспортируемый LUN нарезается на много кусочков с помощью LVM. Однако есть несколько ньюансов которые стоит учесть, например: каким образом обеспечены блокировоки LVM для совместного использования экспортированной группы на нескольких хостах. Пожалуй эти и другие ньюансы я опишу в следующей статье. UPD: Хочется добавить что помимо NFS-Kernel-Server существует ещё NFS-Ganesha — сервер, который полностью работает в user-space. На данный момент я бы советовал использовать именно его, т.к. с ним ваш контейнер больше никогда не подвиснет в неизвестном состоянии. NFS-Ganesha также немного быстрее обычного NFS-Kernel-Server. Установка всё также проста: Но конфигурация немного отличается, экспорт нужно описать в /etc/ganesha/ganesha.conf Затем выполнить: Конфигурация клиентов не отличается. Суперпользователь