Отказоустойчивый кластер ( drbd+heartbeat (Pacemaker) )


Начало

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

Как собрать и где взять - ниже по статье.

На чем испытывалось и работает:
SlackWare Linux - 13.37 c родным ядром - 2.6.37.6-smp

node1 :

 CPU: P4 - 2.4 GHz 
 RAM: 1 Gb
 HDD1(SATA) - 80 GB (система)
 HDD2(SATA) - 80 GB (для drbd)
 Ethernet controller: Intel Corporation 82562EZ 10/100 Ethernet Controller (rev 02)

node2 :

 CPU: P4 - 2.4 GHz 
 RAM: 1 Gb
 HDD1(IDE) - 40 GB (система)
 HDD2(IDE) - 80 GB (для drbd)
 Ethernet controller: 3Com Corporation 3c905 100BaseTX [Boomerang]

Начинаем с разбиения дисков.Я разбил так: node1

 # fdisk -l
 
 Disk /dev/sda: 80.0 GB, 80025280000 bytes
 255 heads, 63 sectors/track, 9729 cylinders, total 156299375 sectors
 .......
 
    Device Boot      Start         End      Blocks   Id  System
 /dev/sda1   *        2048   146802687    73400320   83  Linux
 /dev/sda2       146802688   156299374     4748343+  82  Linux swap 
 
 Disk /dev/sdb: 80.0 GB, 80026361856 bytes
 255 heads, 63 sectors/track, 9729 cylinders, total 156301488 sectors
 ........
 
 Disk /dev/sdb doesn't contain a valid partition table

node2

 # fdisk -l
 
 Disk /dev/sda: 41.1 GB, 41110142976 bytes
 255 heads, 63 sectors/track, 4998 cylinders, total 80293248 sectors
 ........
 
    Device Boot      Start         End      Blocks   Id  System
 /dev/sda1   *        2048    62916607    31457280   83  Linux
 /dev/sda2        62916608    80293247     8688320   82  Linux swap 
 
 Disk /dev/sdb: 82.3 GB, 82347195904 bytes
 255 heads, 63 sectors/track, 10011 cylinders, total 160834367 sectors
 ........
 
 Disk /dev/sdb doesn't contain a valid partition table

Дополнительный винт (/dev/sdb) не разбиваем и не монтируем, а существующие разделы убиваем, т.е. винт девственно чист. Эти два винта и будут между собой зеркалироваться, т.е в дальнейшем, будут единым устройством (/dev/drbd0) на котором мы и будем располагать нужные нам данные.
Ставим систему на обе ноды, как обычно и кому как нравится. Я ставил без «Х» и все, что сними связанно (игры, менеджеры и прочее).
После установки обновим все пакеты, синхронизируем дату и время.

drbd+heartbeat

Создаем пользователя и группу:

 # groupadd -g 226 haclient
 # useradd -u 226 -g haclient -c "Cluster User" -d /var/lib/heartbeat/cores/hacluster -s /bin/false hacluster

в каждой из нод правим файл /etc/hosts, название ноды здесь и в конфигах по всей статье, должно соответствовать выводу команды «uname -n»

 192.168.10.188          node1
 192.168.10.189          node2

И начинаем ставить необходимые для работы кластера пакеты:

  • libheartbeat2 (был переделан из rpm при помощи rpm2tgz)
  • openmpi, или можно поправить файлы и собрать при помощи sbopkg (openmpi-1.4.5-i486-1_SBo.tgz).
  • clusterglue

Подробное описание как его собирать
или можно поправить файлы и собрать при помощи sbopkg (clusterglue-1.0.9-i486-1_SBo.tgz).

Скачиваем, распаковываем и собираем.

 # ./autogen.sh 
 # ./configure \                                                                                                          
 --prefix=/usr \                                                                                                        
 --sysconfdir=/etc \                                                                                                    
 --localstatedir=/var \                                                                                                 
 --mandir=/usr/man \                                                                                                    
 --ith-initdir=/etc/rc.d \                                                                                             
 --enable-libnet \                                                                                                      
 --disable-fatal-warnings
 # make
 # make install DESTDIR=/tmp/ClusterLabs-resource-agents-3.9.2
 # cd /tmp/ClusterLabs-resource-agents-3.9.2
 # makepkg -l y -c n /tmp/ClusterLabs-resource-agents-3.9.2.tgz
 # installpkg ClusterLabs-resource-agents-3.9.2.tgz

Скачиваем, распаковываем и собираем. Обращаем особое внимание, версия ядра и версия drbd должна соответствовать таблице
У нас ядро 2.6.37 значит скачиваем версию 8.3.9

 Linux-release     DRBD-release
       2.6.37                      8.3.9

Как собирать из исходников
я собирал при помощи sbopkg, там он обзывается drbd-tools.

Правим строку в SlackBuild:

 VERSION=${VERSION:-8.3.9}

и info

 PRGNAM="drbd-tools"
 VERSION="8.3.9"
 HOMEPAGE="http://www.drbd.org"
 DOWNLOAD="http://oss.linbit.com/drbd/8.3/drbd-8.3.9.tar.gz"
 MD5SUM="fda3bc1f3f42f3066df33dcb0aa14f2a"
 DOWNLOAD_x86_64=""
 MD5SUM_x86_64=""
 MAINTAINER="Zordrak"
 EMAIL="slackbuilds@tpa.me.uk"
 APPROVED="rworkman"

в итоге получаем пакет drbd-tools-8.3.9-i486-1_SBo.tgz, который сразу же и устанавливаем. (можно в sbopkg указать, чтоб сразу поставил после сборки пакета ).

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

 #./bootstrap
 # ./configure \
 --prefix=/usr \
 --sysconfdir=/etc \
 --localstatedir=/var \
 --mandir=/usr/man \
 --with-initdir=/etc/rc.d \
 --enable-libnet \
 --disable-fatal-warnings
 # make
 # make install DESTDIR=/tmp/heartbeat-3.0.5
 # cd /tmp/heartbeat-3.0.5
 # makepkg  -l y -c n /tmp/heartbeat-3.0.5.tgz
 # installpkg /tmp/heartbeat-3.0.5.tgz

