Надежное хранилище с DRBD9 и Proxmox (Часть 1: NFS)

Содержание

image

Наверное каждый, кто хоть раз озадачивался поиском высокопроизводительного 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 и Linstor

Во первых стоит еще раз упомянуть про DRBDmanage, который очень неплохо интегрируется в Proxmox. LINBIT предоставляет готовый плагин DRBDmanage для Proxmox который позволяет использовать все его функции прямо из интерфейса Proxmox.

Выглядит это и правда потрясающе, но к сожалению имеет некоторые минусы.

  • Во первых захаркоженные названия томов, LVM-группа или ZFS-пул обязательно должен иметь название drbdpool .
  • Невозможность использования более одного пула на ноду
  • В силу специфики решения сontroller volume может находиться только на обычном LVM и никак иначе
  • Переодические глюки dbus, который тесно используется DRBDmanage для взаимодействия с нодами.

В результате чего, LINBIT было принято решение заменить всю сложную логику DRBDmanage на простое приложение, которое связывается с нодами используя обычное tcp-соединение и работает безо всякой там магии. Так появился Linstor.

Linstor и правда работает очень хорошо. К сожалению разработчики выбрали java как основной язык для написания Linstor-server, но пусть это не пугает вас, так как Linstor сам по себе занимается только распределением конфигов DRBD и нарезкой LVM/ZFS разделов на нодах.

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

Отказоустойчивый NFS-сервер

К сожалению на момент написания статьи Linstor имеет готовую интеграцию только с Kubernetes. Но в конце года ожидаются драйверы и для остальных систем Proxmox, OpenNebula, OpenStack.

Но пока готового решения нет, а старое нам так или иначе не нравится. Попробуем использовать DRBD9 по старинке для организации NFS-доступа на общий раздел.

Тем не менее данное решение так-же окажется не без плюсов, ведь NFS-сервер позволит вам организовать конкурентный доступ к файловой системе хранилища с нескольких серверов без необходимости использования сложных кластерных файловых систем с DLM, таких как OCFS и GFS2.

При этом вы получите возможность переключать роли Primary/Secondary нод просто мигрируя контейнер с NFS-сервером в интерфейсе Proxmox.

Вы так же сможете хранить любые файлы внутри этой файловой системы, так же как виртуальные диски и бэкапы.

В случае если вы используете Kubernetes вы сможете организовать ReadWriteMany доступ для ваших PersistentVolumes.

Proxmox и LXC-контейнеры

Теперь вопрос: почему Proxmox?

В принципе для построения подобной схемы мы могли бы использовать и Kubernetes так и обычную схему с кластер-менеджером. Но Proxmox предоставляет готовый, очень многофункциональный и в тоже время простой и интуитивно понятный интерфес практически для всего что нужно. Он из коробки умеет кластеризацию и поддерживает механизм fencing основанный на softdog. А при использовании LXC-контейнеров позволяет добиться минимальных таймаутов при переключении.
Полученное решение не будет иметь единой точки отказа.

По сути мы будем использовать Proxmox преимущественно как cluster-manager, где мы сможем рассматривать отдельный LXC-контейнер как сервис запущенный в классическом HA-кластере, лишь с тем отличием, что с контейнером в комплекте идет так же и его корневая система. То есть у вас нет необходимости устанавливать несколько экземаляров сервиса на каждом сервере отдельно, вы можете сделать это только один раз внутри контейнера.
Если вы когда-нибудь работали с cluster-manager software и обеспечением HA для приложений вы поймете что я имею ввиду.

Общая схема

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

  • У нас есть три ноды
  • На каждой ноде распределенное drbd-устройство.
  • На устройстве обычная файловая система (ext4)
  • Только один сервер может быть мастером
  • На мастере запущен NFS-сервер в LXC-контейнере.
  • Все ноды обращаются к устройству строго через NFS
  • При необходимости мастер может переехать на другую ноду, вместе с NFS-сервером

DRBD9 имеет одну очень крутую функцию которая сильно все упрощает:
drbd-устройство автоматически становиться Primary в тот момент когда оно монтируется на какой-нибудь ноде. В случае если устройство помечено как Primary, любая попытка смонтировать его на другой ноде приведет к ошибке доступа. Таким образом обеспечивается блокировка и гарантированная защита от одновременного доступа к устройству.

Почему это все сильно упрощает? Потому что при запуске контейрнера Proxmox автоматически монтирует это устройство и оно становится Primary на этой ноде, а при остановке контейнера наоборот размонтирует и устройство становится опять Secondary.
Таким образом нам больше не нужно беспокоиться о переключении Primary/Secondary устройств, Proxmox будет делать это автоматически, УРА!

Настройка DRBD

Ну хорошо, с идеей разобрались теперь перейдем к реализации.

По умолчанию в комплекте с ядром Linux поставляется модуль восьмой версии drbd, к сожалению он нам не подходит и нам необходимо установить модуль девятой версии.

Подключим репозиторий LINBIT и установим все необходимое:

  • pve-headers — заголовки ядра необходимые для сборки модуля
  • drbd-dkms — модуль ядра в формате DKMS
  • drbd-utils — основные утилиты для управления DRBD
  • drbdtop — интерактивный инструмент, как top только для DRBD

После установки модуля проверим, все ли в порядке с ним:

Если вы увидите в выводе команды восьмую версию значит что-то пошло не так и загружен in-tree модуль ядра. Проверьте dkms status что-бы разобраться в чем причина.

