Надежное хранилище с DRBD9 и Proxmox (Часть 2: iSCSI+LVM)

    image


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


    В этой статье я расскажу как подобным образом создать отказоустойчивый iSCSI-таргет, который при помощи LVM мы будем нарезать на маленькие кусочки и использовать под виртуальные машины.


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


    Пара слов о DRBD


    DRBD достаточно простое и зрелое решение, код восьмой версии принят в состав ядра Linux. По сути представляет ссобой сетевое зеркало RAID1. В девятой версии появилась поддержка кворума и репликации с больше чем двумя нодами.


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


    Используя DRBD можно добиться очень интересных кофигураций. Сегодня пойдет речь об iSCSI и LVM.


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


    Пара слов об iSCSI


    iSCSI — это протокол доставки блочного устройства по сети.


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


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


    Пара слов об LVM


    Стоит упомянуть, что у LINBIT существует собственное решение для Proxmox, оно должно работать из коробки и позволит добиться похожего результата, но в данной статье я не хотел бы заострять внимание только на Proxmox а описать некоторое более унивирсальное решение которое подойдет как для Proxmox так и для чего-нибудь еще, в данном примере proxmox используется только как средство оркестрации контейнеров, по сути вы можете заменить его на другое решение, например запускать контейнеры с таргетом в Kubernetes.


    Что касается конкретно Proxmox, то он отлично работает с shared LUN и LVM, используя только собственные стандратные драйверы.


    К плюсам LVM можно отнести то, что его использование не является чем-то революционно новым и недостаточно обкатанным, а наоборот, оно показывает сухую стабильность, что обычно и требуется от хранилища. Стоит упомянуть что LVM довольно активно используются и в других средах, например в OpenNebula или в Kubernetes и достаточно неплохо там поддерживается.


    Таким образом вы получите универсальное хранилище которое можно использовать в разных системах (не только в proxmox), используя только готовые драйверы, без особой необходимости дорабатывать его напильником.


    К сожалению, при выборе решения под хранилище всегда приходится идти на какие-нибудь компромиссы. Так и тут, данное решение не даст вам той-же гибкости как например Ceph.
    Размер виртуального диска ограничен размером LVM-группы, а область размеченная под конкретный виртуальный диск обязательно будет преаллоцирована — это сильно улучшает скорость доступа к данным, но не дает возможности к Thin-Provisioning (когда виртуальный диск занимает меньше места чем есть на самом деле). Стоит упомянуть что производительность LVM достаточно сильно проседает при использовании снапшотов, в связи с чем возможность свободного их использования, часто исключается.


    Да, LVM поддерживает Thin-Provision пулы, которые лишены данного недостатка, но к сожалению их использование возможно только в контексте одной ноды и нет возможности расшарить один Thin-Provision пул на несколько нод в кластере.


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


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


    Общая схема


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

    Настройка


    С идеей разобрались теперь перейдем к реализации.


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


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


    wget -O- https://packages.linbit.com/package-signing-pubkey.asc | apt-key add - 
    echo "deb http://packages.linbit.com/proxmox/ proxmox-5 drbd-9.0" \
      > /etc/apt/sources.list.d/linbit.list
    
    apt-get update && apt-get -y install pve-headers drbd-dkms drbd-utils drbdtop

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

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


    # modprobe drbd
    # cat /proc/drbd 
    version: 9.0.14-1 (api:2/proto:86-113)

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


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


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


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


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


    # find /dev/disk/ -lname '*/nvme1n1p1'
    /dev/disk/by-partuuid/847b9713-8c00-48a1-8dff-f84c328b9da2
    /dev/disk/by-path/pci-0000:0e:00.0-nvme-1-part1
    /dev/disk/by-id/nvme-eui.0000000001000000e4d25c33da9f4d01-part1
    /dev/disk/by-id/nvme-INTEL_SSDPEKKA010T7_BTPY703505FB1P0H-part1

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


    # cat /etc/drbd.d/tgt1.res
    resource tgt1 {
      meta-disk internal;
      device    /dev/drbd100;
      protocol  C;
      net { 
        after-sb-0pri discard-zero-changes;
        after-sb-1pri discard-secondary;
        after-sb-2pri disconnect;
      }
      on pve1 {
        address   192.168.2.11:7000;
        disk      /dev/disk/by-partuuid/95e7eabb-436e-4585-94ea-961ceac936f7;
        node-id   0;
      }
      on pve2 {
        address   192.168.2.12:7000;
        disk      /dev/disk/by-partuuid/aa7490c0-fe1a-4b1f-ba3f-0ddee07dfee3;
        node-id   1;
      }
      on pve3 {
        address   192.168.2.13:7000;
        disk      /dev/disk/by-partuuid/847b9713-8c00-48a1-8dff-f84c328b9da2;
        node-id   2;
      }
      connection-mesh {
        hosts pve1 pve2 pve3;
      }
    }

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


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


    # drbdadm create-md tgt1
    initializing activity log
    initializing bitmap (320 KB) to all zero
    Writing meta data...
    New drbd meta data block successfully created.
    success
    # drbdadm up tgt1

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


    # drbdadm status
    tgt1 role:Secondary
      disk:Inconsistent
      pve2 role:Secondary
        peer-disk:Inconsistent
      pve3 role:Secondary
        peer-disk:Inconsistent

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


    drbdadm primary --force tgt1
    drbdadm secondary tgt1

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


    # drbdadm status
    tgt1 role:Secondary
      disk:UpToDate
      pve2 role:Secondary
        replication:SyncSource peer-disk:Inconsistent done:26.66
      pve3 role:Secondary
        replication:SyncSource peer-disk:Inconsistent done:14.20
    

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


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


    systemctl enable drbd.service

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


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


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


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


    mkfs -t ext4 -O mmp -E mmp_update_interval=5 /dev/drbd100

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


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


    # wget http://download.proxmox.com/images/system/ubuntu-16.04-standard_16.04-1_amd64.tar.gz -P /var/lib/vz/template/cache/

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


    pct create 101 local:vztmpl/ubuntu-16.04-standard_16.04-1_amd64.tar.gz \
      --hostname=tgt1 \
      --net0=name=eth0,bridge=vmbr0,gw=192.168.1.1,ip=192.168.1.11/24 \
      --rootfs=volume=/dev/drbd100,shared=1

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


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


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


    pct start 101

    Настройка iSCSI-таргета.


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


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


    pct exec 101 bash

    Установим обновления и istgt:


    apt-get update 
    apt-get -y upgrade
    apt-get -y install istgt

    Создадим файл который мы и будем отдавать по сети:


    mkdir -p /data
    fallocate -l 740G /data/target1.img

    Теперь нам нужно написать конфиг для istgt /etc/istgt/istgt.conf:


    [Global]
      Comment "Global section"
      NodeBase "iqn.2018-07.org.example.tgt1"
      PidFile /var/run/istgt.pid
      AuthFile /etc/istgt/auth.conf
      MediaDirectory /var/istgt
      LogFacility "local7"
      Timeout 30
      NopInInterval 20
      DiscoveryAuthMethod Auto
      MaxSessions 16
      MaxConnections 4
      MaxR2T 32
      MaxOutstandingR2T 16
      DefaultTime2Wait 2
      DefaultTime2Retain 60
      FirstBurstLength 262144
      MaxBurstLength 1048576
      MaxRecvDataSegmentLength 262144
      InitialR2T Yes
      ImmediateData Yes
      DataPDUInOrder Yes
      DataSequenceInOrder Yes
      ErrorRecoveryLevel 0
    [UnitControl]
      Comment "Internal Logical Unit Controller"
      AuthMethod CHAP Mutual
      AuthGroup AuthGroup10000
      Portal UC1 127.0.0.1:3261
      Netmask 127.0.0.1
    [PortalGroup1]
      Comment "SINGLE PORT TEST"
      Portal DA1 192.168.1.11:3260
    [InitiatorGroup1]
      Comment "Initiator Group1"
      InitiatorName "ALL"
      Netmask 192.168.1.0/24
    [LogicalUnit1]
      Comment "Hard Disk Sample"
      TargetName disk1
      TargetAlias "Data Disk1"
      Mapping PortalGroup1 InitiatorGroup1
      AuthMethod Auto
      AuthGroup AuthGroup1
      UseDigest Auto
      UnitType Disk
      LUN0 Storage /data/target1.img Auto

    Перезапустим istgt:


    systemctl restart istgt

    На этом настройка таргета закончена


    Настройка HA


    Теперь мы можем перейти к кофигурации HA-manager. Создадим отдельную HA-группу для нашего устройства:


    ha-manager groupadd tgt1 --nodes pve1,pve2,pve3 --nofailback=1 --restricted=1

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


    ha-manager add ct:101 --group=tgt1 --max_relocate=3 --max_restart=3

    Рекомендации и тюнинг


    DRBD

    Как я отметил выше, всегда желательно использовать отдельную сеть под репликацию. Крайне желательно использовать 10-гигабитные сетевые адаптеры, в противном случае у вас все упрется в скорость портов.
    Если репликация вам кажется достаточно медленной попробуйте потюнить некоторые параметры для DRBD. Вот конфиг, который на мой взгляж является оптимальными для моей 10G-сети:


    # cat /etc/drbd.d/global_common.conf
    global {
     usage-count yes;
     udev-always-use-vnr; 
    }
    common {
     handlers {
     }
     startup {
     }
     options {
     }
     disk {
      c-fill-target 10M;
      c-max-rate   720M;
      c-plan-ahead   10;
      c-min-rate    20M;
     }
     net {
      max-buffers     36k;
      sndbuf-size   1024k;
      rcvbuf-size   2048k;
     }
    }

    Подробнее про каждый параметр вы можете получить информацию из официальной документации DRBD


    Open-iSCSI

    Так как мы не используем multipathing, в нашем случае рекомендуется отключить переодические проверки соединения на клиентах, а так же увеличить таймауты ожидания для восстановления сессии в /etc/iscsi/iscsid.conf.


    node.conn[0].timeo.noop_out_interval = 0
    node.conn[0].timeo.noop_out_timeout = 0
    node.session.timeo.replacement_timeout = 86400

    Использование


    Proxmox


    Полученный iSCSI-таргет можно сразу-же подключить в Proxmox, не забыв снять галочку с Use LUN Directly.



    Сразу после этого станет возможным создание LVM поверх него, не забудьте поставить галочку напротив shared:



    Другие среды


    Если вы планируете использовать это решение в другой среде возможно вам потребуется установить кластерное расширение для LVM на данный момент из существует две реализации. CLVM и lvmlockd.


    Настройка CLVM не совесм тривиальна и требует работающего кластер менеджера.
    Куда как второй метод lvmlockd — еще не до конца протестирован и только-только начинает появляться в стабильных репозиториях.


    Рекомендую к прочтению отличную статью о блокировах в LVM


    При использовании LVM с Proxmox кластерное дополнение не требуется, так как управление томами обеспечивается самим proxmox, который обновляет и следит за метаданными LVM самостоятельно. Тоже касается и OpenNebula, на что явно указывает официальная документация.

    Поделиться публикацией
    Комментарии 4
      0
      LVM уже давольно давно умеет ThinProvision, где нет проблем с производительностью снапшотов.
        0
        Да, но LVM не поддерживает конкурентный доступ к thin-provision пулу с нескольких нод.
        Есть способ под каждую виртуалку генерить отдельный thin-provision пул в общем LVM, правда это не в контексте проксмоса уже.
          0

          Тогда фразу в статье стоит изменить. А то создалось впичатление, что вы не знали про ThinProvision, а вопрос был в поддержке кластеризации.

            0
            Спасибо за замечание, поправил.

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

      Самое читаемое