Настраиваем

Редактируем /etc/drbd.d/global_common.conf на обеих нодах.

 global { usage-count yes; }  <-- счетчик юзверей для разработчиков.
 common { syncer { rate 30M;} }  <-- скорость синхронизации (30% от скорости сети),  если сеть  1Гб - 30МБ/с.
 resource r0 {  <--Название ресурса.
    protocol C;  <--Используемый протокол.
 
 handlers {                                                                                                                                                                                                                           
  pri-on-incon-degr "/usr/lib/drbd/notify-pri-on-incon-degr.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f";
  pri-lost-after-sb "/usr/lib/drbd/notify-pri-lost-after-sb.sh; /usr/lib/drbd/notify-emergency-reboot.sh; echo b > /proc/sysrq-trigger ; reboot -f";
  local-io-error "/usr/lib/drbd/notify-io-error.sh; /usr/lib/drbd/notify-emergency-shutdown.sh; echo o > /proc/sysrq-trigger ; halt -f";
  # split-brain "/usr/lib/drbd/notify-split-brain.sh root"; <---Можно убрать коммент, если хотим получать сообщения по почте при возникновении split-brain.
 }
 
 startup {} 
 
 disk {
  on-io-error detach; <--Перестаем работать, если на диске I/O ошибки.
 }
 
 net {  # Пытаемся решить проблему со split-brain
   after-sb-0pri discard-younger-primary;     
   after-sb-1pri consensus;
 }
 
 # описываем  ноды
 on node1 { <---Не забываем, название ноды должно соответствовать  выводу команды uname -n
  device  /dev/drbd0; <--Устройство drbd.
  disk    /dev/sdb; <--Физический диск для нашего устройства.
  address 192.168.10.188:7789; <--IP адрес и порт ноды для связи с остальными нодами.
  meta-disk internal; <--мета диск, где будут храниться метаданные. В нашем случае это /dev/sdb, внутренний (internal). Можно выделить отдельный сервер.
 }
 
 on node2 {
  device  /dev/drbd0;
  disk    /dev/sdb;
  address 192.168.10.189:7789;
  meta-disk internal;
 }
                           }

Комментируем строку в файле /etc/drbd.conf на обеих нодах:

 include "drbd.d/*.res";

Инициализируем хранилище метаданных на обеих нодах:

 # drbdadm create-md r0
 Writing meta data...
 initializing activity log
 NOT initialized bitmap
 New drbd meta data block successfully created.
 success

Переименовываем на обеих нодах /etc/rc.d/drbd в /etc/rc.d/rc.drbd и запускаем сначала на первой ноде, а потом на второй:

 # /etc/rc.d/rc.drbd start
 Starting DRBD resources: [ d(r0) s(r0) n(r0) ]..........
 ***************************************************************
  DRBD's startup script waits for the peer node(s) to appear.
  - In case this node was already a degraded cluster before the
    reboot the timeout is 0 seconds. [degr-wfc-timeout]
  - If the peer was available before the reboot the timeout will
    expire after 0 seconds. [wfc-timeout]
    (These values are for resource 'r0'; 0 sec -> wait forever)
  To abort waiting enter 'yes' [  18]:          <---- тут ждет вторую ноду! Надо запустить и там!
 .                                              <---- запустилась
 #

Смотрим на первой ноде…

 # cat /proc/drbd
 version: 8.3.9 (api:88/proto:86-95)
 srcversion: A67EB2D25C5AFBFF3D8B788 
 0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r-----
 ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:78148320

Смотрим на второй ноде…

 # cat /proc/drbd
 version: 8.3.9 (api:88/proto:86-95)
 srcversion: A67EB2D25C5AFBFF3D8B788 
 0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r-----
 ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:78148320

видим разницу? - нет (очень хорошо :)

cs:Connected — статус (если что-другое, значить DRBD ресурс не готов).
ro:Secondary/Secondary — обе ноды вторичны, а надо, чтоб одна была первичной!
ds:Inconsistent/Inconsistent — состояние данных на нодах. У нас они несогласованны.

Делаем первичной ноду-1, на ней же командуем:

 # drbdadm -- --overwrite-data-of-peer primary r0
 
  --==  Thank you for participating in the global usage survey  ==--
 The server's response is: 
 
 node already registered

и смотрим процесс синхронизации

 # watch cat /proc/drbd
 
 Every 2.0s: cat /proc/drbd  Thu Mar 29 14:31:51 2012
 
  version: 8.3.9 (api:88/proto:86-95)
  srcversion: A67EB2D25C5AFBFF3D8B788
  0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
     ns:8563880 nr:0 dw:0 dr:8572696 al:0 bm:522 lo:1 pe:16 ua:64 ap:0 ep:1 wo:f oos:69586400
         [=>..................] sync'ed: 11.0% (67952/76316)M
         finish: 1:39:35 speed: 11,640 (11,476) K/sec

Обязательно дожидаемся конца синхронизации !!! ( 80 Гб — более полутора часов на моих 100 Мбит/с %) )
дождались…

смотрим на первой ноде:

 # cat /proc/drbd
 version: 8.3.9 (api:88/proto:86-95)
 srcversion: A67EB2D25C5AFBFF3D8B788 
 0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
 ns:14400 nr:0 dw:14400 dr:701 al:9 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0

смотрим на второй ноде:

 # cat /proc/drbd
 version: 8.3.9 (api:88/proto:86-95)
 srcversion: A67EB2D25C5AFBFF3D8B788 
 0: cs:Connected ro:Secondary/Primary ds:UpToDate/UpToDate C r-----
 ns:0 nr:28784 dw:28784 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0

Все правильно! Первая - primary, Вторая - secondary и данные согласованы (на сей момент)

