DRBD

Задачей являлось создание отказоустойчивого хранилища для VMware vSphere. Не имея на данный момент нормальной хранилки решено было попробовать

сделать ее самостоятельно из двух виртуальных машин, размещенных на разных хостах VMware, на подобие VSA, только из двух нод.

Для VMware можно по сети подключать iSCSI и NFS, с iSCSI в ALTLinux у меня что-то не очень получилось, а вот с NFS вполне даже удачно.

Подготовка виртуальной машины для хранилища.

На одном из хостов VMware была создана виртуальная машина с 1 Гб ОЗУ, 1 ЦП , двумя дисками, один из которых 6 Гб, а второй для блочного устройства 100 Гб (для продакшена надо больше разумеется), один сетевой адаптер, подключенный в VM Network на скорости 10 Гбит/с. На ВМ установлен ALT Linux 1.1.4 Server Light r5 (Collybia confluens). Машина названа drbd1 и ей назначен ip: 10.8.100.8

Установлены следующие пакеты:

drbd83-tools-8.3.8-alt3

drbd83-heartbeat-8.3.8-alt3

heartbeat-2.1.3-alt5

nfs-server-1.2.4-alt0.9

nfs-utils-1.2.4-alt0.9

nfs-clients-1.2.4-alt0.9

Конфигурационый файл /etc/hosts:

127.0.0.1       localhost.localdomain localhost
10.8.100.8      drbd1
10.8.100.9      drbd2
10.8.100.7      nfs

После чего был сделан клон этой машины, который был назван drbd2 и назначен ip-адрес: 10.8.100.9

Настройка DRBD

файл ресурсов /etc/drbd.d/nfs.res

resource nfs {
protocol C;
startup {
degr-wfc-timeout 120;
}
disk {
on-io-error detach;
}
net {
cram-hmac-alg sha1;
shared-secret "password";
after-sb-0pri disconnect;
after-sb-1pri disconnect;
after-sb-2pri disconnect;
rr-conflict disconnect;
}
syncer {
rate 100M;
verify-alg sha1;
al-extents 257;
}
on drbd1 {
device /dev/drbd1;
disk /dev/sdb1;
address 10.8.100.8:7789;
meta-disk internal;
}
on drbd2 {
device /dev/drbd1;
disk /dev/sdb1;
address 10.8.100.9:7789;
meta-disk internal;
}

Этот файл одинаков на обоих нодах. При использовании протокола "C" запись считается завершенной, если она произведена и на primary и отреплицирована на secondary ноды, т.е. это самый медленный, но самый надежный протокол.

Теперь диски нужно проинициализировать, вот так:

[root@drbd1 ~]# dd if=/dev/zero of=/dev/sdb1
[root@drbd1 ~]# drbdadm create-md nfs

Тоже самое нужно повторить на ноде drbd2

После чего запускаем drbd:

[root@drbd1 ~]# service drbd start

Так же следует запустить его и на второй ноде и не забываем включить в автозапуск:

[root@drbd1 ~]# chkconfig drbd on

Так же и на второй ноде.

Теперь делаем первую drbd1 первичной нодой:

[root@drbd1 ~]# drbdadm -- --overwrite-data-of-peer primary nfs

Теперь посматриваем на статус DRBD, через:

[root@drbd1 ~]# cat /proc/drbd

После полной синхронизации должны увидеть что-то вроде:

[root@drbd1 ~]# cat /proc/drbd
version: 8.3.11 (api:88/proto:86-96)
srcversion: 79C7538C029736B369AE7C0
 1: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
    ns:293232304 nr:445525 dw:293702713 dr:309089566 al:67809 bm:34 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0

Обращаем внимание, наша нода Primary, а node2 Secondary.

Далее в корне создадим директорию /disk, это делается на обоих нодах, сюда будем монтировать наше DRBD устройство.

Создадим файловую систему, я выбрл XFS, т.к. в моем случае тут будут лежать образы виртуальных машин.

[root@drbd1 disk]# mkfs.xfs /dev/drbd1

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

Тут на самом деле все просто, экспортируем нашу точку монтиривания /disk:

файл /etc/exports

/disk 10.8.0.0/16(rw,no_root_squash,crossmnt)

Файл одинаков для обоих нод. Нужно проверить, что бы в /etc/sysconfig/rpcbind была закомментирована строка CONTROL_ARGS="-l", а то не увидим наш NFS по сети.

В автозапуск включать nfs не нужно, этим будет заниматься heartbeat.

Настройка Heartbeat

На drbd1 файл /etc/ha.d/ha.cf выглядит следующим образом:

ucast eth0 drbd2
auto_failback on
node drbd1 drbd2

А на drbd2 этот файл выглядит так:

ucast eth0 drbd1
auto_failback on
node drbd1 drbd2

При помощи маленького скрипта ...

#!/bin/sh
( echo -ne "auth 1\n1 sha1 ";  dd if=/dev/urandom bs=512 count=1 | openssl md5 )   > /etc/ha.d/authkeys
chmod 0600 /etc/ha.d/authkeys

Нужно создать файл /etc/ha.d/autchkeys, выглядеть он должен примерно так:

auth 1
1 sha1 (stdin)= af3faf312f54623c88935424c41eaaaa

Создаем authkeys на одной ноде и копируем на вторую.

Теперь главный файл настроек heartbeat /etc/ha.d/haresources:

drbd1 drbddisk::nfs     Filesystem::/dev/drbd1::/disk nfs IPaddr::10.8.100.7/24/eth0

Видим, что тут появляется уже новый IP-адрес, именно к нему мы будем обращаться. скрипты drbddisk, Filesystem и IPaddr стандартные, а вот nfs мне пришлось сделать самому:

файл /etc/ha.d/resource.d/nfs

#!/bin/sh
case $1 in
    start)    /sbin/service nfs start
        ;;
    stop)     killall -9 nfsd
        ;;
    status)
    exit 0
    ;;
    *)        echo err
    ;;