Каждая нода у нас будет иметь одно и тоже drbd-устройство запущенное поверх обычных разделов. Для начала нам нужно подготовить этот раздел под drbd на каждой ноде.

В качестве такого раздела может выступать любое блочное устройство, это может быть lvm, zvol, раздел диска или весь диск целиком. В этой статье я буду использовать отдельный nvme диск с разделом под drbd: /dev/nvme1n1p1

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

Найти такой симлинк для /dev/nvme1n1p1 можно таким образом:

Опишем наш ресурс на всех трех нодах:

Желательно для синхронизации drbd использовать отдельную сеть.

Теперь создадим метаданные для drbd и запустим его:

Повторим эти действия на всех трех нодах и проверим состояние:

Сейчас наш диск Inconsistent на всех трех нодах, это потому, что drbd не знает какой диск должен быть взят в качестве оригинала. Мы должны пометить один из них как Primary, что бы его состояние синхронизировалось на остальные ноды:

Сразу после этого начнется синхронизация:

Нам не обязательно дожидаться ее окончания и мы можем параллельно выполнять дальнейшие шаги. Их можно выполнять на любой ноде, вне зависимости от ее текущего состояния локального диска в DRBD. Все запросы будут автоматически перенаправлены на устройство с UpToDate состоянием.

Стоит не забыть активировать автозапуск drbd-сервиса на нодах:

Настройка LXC-контейнера

Опустим часть настройки кластера Proxmox из трех нод, эта часть хорошо описана в официальной wiki

Как я говорил раньше наш NFS-сервер будет работать в LXC-контейнере. Сам контейнер мы будем держать на устройстве /dev/drbd100 , которое мы только что создали.

Сначала нам нужно создать файловую систему на нем:

Proxmox по умолчанию включает multimount protection на уровне файловой системы, в принципе мы можем обойтись и без нее, т.к. DRBD по умолчанию имеет собственную защиту, он просто запретит второй Primary для устройства, но осторожность нам не повредит.

Теперь скачаем шаблон Ubuntu:

И создадим из него наш контейнер:

В данной команде мы указываем что корневая система нашего контейнера будет находиться на устройстве /dev/drbd100 и добавим параметр shared=1 что бы разрешить миграцию контейнера между нодами.

Если что-то пошло не так, вы всегда можете поправить это через интерфейс Proxmox или в конфиге контейнера /etc/pve/lxc/101.conf

Proxmox распакует шаблон и подготовит корневую систему контейнера для нас. После этого мы можем запустить наш контейнер:

Настройка NFS-сервера.

По умолчанию Proxmox не разрешает запуск NFS-сервера в контейнере, но есть несколько способов разрешить это.

Один из них просто добавить lxc.apparmor.profile: unconfined в конфиг нашего контейнера /etc/pve/lxc/100.conf .

Или мы можем разрешить NFS для всех контейнеров на постоянной основе, для этого нужно обновить стандартный шаблон для LXC на всех нодах, добавьте в /etc/apparmor.d/lxc/lxc-default-cgns следующие строки:

После изменений перезапустите контейнер:

Теперь давайте залогинимся в него:

Установим обновления и NFS-сервер:

Создадим экспорт:

Настройка HA

На момент написания статьи 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-сервера возможно поможет увеличение общего числа запускаемых экземпляров NFS-сервера. По умолчанию — 8, лично мне помогло увеличение этого числа до 64.

Что бы этого добиться обновите параметр RPCNFSDCOUNT=64 в /etc/default/nfs-kernel-server .
И перезапустите демоны:

NFSv3 vs NFSv4

Знаете в чем отличие между NFSv3 и NFSv4?

  • NFSv3 — это stateless протокол как правило он лучше переносит сбои и быстрее восстанавливается.
  • NFSv4 — это stateful протокол, он работает быстрее и может быть привязан к определенным tcp-портам, но из-за наличия состояния он более чувствителен к сбоям. В нем так же есть возможность использование аутентификации с помощью Kerberos и куча других интересных функций.

Тем не менее когда вы выполняете showmount -e nfs_server используется протокол NFSv3. Proxmox тоже использует NFSv3. NFSv3 так же обычно используется для организации загрузки машин по сети.

В общем, если у вас нет особых причин использовать NFSv4, старайтесь использовать NFSv3 так как он менее болезненно переживает любые сбои из-за отсутствия состояния как такового.

Примонтировать шару используя NFSv3 можно указав параметр -o vers=3 для команды mount:

При желании можно отключить NFSv4 для сервера вообще, для этого добавьте опцию —no-nfs-version 4 в переменную RPCNFSDCOUNT и перезапустите сервер, пример:

iSCSI и LVM

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

Как правило экспортируемый LUN нарезается на много кусочков с помощью LVM. Однако есть несколько ньюансов которые стоит учесть, например: каким образом обеспечены блокировоки LVM для совместного использования экспортированной группы на нескольких хостах.

Пожалуй эти и другие ньюансы я опишу в следующей статье.

UPD: Хочется добавить что помимо NFS-Kernel-Server существует ещё NFS-Ganesha — сервер, который полностью работает в user-space.

На данный момент я бы советовал использовать именно его, т.к. с ним ваш контейнер больше никогда не подвиснет в неизвестном состоянии.

NFS-Ganesha также немного быстрее обычного NFS-Kernel-Server.


Источник: habr.com