Создаем файловую систему на /dev/drbd0

 # mkfs.ext4 /dev/drbd0
 mke2fs 1.41.14 (22-Dec-2010)
 Filesystem label=
 OS type: Linux
 Block size=4096 (log=2)
 Fragment size=4096 (log=2)
 Stride=0 blocks, Stripe width=0 blocks
 4890624 inodes, 19537080 blocks
 976854 blocks (5.00%) reserved for the super user
 First data block=0
 Maximum filesystem blocks=0
 597 block groups
 32768 blocks per group, 32768 fragments per group
 8192 inodes per group
 Superblock backups stored on blocks: 
         32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
         4096000, 7962624, 11239424 
 
 Writing inode tables: done                            
 Creating journal (32768 blocks): done
 Writing superblocks and filesystem accounting information: done
 
 This filesystem will be automatically checked every 39 mounts or
 180 days, whichever comes first.  Use tune2fs -c or -i to override.

На ноде-1 монтируем и смотрим результат :

 # mkdir /claster
 # mkdir /claster/drbd0
 # mount /dev/drbd0 /claster/drbd0
 # df -h
 Filesystem      Size  Used Avail Use% Mounted on
 /dev/root        69G  3.6G   62G   6% /
 tmpfs           494M     0  494M   0% /dev/shm
 /dev/drbd0       74G  180M   70G   1% /claster/drbd0
 
 # /etc/rc.d/rc.drbd status
 drbd driver loaded OK; device status:
 version: 8.3.9 (api:88/proto:86-95)
 srcversion: A67EB2D25C5AFBFF3D8B788 
 m:res  cs         ro                 ds                 p  mounted         fstype
 0:r0   Connected  Primary/Secondary  UpToDate/UpToDate  C  /claster/drbd0  ext4

На первой ноде, в /claster/drbd0, создадим файл readme.txt с текстом «My first claster».

 # echo 'My first claster' > /claster/drbd0/readme.txt

Для того, чтобы примонтировать и посмотреть на ноде-2, необходимо размонтировать на первой и перевести ее в Secondary, а вторую в Primary.

На ноде-1 это делается командой:

 # drbdadm secondary r0

И соответственно на ноде-2 командой:

 # drbdadm primary r0

Теперь можно примонтировать и посмотреть — все будет идентично и наш файл readme.txt ,будет там, где и должен быть!

Дальше, настраиваем heartbeat на обеих нодах.
Heartbeat - продукт проекта Linux-HA, позволяющий реализовать механизм безотказной работы отдельных частей кластера.
Примеры файлов конфигурации можно взять в /usr/share/doc/heartbeat.
Редактируем: /etc/ha.d/authkeys

 auth 2                                                                                                                 
 2 sha1 10PiloMaterial54   

тут, autch (1, 2, 3) - Метод хеширования (1 - crc; 2- sha1; 3-md5);
хешируем sha1 слово «10PiloMaterial54»

Ограничиваем authkeys только пользователем root.

 # chmod 600 /etc/ha.d/authkeys

/etc/ha.d/authkeys/ha.cf

 debugfile /var/log/ha-debug.log  <--Дебажный лог файл.
 logfile>/var/log/ha.log  <--Обычный лог файл.
 logfacility local0 <--Вывод в syslog.
 keepalive 2  <--Как часто (в сек.) проверять состояние другой ноды.
 deadtime 30  <--Как быстро (в сек.) надо решить, что другая нода вышла из строя.
 initdead 120  <--Дополнительный счетчик (обычно для интерфейсов, которые начинают корректно работать только после перезагрузки)
 bcast eth0  <--Через какой интерфейс отправлять broatcast запросы.
 auto_failback on  <-- авто переключения primary ноды, если она упадет, а потом снова восстановится.
 node node1  
 node node2  
 respawn hacluster /usr/lib/heartbeat/ipfail  <--ipfail следит за стоянием трафика и если какая-то нода испытывает затруднения, то iptraf отдаст primary  привилегию другой.
 use_logd yes  <--Использовать ли демон логирования.

создадим файлы логов.

 # touch  /var/log/{ha.log,ha-debug.log}

/etc/ha.d/haresources
(указываем на каком IP будут работать пользователи с этим сервером, какая фс и куда будет монтироваться, какие сервисы надо запускать. В данном случае апач).

 node1 IPaddr::192.168.10.190/24 drbddisk::r0 \
 Filesystem::/dev/drbd0::/claster/drbd0::ext4::defaults rc.httpd

node1 - Эта нода, при старте heartbeat будет Primary;
IPaddr::192.168.10.190/24 - IP с которым будут работать пользователи с этим сервером;
drbddisk::r0 - DRBD диск, обозначенный нами как ресурс r0;
Filesystem::/dev/drbd0::/claster/drbd0::ext4::defaults - Куда примонтировать drbd, какая ФС используется и дополнительные ключи (у нас по умолчанию);
rc.httpd - какой сервис будем запускать. Сервисы указываются через пробел (rc.httpd rc.dhcp rc.samba и т.д.).

Файлы authkeys, ha.cf, haresources копируем и на ноду-2 и даем права файлу authkeys

 # chmod 600 /etc/ha.d/authkeys

Проверяем работу кластера

Создадим каталоги на обеих нодах.

 # mkdir /claster/drbd0/www/cgi-bin
 # mkdir /claster/drbd0/www/htdocs
 # mkdir /claster/drbd0/www/logs

В /claster/drbd0/www/htdocs/index.html

 
 <html><body><h1>It is my claster !</h1></body></html>

В /etc/httpd/httpd.conf отредактируем соответствующие строчки и скопируем на ноду-2: (сохраните оригинальный ;) )

 DocumentRoot "/claster/drbd0/www/htdocs" 
 <Directory "/claster/drbd0/www/htdocs">
 ErrorLog "/claster/drbd0/www/log/error_log"
 CustomLog "/claster/drbd0/www/log/access_log" common
 ScriptAlias /cgi-bin/ "/claster/drbd0/www/cgi-bin/" 
 <Directory "/claster/drbd0/www/cgi-bin">

