Отказоустойчивый кластер ( 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) на котором мы и будем располагать нужные нам данные.
Ставим систему на обе ноды, как обычно и кому как нравится. Я ставил без «Х» и все, что сними связанно (игры, менеджеры и прочее).
После установки обновим все пакеты, синхронизируем дату и время.
Создаем пользователя и группу:
# 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
И начинаем ставить необходимые для работы кластера пакеты:
Подробное описание как его собирать
или можно поправить файлы и собрать при помощи 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
все ок!
Цитата из 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
# ./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
# ./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/
терминология: клиентский порт — тот порт, через который идут клиентские запросы. кластерный порт — то, через что идёт репликация. Делается бонд между кластерным портом (который кроссом соединяется) и туннелем в клиентском порте. Если кто-то вынет кластерный провод, трафик пойдёт через туннель в клиентском порте. Если кто-то вынет клиентский провод, кластер останется жить. Если кто-то вынет оба провода, то мы имеем гарантию, что клиент не придёт на сплитбрейновый сервер (т.к. клиентский порт отключен). Когда воткнут клиентский порт, то ПО тут же обнаружит сплитбрейн и отвалится.
Но, пока, я думаю как такое организовать…..
http://blog.demka.org/archives/39
http://www.rhd.ru/docs/manuals/enterprise/RHEL-AS-2.1-Manual/cluster-manager/index.html
http://olemskoi.ru/node/6108
http://habrahabr.ru/post/118925/
http://www.opennet.ru/base/sys/ha_drbl_storage.txt.html
http://www.howtoforge.com/openfiler-2.99-active-passive-with-corosync-pacemaker-and-drbd