esac

Может покажется, что это слишком жестокий способ остановки сервиса NFS, но по другому нормально не отрабатывает. Т.е. если nfs сервер кто-то держит в данный момент, то он фиг остановится, соответственно и IP адрес не переезжает на другую ноду, а так все отлично работает.

Включаем heartbeat и прописываем его в атозапуск:

[root@drbd1 disk]# service heartbeat start
[root@drbd1 disk]# chkconfig heartbeat on

Повторяем на второй ноде

Проверка

Для начала можно смонтировать этот ресурс на свой компьютер, вот строчка для fstab:

10.8.100.7:/disk        /mnt/disk       nfs     soft,nolock,mountproto=tcp,vers=3 0 0

Теперь покопировать туда файлы и повыключать ноды. Например я заливал со своего компьютера большой avi файл и в это время нажимал reset на node1 (основная по умолчанию)

В это время на второй ноде наблюдается следующее:

Jun  3 14:14:29 drbd2 kernel: [3887669.675894] block drbd1: PingAck did not arrive in time.
Jun  3 14:14:29 drbd2 kernel: [3887669.675910] block drbd1: peer( Primary -> Unknown ) conn( Connected -> NetworkFailure ) pdsk( UpToDate -> DUnknown )
Jun  3 14:14:29 drbd2 kernel: [3887669.676137] block drbd1: asender terminated
Jun  3 14:14:29 drbd2 kernel: [3887669.676141] block drbd1: Terminating drbd1_asender
Jun  3 14:14:29 drbd2 kernel: [3887669.676291] block drbd1: Connection closed
Jun  3 14:14:29 drbd2 kernel: [3887669.676296] block drbd1: conn( NetworkFailure -> Unconnected )
Jun  3 14:14:29 drbd2 kernel: [3887669.676300] block drbd1: receiver terminated
Jun  3 14:14:29 drbd2 kernel: [3887669.676302] block drbd1: Restarting drbd1_receiver
Jun  3 14:14:29 drbd2 kernel: [3887669.676305] block drbd1: receiver (re)started
Jun  3 14:14:29 drbd2 kernel: [3887669.676309] block drbd1: conn( Unconnected -> WFConnection )
Jun  3 14:14:52 drbd2 kernel: [3887693.318850] block drbd1: Handshake successful: Agreed network protocol version 96
Jun  3 14:14:52 drbd2 kernel: [3887693.319413] block drbd1: Peer authenticated using 20 bytes of 'sha1' HMAC
Jun  3 14:14:52 drbd2 kernel: [3887693.319422] block drbd1: conn( WFConnection -> WFReportParams )
Jun  3 14:14:52 drbd2 kernel: [3887693.319437] block drbd1: Starting asender thread (from drbd1_receiver [3579])
Jun  3 14:14:52 drbd2 kernel: [3887693.319596] block drbd1: data-integrity-alg: <not-used>
Jun  3 14:14:52 drbd2 kernel: [3887693.319616] block drbd1: drbd_sync_handshake:
Jun  3 14:14:52 drbd2 kernel: [3887693.319623] block drbd1: self 93CA347B642E2F5A:0000000000000000:F7F60AD9250606C7:F7F50AD9250606C7 bits:0 flags:0
Jun  3 14:14:52 drbd2 kernel: [3887693.319628] block drbd1: peer 93CA347B642E2F5A:0000000000000000:F7F60AD9250606C6:F7F50AD9250606C7 bits:11264 flags:2
Jun  3 14:14:52 drbd2 kernel: [3887693.319631] block drbd1: uuid_compare()=-1 by rule 40
Jun  3 14:14:52 drbd2 kernel: [3887693.319638] block drbd1: peer( Unknown -> Secondary ) conn( WFReportParams -> WFBitMapT ) disk( UpToDate -> Outdated ) pdsk( DUnknown -> UpToDate )
Jun  3 14:14:53 drbd2 kernel: [3887693.374894] block drbd1: conn( WFBitMapT -> WFSyncUUID )
Jun  3 14:14:53 drbd2 kernel: [3887693.381323] block drbd1: updated sync uuid 0001000000000000:0000000000000000:F7F60AD9250606C7:F7F50AD9250606C7
Jun  3 14:14:53 drbd2 kernel: [3887693.381542] block drbd1: helper command: /sbin/drbdadm before-resync-target minor-1
Jun  3 14:14:53 drbd2 kernel: [3887693.385222] block drbd1: helper command: /sbin/drbdadm before-resync-target minor-1 exit code 0 (0x0)
Jun  3 14:14:53 drbd2 kernel: [3887693.385229] block drbd1: conn( WFSyncUUID -> SyncTarget ) disk( Outdated -> Inconsistent )
Jun  3 14:14:53 drbd2 kernel: [3887693.385236] block drbd1: Began resync as SyncTarget (will sync 45056 KB [11264 bits set]).
Jun  3 14:14:53 drbd2 heartbeat: [4097]: WARN: node drbd1: is dead
Jun  3 14:14:53 drbd2 heartbeat: [4097]: WARN: No STONITH device configured.
Jun  3 14:14:53 drbd2 heartbeat: [4097]: WARN: Shared disks are not protected.
Jun  3 14:14:53 drbd2 heartbeat: [4097]: info: Resources being acquired from drbd1.
Jun  3 14:14:53 drbd2 heartbeat: [4097]: info: Link drbd1:eth0 dead.
Jun  3 14:14:53 drbd2 harc[28810]: [28821]: info: Running /etc/ha.d/rc.d/status status
Jun  3 14:14:53 drbd2 heartbeat: [28811]: info: No local resources [/usr/share/heartbeat/ResourceManager listkeys drbd2] to acquire.
Jun  3 14:14:53 drbd2 mach_down[28835]: [28856]: info: Taking over resource group drbddisk::nfs
Jun  3 14:14:53 drbd2 ResourceManager[28857]: [28868]: info: Acquiring resource group: drbd1 drbddisk::nfs Filesystem::/dev/drbd1::/disk nfs IPaddr::10.8.100.7/24/eth0
Jun  3 14:14:53 drbd2 ResourceManager[28857]: [28897]: info: Running /etc/ha.d/resource.d/drbddisk nfs start
Jun  3 14:14:53 drbd2 kernel: [3887693.739294] block drbd1: role( Secondary -> Primary )
Jun  3 14:14:53 drbd2 Filesystem[28916]: [28961]: INFO:  Resource is stopped
Jun  3 14:14:53 drbd2 ResourceManager[28857]: [28975]: info: Running /etc/ha.d/resource.d/Filesystem /dev/drbd1 /disk start
Jun  3 14:14:53 drbd2 Filesystem[28988]: [29018]: INFO: Running start for /dev/drbd1 on /disk
Jun  3 14:14:53 drbd2 Filesystem[28988]: [29023]: INFO: Starting filesystem check on /dev/drbd1
Jun  3 14:14:53 drbd2 kernel: [3887693.997663] XFS (drbd1): Mounting Filesystem
Jun  3 14:14:53 drbd2 kernel: [3887694.080031] block drbd1: Resync done (total 1 sec; paused 0 sec; 45056 K/sec)
Jun  3 14:14:53 drbd2 kernel: [3887694.080037] block drbd1: updated UUIDs 93CA347B642E2F5B:0000000000000000:0001000000000001:F7F60AD9250606C6
Jun  3 14:14:53 drbd2 kernel: [3887694.080042] block drbd1: conn( SyncTarget -> Connected ) disk( Inconsistent -> UpToDate )
Jun  3 14:14:53 drbd2 kernel: [3887694.080159] block drbd1: helper command: /sbin/drbdadm after-resync-target minor-1
Jun  3 14:14:53 drbd2 kernel: [3887694.082115] block drbd1: helper command: /sbin/drbdadm after-resync-target minor-1 exit code 0 (0x0)
Jun  3 14:14:53 drbd2 kernel: [3887694.136135] block drbd1: bitmap WRITE of 791 pages took 1 jiffies
Jun  3 14:14:53 drbd2 kernel: [3887694.136142] block drbd1: 0 KB (0 bits) marked out-of-sync by on disk bit-map.
Jun  3 14:14:53 drbd2 kernel: [3887694.191885] XFS (drbd1): Starting recovery (logdev: internal)
Jun  3 14:14:53 drbd2 Filesystem[28977]: [29037]: INFO:  Success
Jun  3 14:14:53 drbd2 kernel: [3887694.265068] XFS (drbd1): Ending recovery (logdev: internal)
Jun  3 14:14:53 drbd2 ResourceManager[28857]: [29054]: info: Running /etc/ha.d/resource.d/nfs  start
Jun  3 14:14:53 drbd2 exportfs: exportfs:
Jun  3 14:14:53 drbd2 exportfs: /etc/exports [1]: Neither 'subtree_check' or 'no_subtree_check' specified for export "10.8.0.0/16:/disk".
Jun  3 14:14:53 drbd2 exportfs:   Assuming default behaviour ('no_subtree_check').
Jun  3 14:14:53 drbd2 exportfs:   NOTE: this default has changed since nfs-utils version 1.0.x
Jun  3 14:14:53 drbd2 exportfs: exportfs:
Jun  3 14:14:53 drbd2 exportfs: scandir /etc/exports.d: No such file or directory
Jun  3 14:14:53 drbd2 nfs: Exporting NFS file systems: succeeded
Jun  3 14:14:53 drbd2 nfs: rpc.rquotad startup succeeded
Jun  3 14:14:54 drbd2 kernel: [3887694.340342] NFSD: Using /var/lib/nfs/v4recovery as the NFSv4 state recovery directory
Jun  3 14:14:54 drbd2 kernel: [3887694.340372] NFSD: starting 90-second grace period
Jun  3 14:14:54 drbd2 nfs: Starting NFS daemon: succeeded
Jun  3 14:14:54 drbd2 nfs: rpc.mountd startup succeeded
Jun  3 14:14:54 drbd2 idmapd: rpc.idmapd shutdown succeeded
Jun  3 14:14:54 drbd2 idmapd: rpc.idmapd startup succeeded
Jun  3 14:14:54 drbd2 IPaddr[29154]: [29197]: INFO:  Resource is stopped
Jun  3 14:14:54 drbd2 ResourceManager[28857]: [29211]: info: Running /etc/ha.d/resource.d/IPaddr 10.8.100.7/24/eth0 start
Jun  3 14:14:54 drbd2 IPaddr[29242]: [29276]: INFO: Using calculated netmask for 10.8.100.7: 255.255.255.0
Jun  3 14:14:54 drbd2 IPaddr[29242]: [29298]: INFO: eval ifconfig eth0:0 10.8.100.7 netmask 255.255.255.0 broadcast 10.8.100.255
Jun  3 14:14:54 drbd2 IPaddr[29213]: [29317]: INFO:  Success
Jun  3 14:14:54 drbd2 mach_down[28835]: [29319]: info: /usr/share/heartbeat/mach_down: nice_failback: foreign resources acquired
Jun  3 14:14:54 drbd2 mach_down[28835]: [29323]: info: mach_down takeover complete for node drbd1.
Jun  3 14:14:54 drbd2 heartbeat: [4097]: info: mach_down takeover complete.
Jun  3 14:14:56 drbd2 heartbeat: [4097]: info: Heartbeat restart on node drbd1
Jun  3 14:14:56 drbd2 heartbeat: [4097]: info: Link drbd1:eth0 up.
Jun  3 14:14:56 drbd2 heartbeat: [4097]: info: Status update for node drbd1: status init
Jun  3 14:14:56 drbd2 heartbeat: [4097]: info: Status update for node drbd1: status up
Jun  3 14:14:56 drbd2 harc[29324]: [29330]: info: Running /etc/ha.d/rc.d/status status
Jun  3 14:14:56 drbd2 harc[29336]: [29342]: info: Running /etc/ha.d/rc.d/status status
Jun  3 14:14:57 drbd2 heartbeat: [4097]: info: Status update for node drbd1: status active
Jun  3 14:14:57 drbd2 harc[29348]: [29354]: info: Running /etc/ha.d/rc.d/status status
Jun  3 14:14:58 drbd2 heartbeat: [4097]: info: remote resource transition completed.
Jun  3 14:14:58 drbd2 heartbeat: [4097]: info: drbd2 wants to go standby [foreign]
Jun  3 14:14:58 drbd2 heartbeat: [4097]: info: standby: drbd1 can take our foreign resources
Jun  3 14:14:58 drbd2 heartbeat: [29360]: info: give up foreign HA resources (standby).
Jun  3 14:14:58 drbd2 ResourceManager[29373]: [29384]: info: Releasing resource group: drbd1 drbddisk::nfs Filesystem::/dev/drbd1::/disk nfs IPaddr::10.8.100.7/24/eth0
Jun  3 14:14:58 drbd2 ResourceManager[29373]: [29399]: info: Running /etc/ha.d/resource.d/IPaddr 10.8.100.7/24/eth0 stop
Jun  3 14:14:58 drbd2 IPaddr[29430]: [29449]: INFO: ifconfig eth0:0 down
Jun  3 14:14:58 drbd2 IPaddr[29401]: [29452]: INFO:  Success
Jun  3 14:14:58 drbd2 ResourceManager[29373]: [29462]: info: Running /etc/ha.d/resource.d/nfs  stop
Jun  3 14:14:58 drbd2 kernel: [3887699.040703] nfsd: last server has exited, flushing export cache
Jun  3 14:14:58 drbd2 ResourceManager[29373]: [29480]: info: Running /etc/ha.d/resource.d/Filesystem /dev/drbd1 /disk stop
Jun  3 14:14:58 drbd2 Filesystem[29493]: [29523]: INFO: Running stop for /dev/drbd1 on /disk
Jun  3 14:14:58 drbd2 Filesystem[29493]: [29533]: INFO: Trying to unmount /disk
Jun  3 14:14:58 drbd2 Filesystem[29493]: [29535]: INFO: unmounted /disk successfully
Jun  3 14:14:58 drbd2 Filesystem[29482]: [29541]: INFO:  Success
Jun  3 14:14:58 drbd2 ResourceManager[29373]: [29556]: info: Running /etc/ha.d/resource.d/drbddisk nfs stop
Jun  3 14:14:58 drbd2 kernel: [3887699.208152] block drbd1: role( Primary -> Secondary )
Jun  3 14:14:58 drbd2 kernel: [3887699.208176] block drbd1: bitmap WRITE of 0 pages took 0 jiffies
Jun  3 14:14:58 drbd2 kernel: [3887699.208182] block drbd1: 0 KB (0 bits) marked out-of-sync by on disk bit-map.
Jun  3 14:14:58 drbd2 heartbeat: [29360]: info: foreign HA resource release completed (standby).
Jun  3 14:14:58 drbd2 heartbeat: [4097]: info: Local standby process completed [foreign].
Jun  3 14:14:59 drbd2 kernel: [3887699.621693] block drbd1: peer( Secondary -> Primary )
Jun  3 14:15:01 drbd2 heartbeat: [4097]: WARN: 1 lost packet(s) for [drbd1] [13:15]
Jun  3 14:15:01 drbd2 heartbeat: [4097]: info: remote resource transition completed.
Jun  3 14:15:01 drbd2 heartbeat: [4097]: info: No pkts missing from drbd1!
Jun  3 14:15:01 drbd2 heartbeat: [4097]: info: Other node completed standby takeover of foreign resources.