И запустим heartbeat на обеих нодах.
Для это переименуем файл /etc/rc.d/heartbeat в /etc/rc.d/rc.heartbeat

 # /etc/rc.d/rc.heartbeat start
 Starting High-Availability services: IPaddr[15551]: INFO:  Resource is stopped                                            
                             [  OK  ]

смотрим на первой ноде.

 # ifconfig
 
 eth0      Link encap:Ethernet  HWaddr 00:11:D8:DD:38:F2  
           inet addr:192.168.10.188  Bcast:192.168.10.255  Mask:255.255.255.0
           .....
 
 eth0:0    Link encap:Ethernet  HWaddr 00:11:D8:DD:38:F2  
           inet addr:192.168.10.190  Bcast:192.168.10.255  Mask:255.255.255.0
           .....
 
 lo        Link encap:Local Loopback  
           inet addr:127.0.0.1  Mask:255.0.0.0
           .....

на второй ноде.

 # ifconfig
 
 eth0      Link encap:Ethernet  HWaddr 00:10:4B:26:86:49  
           inet addr:192.168.10.189  Bcast:192.168.10.255  Mask:255.255.255.0
           .....
 lo        Link encap:Local Loopback  
           inet addr:127.0.0.1  Mask:255.0.0.0
           .....

Мы видим, что появился новый псевдоинтерфейс eth0:0 с IP-192.168.10.190.
Заходим в браузере на http://192.168.10.190/index.html и видим: It is my claster !

Выдергиваем кабель из первой ноды (или останавливаем heartbeat) и видим:
на первой ноде.

 # ifconfig
 
 eth0      Link encap:Ethernet  HWaddr 00:11:D8:DD:38:F2  
           inet addr:192.168.10.188  Bcast:192.168.10.255  Mask:255.255.255.0
           ....
 
 lo        Link encap:Local Loopback  
           inet addr:127.0.0.1  Mask:255.0.0.0
           ....

и на второй ноде.

 # ifconfig
 
 eth0      Link encap:Ethernet  HWaddr 00:10:4B:26:86:49  
           inet addr:192.168.10.189  Bcast:192.168.10.255  Mask:255.255.255.0
           ..... 
 
 eth0:0    Link encap:Ethernet  HWaddr 00:10:4B:26:86:49  
           inet addr:192.168.10.190  Bcast:192.168.10.255  Mask:255.255.255.0
           ....
 
 lo        Link encap:Local Loopback  
           inet addr:127.0.0.1  Mask:255.0.0.0
           .....

Псевдоинтерфейс с IP перекочевали на ноду-2!
А, что апач? обновляем страничку и видим: It is my claster !

Все работает :) !

Проблемы

Если в логах видим такую картину

 block drbd0: Split-Brain detected but unresolved, dropping connection!
 block drbd0: helper command: /sbin/drbdadm split-brain minor-0
 block drbd0: helper command: /sbin/drbdadm split-brain minor-0 exit code 0 (0x0)
 block drbd0: conn( WFReportParams -> Disconnecting )
 block drbd0: error receiving ReportState, l: 4!
 block drbd0: asender terminated
 block drbd0: Terminating asender thread
 block drbd0: Connection closed
 block drbd0: conn( Disconnecting -> StandAlone )
 block drbd0: receiver terminated
 block drbd0: Terminating receiver thread

и на первой ноде:

 # cat /proc/drbd
  0: cs:WFConnection ro:Primary/Unknown ds:UpToDate/DUnknown C r-----
     ns:0 nr:0 dw:52 dr:1117 al:4 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:633896

а на второй:

 # cat /proc/drbd
 0: cs:StandAlone ro:Secondary/Unknown ds:UpToDate/DUnknown   r-----
     ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:53388

Поздравляю, у вас Split-Brain :(
Цитата из http://www.opennet.ru/base/sys/ha_drbl_storage.txt.html

  При падении/отключении одного их узлов второй принимает управление самостоятельно, 
 самое неприятное что может произойти - это ситуация, когда узлы теряют друг друга из вида,
 при этом остаются on-line, оба считают себя единственными выжившими и обслуживают пользователей. 
 В таком случае некоторое время оба узла работают в режиме Primary, и данные на них расходятся. 
 При появлении связи между узлами drbd не сможет самостоятельно принять решение кого оставить.
 Такая ситуация называется split-brain. DRBD попытается разрешить split-brain пользуясь директивами:
  
               after-sb-0pri discard-younger-primary;
               after-sb-1pri consensus;
  
  файла конфигурации.
  
   Т.е. если split-brain произошел после того как оба узла были secondary то выбрать последнего 
 primary в качестве ведущего, если split-brain при одном ведущем, опустить его до secondary и 
 попробовать разрешить ситуацию по первому алгоритму. Если эти варианты не приемлемы, то узлы
 переходят в состояние StandAlone, т.е. синхронизации не происходит.

Пробуем исправить.
Выполняем на первой ноде:

 # drbdadm disconnect r0
 # drbdadm connect r0

Если не помогло, то на второй ноде:

 # drbdadm disconnect r0
 # drbdadm -- --discard-my-data connect r0
 # watch cat /proc/drbd
 version: 8.3.9 (api:88/proto:86-95)
 srcversion: A67EB2D25C5AFBFF3D8B788 
  0: cs:SyncTarget ro:Secondary/Primary ds:Inconsistent/UpToDate C r-----
     ns:0 nr:140456 dw:140456 dr:0 al:0 bm:21 lo:1 pe:8 ua:0 ap:0 ep:1 wo:f oos:493440
         [===>................] sync'ed: 22.6% (493440/633896)K
         finish: 0:00:45 speed: 10,804 (10,804) want: 10,240 K/sec

Дожидаемся завершения и на первой ноде повторяем:

 # drbdadm disconnect r0
 # drbdadm connect r0
 # cat /proc/drbd
 version: 8.3.9 (api:88/proto:86-95)
 srcversion: A67EB2D25C5AFBFF3D8B788 
  0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
     ns:0 nr:0 dw:52 dr:635013 al:4 bm:67 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0

все ок!

Чтобы в ручную не запускать DRBD и HEARTBEAT при запуске нод, прописываем в /etc/rc.d/rc.local каждой ноды:

/etc/rc.d/rc.drbd start
/etc/rc.d/rc.heartbeat start

и, если по какой-то причине будут выключены обе ноды, то включать лучше сначала ноду-1, а потом ноду-2 (сначала Primary, потом Secondary).

Pacemaker

Цитата из http://olemskoi.ru/node/6108

    Pacemaker позволяет гибко распределять ресурсы по узлам кластера, 
 следить за их доступностью, поднимать в случае падения ресурса, 
 отрабатывать failover целого узла.
 
     Если говорить кратко, Pacemaker работает по принципу Heartbeat, 
 только расширяет его функциональность до высоких высот. Во-первых, 
 Pacemaker может управлять более чем двумя узлами кластера, во-вторых, 
 мониторить состояние ресурсов, в-третьих, позволяет ресурсы клонировать. 
 И еще много-много чего другого.
 
     Pacemaker представляет из себя конгломерат из пакетов Pacemaker, Corosyc, OpenAIS, Heartbeat.
 Pacemaker использует транспорт сообщений Corosync/OpenAIS либо Heartbeat для взаимодействия между
 узлами кластера. При этом действующий транспорт в кластере может быть только одного типа: 
 либо Corosync/OpenAIS, либо Heartbeat.
 
     Не смотря на то, что предпочтительным транспортом является Corosync, пакет Heartbeat
 так же должен быть установлен, поскольку он включает в себя достаточно большое количество
 OCF скриптов для управления ресурсами кластера.

Приступим.
Отключим drbd и heartbeat на обеих нодах.

 # /etc/rc.d/rc.heartbeat stop
 Stopping High-Availability services:                       [  OK  ]
 
 # /etc/rc.d/rc.drbd stop
 Stopping all DRBD resources: .

И начинаем устанавливать недостающие пакеты.
libqb

 # git clone git://github.com/asalkeld/libqb.git
 # ./autogen.sh
 # ./configure \
 --prefix=/usr \
 --libdir=/usr/lib \
 --sysconfdir=/etc \
 --localstatedir=/var \
 --mandir=/usr/man \
 --docdir=/usr/doc
 # make
 # make install DESTDIR=/tmp/libqb
 # cd /tmp/libqb
 # makepkg  -l y -c n /tmp/libqb.tgz
 # installpkg /tmp/libqb.tgz

corosync

 # ./configure \
 --prefix=/usr \                                                                                                
 --libdir=/usr/lib \
 --sysconfdir=/etc \
 --localstatedir=/var \
 --mandir=/usr/man \
 --docdir=/usr/doc \
 --disable-nss \
 --with-initddir=/etc/rc.d
 # make
 # make install DESTDIR=/tmp/corosync-1.4.2
 # cd /tmp/corosync-1.4.2
 # makepkg  -l y -c n /tmp/corosync-1.4.2.tgz
 # installpkg /tmp/corosync-1.4.2.tgz

openais

 # ./configure \
 --prefix=/usr \
 --libdir=/usr/lib \
 --sysconfdir=/etc \
 --localstatedir=/var \
 --mandir=/usr/man \
 --docdir=/usr/doc \
 --with-initddir=/etc/rc.d \
 --with-lcrso-dir=/usr/libexec/lcrso
 # make
 # make install DESTDIR=/tmp/openais-1.1.4
 # cd /tmp/openais-1.1.4
 # makepkg  -l y -c n /tmp/openais-1.1.4.tgz
 # installpkg /tmp/openais-1.1.4.tgz

Скачиваем и устанавливаем libesmtp

Скачиваем и распаковываем Pacemaker

 # . /autogen.sh
 # . /configure \
 --prefix=/usr \
 --with-ais-prefix=/usr \
 --libdir=/usr/lib \
 --sysconfdir=/etc \
 --localstatedir=/var \
 --mandir=/usr/man \
 --docdir=/usr/doc \
 --with-lcrso-dir=/usr/libexec/lcrso \
 --with-initdir=/etc/rc.d \
 --with-snmp \
 --with-esmtp \
 --with-ais \
 --without-heartbeat \     //'<---Потому-что он у нас уже стоит.//'
 --enable-bundled-ltdl \
 --enable-libnet
 # make
 # make install DESTDIR=/tmp/pacemaker-1.2
 # cd /tmp/pacemaker-1.2
 # makepkg  -l y -c n /tmp/pacemaker-1.2.tgz
 # installpkg /tmp/pacemaker-1.2.tgz

Файл /etc/corosync/authkey суть случайная последовательность байт длинной около 128 байт, должен быть одинаковый для всех нод кластера. Следовательно, для первой ноды кластера мы его создаем.

 # dd if=/dev/urandom of=/etc/corosync/authkey bs=1 count=128

и ограничиваем root'ом

 # chmod 600 /etc/corosync/authkey

Для связки corosync и pacemaker необходим файл /etc/corosync/service.d/pcmk с текстом:

 service {
 # Load the Pacemaker Cluster Resource Manager
 name: pacemaker
 ver: 0
 }
 END

Создаем, вписываем текст и даем права на запуск.
А для второй ноды мы просто копируем оба эти файла, не забывая потом, дать права.

Далее, переименуем /etc/rc.d/openais в /etc/rc.d/rc.openais и /etc/rc.d/corosync в /etc/rc.d/rc.corosync.
Стартуем:

 # /etc/rc.d/rc.openais start
 # /etc/rc.d/rc.corosync start

И смотрим:

 # grep pcmk_startup /var/log/messages
 Apr  2 19:01:21 node1 corosync[6345]:   [pcmk  ] info: pcmk_startup: CRM: Initialized
 Apr  2 19:01:21 node1 corosync[6345]:   [pcmk  ] Logging: Initialized pcmk_startup
 Apr  2 19:01:21 node1 corosync[6345]:   [pcmk  ] info: pcmk_startup: Maximum core file size is: 4294967295
 Apr  2 19:01:21 node1 corosync[6345]:   [pcmk  ] info: pcmk_startup: Service: 9
 Apr  2 19:01:21 node1 corosync[6345]:   [pcmk  ] info: pcmk_startup: Local hostname: node1 
 
 # grep ERROR: /var/log/messages | grep -v unpack_resources
 # 
 
 # crm_mon
 ============
 Last updated: Tue Apr  3 09:28:47 2012
 Stack: openais
 Current DC: node1 - partition with quorum
 Version: 1.1.1-cc0e4d295e298510dad994ad5f9f6a8ffbf9f9ff 
 2 Nodes configured, 2 expected votes
 0 Resources configured.
 ============
 
 Online: [ node1 node2 ]
 
 # crm configure show
 node node1
 node node2
 property $id="cib-bootstrap-options" \
         dc-version="1.1.1-cc0e4d295e298510dad994ad5f9f6a8ffbf9f9ff" \
         cluster-infrastructure="openais" \
         expected-quorum-votes="2" 
 
 # crm_verify -L
 crm_verify[6633]: 2012/04/03_09:30:55 ERROR: unpack_resources: Resource start-up disabled since no STONITH resources have been defined
 crm_verify[6633]: 2012/04/03_09:30:55 ERROR: unpack_resources: Either configure some or disable STONITH with the stonith-enabled option
 crm_verify[6633]: 2012/04/03_09:30:55 ERROR: unpack_resources: NOTE: Clusters with shared data need STONITH to ensure data integrity
 Errors found during check: config not valid
   -V may provide more details

STONITH — не сконфигурирован, пока отключим.

 # crm configure property stonith-enabled=false
 # crm configure show
 node node1
 node node2
 property $id="cib-bootstrap-options" \
         dc-version="1.1.1-cc0e4d295e298510dad994ad5f9f6a8ffbf9f9ff" \
         cluster-infrastructure="openais" \
         expected-quorum-votes="2" \
         stonith-enabled="false"

идем дальше…
Цитата из http://olemskoi.ru/node/6108

 Ресурсы
  
 Что есть ресурс с точки зрения pacemaker? 
 Все, что может быть заскриптовано. Обычно скрипты пишутся на bash,
 но ничто не мешает вам писать их на Perl, Python или даже на C. 
 Все, что требуется от скрипта, это выполнять 3 действия: start, stop и monitor.
 В общем-то скрипты должны соответствовать LSB (Linux Standard Base) или
 OCF (Open Cluster Framework) — последнее несколько расширяет LSB, требуя также
 передачи параметров через переменные окружения с особым названием.
  
 Ресурс может представлять из себя:
  
 - IP адрес
 - Демон с определенной конфигурацией
 - Блочное устройство
 - Файловую систему
 - etc
  
 Каждый ресурс представляет из себя LSB/OCF скрипт,
 который должен обрабатывать минимум три параметра: start,stop,monitor,
 выдавая корректные коды возврата.
  
 Управление ресурсами осуществляется через команду crm resource:
 
 crm resource stop resource1 - остановить ресурс resource1
 crm resource start resource1 - запустить ресурс resource1
 crm resource move resource1 node2 - принудительно переместить ресурс resource1 на node2
 crm resource cleanup resource1- удалить счетчики сбоев ресурса resource1 со всех узлов
 crm resource cleanup resource1 node2 - удалить счетчики сбоев ресурса resource1 с узла node2
 crm resource help - справка по доступным действиям
 Создание ресурсов осуществляется через //crm configure primitive// … .

Посмотрим какие же у нас установлены агенты ресурсов (Resource Agents):

 # crm ra classes
 heartbeat
 lsb
 ocf / heartbeat linbit pacemaker redhat
 stonith
 # crm ra list ocf heartbeat
 AoEtarget             AudibleAlarm          CTDB                  
 ClusterMon            Delay                 Dummy                 EvmsSCC
 Evmsd                 Filesystem            ICP                   IPaddr                
 IPaddr2               IPsrcaddr             IPv6addr
 .....

Очень много…, все не привожу.
Зададим IP-адрес, через который пользователи будут работать с кластером.

 # crm configure primitive ClusterIP ocf:heartbeat:IPaddr2 params ip=192.168.10.190 cidr_netmask=24 op monitor interval=30s

ClusterIP - имя ресурса
ocf:heartbeat:IPaddr2 - расположение скрипта ресурса. ocf – тип скрипта (ocf или lsb), heartbeat – набор скриптов heartbeat, IPaddr2 - имя скрипта. OCF скрипты располагаются в /usr/lib/ocf.
params ip=… cidr_netmask=… - набор параметров OCF скрипта. Их имена, семантика и использование индивидуальны для каждого скрипта.
op monitor interval=30s - применять к скрипту операцию monitor каждые 30 секунд. В случае если скрипт ocf::IPaddr2 monitor вернул статус отличный от нуля, осуществляется попытка потушить ресурс и поднять его снова. При определенном количестве сбоев осуществляется решение о перемещении ресурса на другой узел.

Смотрим, что получилось:

 # crm configure show
 node node1
 node node2
 primitive ClusterIP ocf:heartbeat:IPaddr2 \
         params ip="192.168.10.190" cidr_netmask="24" \
         op monitor interval="30s"
 property $id="cib-bootstrap-options" \
         dc-version="1.1.1-cc0e4d295e298510dad994ad5f9f6a8ffbf9f9ff" \
         cluster-infrastructure="openais" \
         expected-quorum-votes="2" \
         stonith-enabled="false"
 # crm_mon
 ============
 Last updated: Tue Apr  3 09:42:44 2012
 Stack: openais
 Current DC: node1 - partition with quorum
 Version: 1.1.1-cc0e4d295e298510dad994ad5f9f6a8ffbf9f9ff
 2 Nodes configured, 2 expected votes
 1 Resources configured.
 ============
 
 Online: [ node1 node2 ] 
 
 ClusterIP       (ocf::heartbeat:IPaddr2):       Started node1
 # crm resource status ClusterIP
 resource ClusterIP is running on: node1

Думаю, понятно, что ресурс стартовал на первой ноде.
Но, что самое интересное ping с любого компа в сети:

 # ping 192.168.10.190
 PING 192.168.10.190 (192.168.10.190) 56(84) bytes of data.
 64 bytes from 192.168.10.190: icmp_req=1 ttl=64 time=0.417 ms
 64 bytes from 192.168.10.190: icmp_req=2 ttl=64 time=0.112 ms

а вот результат вывода ifconfig, в это же время, с первой и второй ноды одинаков, привожу только с первой:

 # ifconfig -a
 eth0      Link encap:Ethernet  HWaddr 00:11:D8:DD:38:F2  
              inet addr:192.168.10.188  Bcast:192.168.10.255  Mask:255.255.255.0
              ….............
 
 lo        Link encap:Local Loopback  
            inet addr:127.0.0.1  Mask:255.0.0.0
            …................

Пинг есть, интерфейса нет :)
Почему так, можно посмотреть в скрипте /usr/lib/ocf/resource.d/heartbeat/IPaddr2, я не разбирался.