Видно, что DRBD сразу просекает неладное, а через несколько секунд и heartbeat сообщает WARN: node drbd1: is dead потом запускает все что нужно: drbddisk, затем Fileststem, nfs и наконец поднимает IP-адрес.После того как drbd1 опять поднялся, все переключается на него. Я же заметил небольшой затык при копировании на ресурс nfs, после чего процесс продолжился. Разместив на NFS тестовую виртуалку вообще не заметил никаких тормозов при переключении, видимо VMware очень неплохо кеширует данные при работе с диском. На виртуалки drbd1 и drbd2 также установлены vmware-tools, так что если выключение происходит не аварийно, то сервисы переключаются в более штатном режиме.

Скорость

Скорость работы хранилища была измерена при помощи iometer, в результате, при выборе шаблона 4K;75% Read;0% Random, была получена максимальная скорость ~9000 IOPS, после заполнения всевозможных кешей, скорость уперлась в 1236 IOPS, скорость снижалась очень медленно на протяжении четырех часов всего теста.

Стоит отметить, что хосты vmware подключены в коммутаторы Cisco Catalyst 3750, на скорости 1 Гбит/с, одним линком в один коммутатор, а вторым во второй, в свою очередь каталисты объединены в стек. Для работы DRBD используется менеджмент сеть. В будущем планирую попробовать включить Jumbo frames, может будет быстрее.