Проверим работу кластера

На первой ноде останавливаем corosync или можно вообще выключить или ребутнуть комп.

 # /etc/rc.d/rc.corosync stop
 Signaling Corosync Cluster Engine (corosync) to terminate: [  OK  ]
 Waiting for corosync services to unload:.[  OK  ]

Смотрим на второй ноде:

 # crm_mon
 ===========
 Last updated: Tue Apr  3 09:57:30 2012
 Stack: openais
 Current DC: node2 - partition with quorum
 Version: 1.1.1-cc0e4d295e298510dad994ad5f9f6a8ffbf9f9ff
 2 Nodes configured, 2 expected votes
 1 Resources configured.
 ============
 
 Online: [ node2 ]
 OFFLINE: [ node1 ]
 
 ClusterIP       (ocf::heartbeat:IPaddr2):       Started node2

Как видим «Current DC: node2», т.е. Нода-2 теперь у нас главная, а пинги на 192.168.10.190 как шли, так и идут.

Идем дальше. И попробуем поднять апач и посмотреть как он себя поведет при имитации сбоя одной из нод.
Но сначала…..

Сбой демона кворумного раздела.
Цитата из http://www.rhd.ru/docs/manuals/enterprise/RHEL-AS-2.1-Manual/cluster-manager/s1-swinfo-fail.html#S2-SWINFO-NET

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

Цитата из http://habrahabr.ru/post/107837/

 Не забывайте, что кворум достигается когда в строю более половины узлов.
 Поэтому если у вас кластер всего из 2-х, то эту опцию стоит отключить,
 иначе при падении любого из них, кластер будет считать себя развалившимся.

Цитата из http://www.clusterlabs.org/wiki/FAQ

   I Killed a Node but the Cluster Didn't Recover
 One of the most common reasons for this is the way quorum is calculated for
 a 2-node cluster. Unlike Heartbeat, OpenAIS doesn't pretend 2-node clusters
 always have quorum.
   In order to have quorum, more than half of the total number of cluster nodes
 need to be online. Clearly this is not the case when a node failure occurs in a 2-node cluster.
   If you want to allow the remaining node to provide all the cluster services,
 you need to set the no-quorum-policy to ignore.

Поэтому сделаем как советуют, ибо у нас всего 2 ноды:

 # crm configure property no-quorum-policy=ignore

и приступим к апачу….
Цитата из http://habrahabr.ru/post/107837/

 Связи.
 Начнем с того, что любая связь имеет свой вес — целое число
 в пределах от -INFINITY до +INFINITY. При этом если вес связи 
 ± INFINITY, то она считается жесткой, в противном случае — мягкой,
 т.е. если веса других связей окажутся выше, она может быть проигнорирована.
  
 Связи определяют привязку ресурсов к узлу (location), порядок запуска ресурсов
 (ordering) и совместное их проживание на узле (colocation).

Чтобы предотвратить переезды на высоко нагруженном кластере, в случае сбоя и последующего восстановления ноды, которые могут привести к нежелательным простоям, мы должны задать параметр «липкости» (resource-stickiness):

 # crm configure rsc_defaults resource-stickiness=100

И далее

Пропишем апача.

 # crm configure primitive WebSite lsb:rc.httpd op monitor interval="1min"

Здесь мы создали еще один ресурс - WebSite;
Указали, что будем запускать lsb (это те, что у нас в /etc/rc.d) скрипт rc.httpd - lsb:rc.httpd ;
И время мониторинга вновь созданного ресурса - op monitor interval=«1min».

Пропишем drbd

 # crm configure primitive drbd_meta ocf:linbit:drbd params drbd_resource="r0" op monitor interval="15s"

Здесь мы создали еще один ресурс - drbd_meta;
Указали, что будем запускать ocf/linbit скрипт drbd- ocf:linbit:drbd;
Указали наш drbd ресурс r0 ( тот, что прописан в файле /etc/drbd.d/global_common.conf ) - params drbd_resource=«r0»;
И время мониторинга вновь созданного ресурса - op monitor interval=«15s».

Создаем настройку ms (Master/Slave) узлов с именем ms_drbd_meta для ресурса drbd_meta.

 # crm configure ms ms_drbd_meta drbd_meta meta master-max="1" master-node-max="1" clone-max="2" clone-node-max="1" notify="true"

Определяем drbd устройство, его точку монтирования и ФС.

 # crm configure primitive MetaFS ocf:heartbeat:Filesystem params device="/dev/drbd0" directory="/claster/drbd0" fstype="ext4" op monitor interval="15s"

Здесь мы создали еще один ресурс с именем - MetaFS;
Указали, что будем запускать ocf/heartbeat скрипт Filesystem - ocf:heartbeat:Filesystem;
Указали, что будет использоваться устройство /dev/drbd0 смонтированное в /claster/drbd0 c файловой системой ext4 - params device=«/dev/drbd0» directory=«/claster/drbd0» fstype=«ext4»;
И время мониторинга вновь созданного ресурса - op monitor interval=«15s».

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

 # crm configure group my_services MetaFS ClusterIP WebSite

Сначала монтирование drbd, потом поднятие сетевого интерфейса с ip-192.168.10.190 и потом уже запуск апача.

Задаем совместное проживание под именем services_drbd, группы my_services с ресурсом ms_drbd_meta:Master (кстати, -inf означало бы, что ресурсы НЕ должны находиться на одном узле).

 # crm configure colocation services_drbd inf: my_services ms_drbd_meta:Master

Определяем порядок запуска с именем services_after_drbd: сначала ms_drbd_meta, потом наша группа сервисов my_services.

 # crm configure order services_after_drbd inf: ms_drbd_meta:promote my_services:start

Определяем, что группе my_services очень желательно находиться бы на узле node1, с весом 50

 # crm configure location prefer-node1 my_services rule 50: node1

и посмотрим, что получилось:

 # crm configure show
 node node1
 node node2
 primitive ClusterIP ocf:heartbeat:IPaddr2 \
         params ip="192.168.10.190" cidr_netmask="24" \
         op monitor interval="30s"
 primitive MetaFS ocf:heartbeat:Filesystem \
         params device="/dev/drbd0" directory="/claster/drbd0" fstype="ext4" \
         op monitor interval="15s"
 primitive WebSite lsb:rc.httpd \
         op monitor interval="1min"
 primitive drbd_meta ocf:linbit:drbd \
         params drbd_resource="r0" \
         op monitor interval="15s"
 group my_services MetaFS ClusterIP WebSite
 ms ms_drbd_meta drbd_meta \
         meta master-max="1" master-node-max="1" clone-max="2" clone-node-max="1" notify="true"
 location prefer-node1 my_services 50: node1
 colocation services_drbd inf: my_services ms_drbd_meta:Master
 order services_after_drbd inf: ms_drbd_meta:promote my_services:start
 property $id="cib-bootstrap-options" \
         dc-version="1.1.1-cc0e4d295e298510dad994ad5f9f6a8ffbf9f9ff" \
         cluster-infrastructure="openais" \
         expected-quorum-votes="2" \
         stonith-enabled="false" \
         no-quorum-policy="ignore"
 rsc_defaults $id="rsc-options" \
         resource-stickiness="100"
 # crm_mon
 ============
 Last updated: Fri Apr  6 19:32:42 2012
 Stack: openais
 Current DC: node1 - partition with quorum
 Version: 1.1.1-cc0e4d295e298510dad994ad5f9f6a8ffbf9f9ff
 2 Nodes configured, 2 expected votes
 2 Resources configured.
 ============ 
 
 Online: [ node1 node2 ] 
 
  Master/Slave Set: ms_drbd_meta
      Masters: [ node1 ]
      Slaves: [ node2 ]
  Resource Group: my_services
      MetaFS     (ocf::heartbeat:Filesystem):    Started node1
      ClusterIP  (ocf::heartbeat:IPaddr2):       Started node1
      WebSite    (lsb:rc.httpd): Started node1

Теперь можно рестартанут сервисы corosync и openais на обеих нодах, или ребутнуть их.
После загрузки на http://192.168.10.190/index.html появится знакомая нам надпись «'It is my claster !
Теперь, если выдернуть лан-кабель из одной из нод или просто выключить одну из них, все равно апач будет работать.

Для удаления, редактирования и прочих действий можно зайти в консоль crm и там все это сделать.

 # crm
 # crm(live)# 
 # crm(live)# help
 This is the CRM command line interface program. 
 
 
 Available commands:
 
         cib              manage shadow CIBs
         resource         resources management
         node             nodes management
         options          user preferences
         configure        CRM cluster configuration
         ra               resource agents information center
         status           show cluster status
         quit,bye,exit    exit the program
         help             show help
         end,cd,up        go back one level
 crm(live)# configure
 crm(live)configure# 
 crm(live)configure# help
 This level enables all CIB object definition commands.
 
 The configuration may be logically divided into four parts:
 nodes, resources, constraints, and (cluster) properties and
 attributes.  Each of these commands support one or more basic CIB
 objects.
 ….............
 …..............
 # crm(live)configure# exit
 bye

P.S.
Цитата из http://habrahabr.ru/post/118925/

   Использовать STONITH в двухнодном кластере при пропаже линков — бессмысленно.
 Ноды просто убьют друг друга. Мы получим, так называемый deathmatch: 
 одна убивает другую — другая перезагружается и убивает первую и тд. 
 Т.к. не понятно какая из нод «правильная» и нету кворума. 
   В свою очередь, STONITH нужен для убийства ноды с зависшим ресурсом.
 Однако тут много тонкостей с таймаутами мониторинга и остановки ресурсов.
 Можно убить ноду, которая просто замешкалась с отмонтирование файловой системы,
 ожидая, когда её просто освободит процесс. Это вообще отдельная большая тема.

советы как не допустить stonith deathmatch, один из них - не ставить в автозагрузку скрипты запуска corosync и openais.

P.P.S
Можно использовать отдельные адаптеры для репликации, но я так не делал потому что:
Цитата из http://habrahabr.ru/post/118925/

 терминология: клиентский порт — тот порт, через который идут клиентские запросы.
 кластерный порт — то, через что идёт репликация.
  Делается бонд между кластерным портом (который кроссом соединяется) и туннелем в
 клиентском порте. Если кто-то вынет кластерный провод, трафик пойдёт через туннель в клиентском порте.
 Если кто-то вынет клиентский провод, кластер останется жить.
 Если кто-то вынет оба провода, то мы имеем гарантию, что клиент не придёт на сплитбрейновый сервер
 (т.к. клиентский порт отключен). Когда воткнут клиентский порт, то ПО тут же обнаружит сплитбрейн и отвалится.

Но, пока, я думаю как такое организовать…..

Ссылался на....

Навигация
Печать/экспорт
QR Code
QR Code wiki:articles:ha (generated for current page)