| |
— | wiki:articles:ha [29/11/2012 13:44] (текущий) – создано - внешнее изменение 127.0.0.1 |
---|
| ^ **Отказоустойчивый кластер ( drbd+heartbeat (Pacemaker) )** ^ |
| \\ |
| |
| ===== Начало ===== |
| |
| Необходимые пакеты и документацию выложил на локальный ресурс, обновляться будут по мере возможности, так-что за актуальность не ручаюсь, сорри.\\ |
| |
| ^ **Пакеты** ^ **Документация** ^ |
| |[[http://slackware.su/forum/files/libnet-1.1.5-i486-2sl.txz | libnet-1.1.5-i486-2sl.txz]] | [[http://slackware.su/forum/files/Cluster_from_Scratch.pdf | Cluster_from_Scratch.pdf]] | |
| |[[http://slackware.su/forum/files/libheartbeat2-2.99.3-51.1.i586.tgz | libheartbeat2-2.99.3-51.1.i586.tgz]] | [[http://slackware.su/forum/files/Pacemaker_Explained.pdf | Pacemaker_Explained.pdf]] | |
| |[[http://slackware.su/forum/files/openmpi-1.4.5-i486-1_SBo.tgz | openmpi-1.4.5-i486-1_SBo.tgz]] | |
| |[[http://slackware.su/forum/files/clusterglue-1.0.9-i486-1_SBo.tgz | clusterglue-1.0.9-i486-1_SBo.tgz]] | |
| |[[http://slackware.su/forum/files/ClusterLabs-resource-agents-3.9.2.tgz | ClusterLabs-resource-agents-3.9.2.tgz]] | |
| |[[http://slackware.su/forum/files/drbd-tools-8.3.9-i486-1_SBo.tgz | drbd-tools-8.3.9-i486-1_SBo.tgz]] | |
| |[[http://slackware.su/forum/files/heartbeat-3.0.5.tgz | heartbeat-3.0.5.tgz]] | |
| |[[http://slackware.su/forum/files/libqb.tgz | libqb.tgz]] | |
| |[[http://slackware.su/forum/files/corosync-1.4.2.tgz | corosync-1.4.2.tgz]] | |
| |[[http://slackware.su/forum/files/openais-1.1.4.tgz | openais-1.1.4.tgz]] | |
| |[[http://slackware.su/forum/files/libesmtp-1.0.6-i686-1cf.txz | libesmtp-1.0.6-i686-1cf.txz]] | |
| |[[http://slackware.su/forum/files/pacemaker-1.2.tgz | pacemaker-1.2.tgz]] | |
| |
| |
| Как собрать и где взять - ниже по статье. |
| |
| На чем испытывалось и работает:\\ |
| //**SlackWare Linux - 13.37 c родным ядром - 2.6.37.6-smp**// |
| |
| node1 : |
| <code> |
| 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) |
| </code> |
| |
| node2 : |
| <code> |
| CPU: P4 - 2.4 GHz |
| RAM: 1 Gb |
| HDD1(IDE) - 40 GB (система) |
| HDD2(IDE) - 80 GB (для drbd) |
| Ethernet controller: 3Com Corporation 3c905 100BaseTX [Boomerang] |
| </code> |
| Начинаем с разбиения дисков.Я разбил так: |
| node1 |
| <code> |
| # 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 |
| </code> |
| |
| node2 |
| <code> |
| # 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 |
| </code> |
| |
| Дополнительный винт (///dev/sdb//) не разбиваем и не монтируем, а существующие разделы убиваем, т.е. винт девственно чист. Эти два винта и будут между собой зеркалироваться, т.е в дальнейшем, будут единым устройством (///dev/drbd0//) на котором мы и будем располагать нужные нам данные. \\ |
| Ставим систему на обе ноды, как обычно и кому как нравится. Я ставил без <<Х>> и все, что сними связанно (игры, менеджеры и прочее).\\ |
| После установки обновим все пакеты, синхронизируем дату и время. |
| |
| ===== drbd+heartbeat ===== |
| |
| Создаем пользователя и группу: |
| <code> |
| # groupadd -g 226 haclient |
| # useradd -u 226 -g haclient -c "Cluster User" -d /var/lib/heartbeat/cores/hacluster -s /bin/false hacluster |
| </code> |
| |
| в каждой из нод правим файл ///etc/hosts//, название ноды здесь и в конфигах по всей статье, должно соответствовать выводу команды **<<uname -n>>** |
| <code> |
| 192.168.10.188 node1 |
| 192.168.10.189 node2 |
| </code> |
| |
| И начинаем ставить необходимые для работы кластера пакеты: |
| |
| * //**[[http://slackfind.net/ru/packages/search/?name=libnet&distversion=11 | libnet]] **// |
| * //**libheartbeat2**// (был переделан из //rpm// при помощи //rpm2tgz//) |
| * //**[[http://www.open-mpi.org/software/ompi/v1.4/ | openmpi]]**//, или можно поправить файлы и собрать при помощи //sbopkg// (//openmpi-1.4.5-i486-1_SBo.tgz//). |
| * //**clusterglue**// |
| Подробное описание [[http://www.linux-ha.org/doc/users-guide/_building_and_installing_from_source.html | как его собирать]]\\ |
| или можно поправить файлы и собрать при помощи //sbopkg// (//clusterglue-1.0.9-i486-1_SBo.tgz//). |
| * //**[[https://github.com/ClusterLabs/resource-agents/tarball/v3.9.2 | ClusterLabs-resource-agents]]**//\\ |
| Скачиваем, распаковываем и собираем. |
| <code> |
| # ./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 |
| </code> |
| * //**[[http://oss.linbit.com/drbd/ | drbd]]**//\\ |
| Скачиваем, распаковываем и собираем. Обращаем особое внимание, версия ядра и версия //drbd// должна соответствовать [[http://www.drbd.org/download/mainline/ | таблице]]\\ |
| У нас ядро 2.6.37 значит скачиваем версию 8.3.9 |
| <code> |
| Linux-release DRBD-release |
| 2.6.37 8.3.9 |
| </code> |
| |
| [[http://www.drbd.org/users-guide-8.3/ch-build-install-from-source.html | Как собирать из исходников]]\\ |
| я собирал при помощи //sbopkg//, там он обзывается //drbd-tools//. |
| |
| Правим строку в //SlackBuild//: |
| <code> |
| VERSION=${VERSION:-8.3.9} |
| </code> |
| и //info// |
| <code> |
| 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" |
| </code> |
| |
| в итоге получаем пакет //drbd-tools-8.3.9-i486-1_SBo.tgz//, который сразу же и устанавливаем. |
| (можно в //sbopkg// указать, чтоб сразу поставил после сборки пакета ). |
| |
| * //**[[http://hg.linux-ha.org/heartbeat-STABLE_3_0/archive/7e3a82377fa8.tar.bz2 | Heartbeat]]**//\\ |
| [[http://www.linux-ha.org/doc/users-guide/_building_and_installing_heartbeat_from_source.html | Как собирать из исходников]]\\ |
| Скачиваем, распаковываем и устанавливаем: |
| <code> |
| #./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 |
| </code> |
| |
| ==== Настраиваем ==== |
| |
| Редактируем ///etc/drbd.d/global_common.conf// на обеих нодах. |
| <code> |
| 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; |
| } |
| } |
| </code> |
| |
| Комментируем строку в файле ///etc/drbd.conf// на обеих нодах: |
| <code> |
| include "drbd.d/*.res"; |
| </code> |
| Инициализируем хранилище метаданных на обеих нодах: |
| <code> |
| # drbdadm create-md r0 |
| Writing meta data... |
| initializing activity log |
| NOT initialized bitmap |
| New drbd meta data block successfully created. |
| success |
| </code> |
| |
| Переименовываем на обеих нодах ///etc/rc.d/drbd// в ///etc/rc.d/rc.drbd// и запускаем сначала на первой ноде, а потом на второй: |
| <code> |
| # /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]: <---- тут ждет вторую ноду! Надо запустить и там! |
| . <---- запустилась |
| # |
| </code> |
| |
| Смотрим на первой ноде... |
| <code> |
| # 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 |
| </code> |
| Смотрим на второй ноде... |
| <code> |
| # 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 |
| </code> |
| |
| видим разницу? - нет (очень хорошо :) |
| |
| //cs:Connected// — статус (если что-другое, значить DRBD ресурс не готов).\\ |
| //ro:Secondary/Secondary// — обе ноды вторичны, а надо, чтоб одна была первичной!\\ |
| //ds:Inconsistent/Inconsistent// — состояние данных на нодах. У нас они несогласованны.\\ |
| |
| Делаем первичной ноду-1, на ней же командуем: |
| <code> |
| # drbdadm -- --overwrite-data-of-peer primary r0 |
| |
| --== Thank you for participating in the global usage survey ==-- |
| The server's response is: |
| |
| node already registered |
| </code> |
| и смотрим процесс синхронизации |
| <code> |
| # 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 |
| </code> |
| |
| Обязательно дожидаемся конца синхронизации !!! ( 80 Гб — более полутора часов на моих 100 Мбит/с %) )\\ |
| дождались... |
| |
| смотрим на первой ноде: |
| <code> |
| # 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 |
| </code> |
| |
| смотрим на второй ноде: |
| <code> |
| # 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 |
| </code> |
| |
| Все правильно! Первая - //primary//, Вторая - //secondary// и данные согласованы (на сей момент) |
| |
| Создаем файловую систему на ///dev/drbd0// |
| <code> |
| # 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. |
| </code> |
| |
| На ноде-1 монтируем и смотрим результат : |
| <code> |
| # 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 |
| </code> |
| |
| На первой ноде, в ///claster/drbd0//, создадим файл //readme.txt// с текстом //<<My first claster>>//. |
| <code> |
| # echo 'My first claster' > /claster/drbd0/readme.txt |
| </code> |
| |
| Для того, чтобы примонтировать и посмотреть на ноде-2, необходимо размонтировать на первой и перевести ее в //Secondary//, а вторую в //Primary//. |
| |
| На ноде-1 это делается командой: |
| <code> |
| # drbdadm secondary r0 |
| </code> |
| И соответственно на ноде-2 командой: |
| <code> |
| # drbdadm primary r0 |
| </code> |
| |
| Теперь можно примонтировать и посмотреть — все будет идентично и наш файл readme.txt ,будет там, где и должен быть! |
| |
| Дальше, настраиваем //heartbeat// на обеих нодах.\\ |
| //Heartbeat// - продукт проекта Linux-HA, позволяющий реализовать механизм безотказной работы отдельных частей кластера.\\ |
| Примеры файлов конфигурации можно взять в ///usr/share/doc/heartbeat//.\\ |
| Редактируем: |
| ///etc/ha.d/authkeys// |
| <code> |
| auth 2 |
| 2 sha1 10PiloMaterial54 |
| </code> |
| тут, //autch (1, 2, 3)// - Метод хеширования (1 - crc; 2- sha1; 3-md5);\\ |
| хешируем //sha1// слово //<<10PiloMaterial54>>// |
| |
| Ограничиваем //authkeys// только пользователем //root//. |
| <code> |
| # chmod 600 /etc/ha.d/authkeys |
| </code> |
| |
| ///etc/ha.d/authkeys/ha.cf// |
| <code> |
| 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 <--Использовать ли демон логирования. |
| </code> |
| |
| создадим файлы логов. |
| <code> |
| # touch /var/log/{ha.log,ha-debug.log} |
| </code> |
| |
| ///etc/ha.d/haresources//\\ |
| (указываем на каком IP будут работать пользователи с этим сервером, какая фс и куда будет монтироваться, какие сервисы надо запускать. В данном случае апач). |
| <code> |
| node1 IPaddr::192.168.10.190/24 drbddisk::r0 \ |
| Filesystem::/dev/drbd0::/claster/drbd0::ext4::defaults rc.httpd |
| </code> |
| |
| //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// |
| <code> |
| # chmod 600 /etc/ha.d/authkeys |
| </code> |
| |
| ==== Проверяем работу кластера ==== |
| |
| Создадим каталоги на обеих нодах. |
| <code> |
| # mkdir /claster/drbd0/www/cgi-bin |
| # mkdir /claster/drbd0/www/htdocs |
| # mkdir /claster/drbd0/www/logs |
| </code> |
| |
| В ///claster/drbd0/www/htdocs/index.html// |
| <code> |
| <html><body><h1>It is my claster !</h1></body></html> |
| </code> |
| |
| В ///etc/httpd/httpd.conf// отредактируем соответствующие строчки и скопируем на ноду-2: (сохраните оригинальный ;) ) |
| <code> |
| 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"> |
| </code> |
| |
| И запустим //heartbeat// на обеих нодах.\\ |
| Для это переименуем файл ///etc/rc.d/heartbeat// в ///etc/rc.d/rc.heartbeat// |
| <code> |
| # /etc/rc.d/rc.heartbeat start |
| Starting High-Availability services: IPaddr[15551]: INFO: Resource is stopped |
| [ OK ] |
| </code> |
| |
| смотрим на первой ноде. |
| <code> |
| # 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 |
| ..... |
| </code> |
| |
| на второй ноде. |
| <code> |
| # 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 |
| ..... |
| </code> |
| |
| Мы видим, что появился новый псевдоинтерфейс //eth0:0// с IP-//192.168.10.190//.\\ |
| Заходим в браузере на **%%http://192.168.10.190/index.html%%** и видим: //**It is my claster !**// |
| |
| Выдергиваем кабель из первой ноды (или останавливаем //heartbeat//) и видим:\\ |
| на первой ноде. |
| <code> |
| # 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 |
| .... |
| </code> |
| |
| и на второй ноде. |
| <code> |
| # 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 |
| ..... |
| </code> |
| |
| Псевдоинтерфейс с IP перекочевали на ноду-2!\\ |
| А, что апач? обновляем страничку и видим: //**It is my claster !**// |
| |
| Все работает :) ! |
| |
| ==== Проблемы ==== |
| |
| Если в логах видим такую картину |
| <code> |
| 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 |
| </code> |
| |
| и на первой ноде: |
| <code> |
| # 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 |
| </code> |
| |
| а на второй: |
| <code> |
| # 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 |
| </code> |
| |
| Поздравляю, у вас //Split-Brain// :( \\ |
| Цитата из [[http://www.opennet.ru/base/sys/ha_drbl_storage.txt.html]] |
| <code> |
| При падении/отключении одного их узлов второй принимает управление самостоятельно, |
| самое неприятное что может произойти - это ситуация, когда узлы теряют друг друга из вида, |
| при этом остаются 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, т.е. синхронизации не происходит. |
| </code> |
| |
| Пробуем исправить.\\ |
| Выполняем на первой ноде: |
| <code> |
| # drbdadm disconnect r0 |
| # drbdadm connect r0 |
| </code> |
| |
| Если не помогло, то на второй ноде: |
| <code> |
| # 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 |
| </code> |
| |
| Дожидаемся завершения и на первой ноде повторяем: |
| <code> |
| # 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 |
| </code> |
| |
| все ок! |
| |
| <note tip> //Чтобы в ручную не запускать //DRBD// и //HEARTBEAT// при запуске нод, прописываем в ///etc/rc.d/rc.local// каждой ноды:\\ |
| \\ |
| /etc/rc.d/rc.drbd start\\ |
| /etc/rc.d/rc.heartbeat start\\ |
| \\ |
| и, если по какой-то причине будут выключены обе ноды, то включать лучше сначала ноду-1, а потом ноду-2 (сначала Primary, потом Secondary).//</note> |
| |
| |
| ===== Pacemaker ===== |
| |
| Цитата из [[http://olemskoi.ru/node/6108]] |
| <code> |
| Pacemaker позволяет гибко распределять ресурсы по узлам кластера, |
| следить за их доступностью, поднимать в случае падения ресурса, |
| отрабатывать failover целого узла. |
| |
| Если говорить кратко, Pacemaker работает по принципу Heartbeat, |
| только расширяет его функциональность до высоких высот. Во-первых, |
| Pacemaker может управлять более чем двумя узлами кластера, во-вторых, |
| мониторить состояние ресурсов, в-третьих, позволяет ресурсы клонировать. |
| И еще много-много чего другого. |
| |
| Pacemaker представляет из себя конгломерат из пакетов Pacemaker, Corosyc, OpenAIS, Heartbeat. |
| Pacemaker использует транспорт сообщений Corosync/OpenAIS либо Heartbeat для взаимодействия между |
| узлами кластера. При этом действующий транспорт в кластере может быть только одного типа: |
| либо Corosync/OpenAIS, либо Heartbeat. |
| |
| Не смотря на то, что предпочтительным транспортом является Corosync, пакет Heartbeat |
| так же должен быть установлен, поскольку он включает в себя достаточно большое количество |
| OCF скриптов для управления ресурсами кластера. |
| </code> |
| |
| Приступим.\\ |
| Отключим //drbd// и //heartbeat// на обеих нодах. |
| <code> |
| # /etc/rc.d/rc.heartbeat stop |
| Stopping High-Availability services: [ OK ] |
| |
| # /etc/rc.d/rc.drbd stop |
| Stopping all DRBD resources: . |
| </code> |
| |
| И начинаем устанавливать недостающие пакеты.\\ |
| //**libqb**// |
| <code> |
| # 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 |
| </code> |
| |
| //**[[http://ftp://corosync.org/downloads/corosync-1.4.2/corosync-1.4.2.tar.gz | corosync]]**// |
| <code> |
| # ./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 |
| </code> |
| |
| //**[[http://ftp://openais.org/downloads/openais-1.1.4/openais-1.1.4.tar.gz | openais]]**// |
| <code> |
| # ./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 |
| </code> |
| |
| Скачиваем и устанавливаем //**[[http://www.slackers.it/repository/libesmtp/pkg/libesmtp-1.0.6-i686-1cf.txz | libesmtp]]**// |
| |
| Скачиваем и распаковываем //**[[http://hg.clusterlabs.org/pacemaker/1.2/shortlog/cc0e4d295e29 | Pacemaker]]**// |
| <code> |
| # . /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 |
| </code> |
| |
| Файл ///etc/corosync/authkey// суть случайная последовательность байт длинной около 128 байт, должен быть одинаковый для всех нод кластера. Следовательно, для первой ноды кластера мы его создаем. |
| <code> |
| # dd if=/dev/urandom of=/etc/corosync/authkey bs=1 count=128 |
| </code> |
| |
| и ограничиваем //root//'ом |
| <code> |
| # chmod 600 /etc/corosync/authkey |
| </code> |
| |
| Для связки //corosync// и //pacemaker// необходим файл ///etc/corosync/service.d/pcmk// с текстом: |
| <code> |
| service { |
| # Load the Pacemaker Cluster Resource Manager |
| name: pacemaker |
| ver: 0 |
| } |
| END |
| </code> |
| |
| Создаем, вписываем текст и даем права на запуск.\\ |
| А для второй ноды мы просто копируем оба эти файла, не забывая потом, дать права.\\ |
| |
| Далее, переименуем ///etc/rc.d/openais// в ///etc/rc.d/rc.openais// и ///etc/rc.d/corosync// в ///etc/rc.d/rc.corosync//. \\ |
| Стартуем: |
| <code> |
| # /etc/rc.d/rc.openais start |
| # /etc/rc.d/rc.corosync start |
| </code> |
| |
| И смотрим: |
| <code> |
| # 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 |
| </code> |
| |
| |
| //STONITH// — не сконфигурирован, пока отключим. |
| |
| <code> |
| # 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" |
| </code> |
| |
| идем дальше...\\ |
| Цитата из [[http://olemskoi.ru/node/6108]] |
| <code> |
| Ресурсы |
| |
| Что есть ресурс с точки зрения 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// … . |
| </code> |
| |
| Посмотрим какие же у нас установлены агенты ресурсов (//Resource Agents//): |
| <code> |
| # crm ra classes |
| heartbeat |
| lsb |
| ocf / heartbeat linbit pacemaker redhat |
| stonith |
| </code> |
| |
| <code> |
| # crm ra list ocf heartbeat |
| AoEtarget AudibleAlarm CTDB |
| ClusterMon Delay Dummy EvmsSCC |
| Evmsd Filesystem ICP IPaddr |
| IPaddr2 IPsrcaddr IPv6addr |
| ..... |
| </code> |
| |
| Очень много..., все не привожу.\\ |
| Зададим IP-адрес, через который пользователи будут работать с кластером. |
| <code> |
| # crm configure primitive ClusterIP ocf:heartbeat:IPaddr2 params ip=192.168.10.190 cidr_netmask=24 op monitor interval=30s |
| </code> |
| |
| //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// вернул статус отличный от нуля, осуществляется попытка потушить ресурс и поднять его снова. При определенном количестве сбоев осуществляется решение о перемещении ресурса на другой узел. |
| |
| Смотрим, что получилось: |
| <code> |
| # 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" |
| </code> |
| <code> |
| # 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 |
| </code> |
| <code> |
| # crm resource status ClusterIP |
| resource ClusterIP is running on: node1 |
| </code> |
| |
| Думаю, понятно, что ресурс стартовал на первой ноде.\\ |
| Но, что самое интересное ping с любого компа в сети: |
| <code> |
| # 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 |
| </code> |
| |
| а вот результат вывода //ifconfig//, в это же время, с первой и второй ноды одинаков, привожу только с первой: |
| <code> |
| # 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 |
| …................ |
| </code> |
| |
| Пинг есть, интерфейса нет :)\\ |
| Почему так, можно посмотреть в скрипте ///usr/lib/ocf/resource.d/heartbeat/IPaddr2//, я не разбирался. |
| |
| ==== Проверим работу кластера ==== |
| |
| На первой ноде останавливаем //corosync// или можно вообще выключить или ребутнуть комп. |
| <code> |
| # /etc/rc.d/rc.corosync stop |
| Signaling Corosync Cluster Engine (corosync) to terminate: [ OK ] |
| Waiting for corosync services to unload:.[ OK ] |
| </code> |
| |
| Смотрим на второй ноде: |
| <code> |
| # 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 |
| </code> |
| |
| Как видим «//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]] \\ |
| <code> |
| Если в кластерной системе отказывает демон кворума, |
| система больше не сможет наблюдать за кворумными разделами. |
| Если в кластере не применяются переключатели питания, при |
| описанных выше условиях служба может начать работу сразу в |
| нескольких кластерных системах, что может привести к разрушению данных. |
| </code> |
| |
| Цитата из [[http://habrahabr.ru/post/107837/]] |
| <code> |
| Не забывайте, что кворум достигается когда в строю более половины узлов. |
| Поэтому если у вас кластер всего из 2-х, то эту опцию стоит отключить, |
| иначе при падении любого из них, кластер будет считать себя развалившимся. |
| </code> |
| |
| Цитата из [[http://www.clusterlabs.org/wiki/FAQ]] |
| <code> |
| 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. |
| </code> |
| |
| Поэтому сделаем как советуют, ибо у нас всего 2 ноды: |
| <code> |
| # crm configure property no-quorum-policy=ignore |
| </code> |
| |
| и приступим к апачу....\\ |
| Цитата из [[http://habrahabr.ru/post/107837/]] |
| <code> |
| Связи. |
| Начнем с того, что любая связь имеет свой вес — целое число |
| в пределах от -INFINITY до +INFINITY. При этом если вес связи |
| ± INFINITY, то она считается жесткой, в противном случае — мягкой, |
| т.е. если веса других связей окажутся выше, она может быть проигнорирована. |
| |
| Связи определяют привязку ресурсов к узлу (location), порядок запуска ресурсов |
| (ordering) и совместное их проживание на узле (colocation). |
| </code> |
| |
| Чтобы предотвратить переезды на высоко нагруженном кластере, в случае сбоя и последующего восстановления ноды, которые могут привести к нежелательным простоям, мы должны задать параметр <<липкости>> (//resource-stickiness//): |
| <code> |
| # crm configure rsc_defaults resource-stickiness=100 |
| </code> |
| |
| И далее |
| |
| Пропишем апача. |
| <code> |
| # crm configure primitive WebSite lsb:rc.httpd op monitor interval="1min" |
| </code> |
| Здесь мы создали еще один ресурс - //WebSite//;\\ |
| Указали, что будем запускать //lsb// (это те, что у нас в ///etc/rc.d//) скрипт //rc.httpd// - //lsb:rc.httpd// ;\\ |
| И время мониторинга вновь созданного ресурса - //op monitor interval=<<1min>>//. |
| |
| Пропишем //drbd// |
| <code> |
| # crm configure primitive drbd_meta ocf:linbit:drbd params drbd_resource="r0" op monitor interval="15s" |
| </code> |
| Здесь мы создали еще один ресурс - //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//. |
| <code> |
| # 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" |
| </code> |
| |
| Определяем //drbd// устройство, его точку монтирования и ФС. |
| <code> |
| # crm configure primitive MetaFS ocf:heartbeat:Filesystem params device="/dev/drbd0" directory="/claster/drbd0" fstype="ext4" op monitor interval="15s" |
| </code> |
| Здесь мы создали еще один ресурс с именем - //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// и включим туда наши ресурсы по порядку их загрузки. |
| <code> |
| # crm configure group my_services MetaFS ClusterIP WebSite |
| </code> |
| Сначала монтирование //drbd//, потом поднятие сетевого интерфейса с //ip-192.168.10.190// и потом уже запуск апача. |
| |
| Задаем совместное проживание под именем //services_drbd//, группы //my_services// с ресурсом //ms_drbd_meta:Master// (кстати, //-inf// означало бы, что ресурсы НЕ должны находиться на одном узле). |
| <code> |
| # crm configure colocation services_drbd inf: my_services ms_drbd_meta:Master |
| </code> |
| |
| Определяем порядок запуска с именем //services_after_drbd:// сначала //ms_drbd_meta//, потом наша группа сервисов //my_services//. |
| <code> |
| # crm configure order services_after_drbd inf: ms_drbd_meta:promote my_services:start |
| </code> |
| |
| Определяем, что группе //my_services// очень желательно находиться бы на узле //node1//, с весом 50 |
| <code> |
| # crm configure location prefer-node1 my_services rule 50: node1 |
| </code> |
| |
| и посмотрим, что получилось: |
| <code> |
| # 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" |
| </code> |
| |
| <code> |
| # 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 |
| </code> |
| |
| Теперь можно рестартанут сервисы //corosync// и //openais// на обеих нодах, или ребутнуть их.\\ |
| После загрузки на <nowiki>http://192.168.10.190/index.html</nowiki> появится знакомая нам надпись «//'It is my claster !//'» \\ |
| Теперь, если выдернуть лан-кабель из одной из нод или просто выключить одну из них, все равно апач будет работать. |
| |
| Для удаления, редактирования и прочих действий можно зайти в консоль //crm// и там все это сделать. |
| <code> |
| # 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 |
| </code> |
| |
| //**P.S.**//\\ |
| Цитата из [[http://habrahabr.ru/post/118925/]] |
| <code> |
| Использовать STONITH в двухнодном кластере при пропаже линков — бессмысленно. |
| Ноды просто убьют друг друга. Мы получим, так называемый deathmatch: |
| одна убивает другую — другая перезагружается и убивает первую и тд. |
| Т.к. не понятно какая из нод «правильная» и нету кворума. |
| В свою очередь, STONITH нужен для убийства ноды с зависшим ресурсом. |
| Однако тут много тонкостей с таймаутами мониторинга и остановки ресурсов. |
| Можно убить ноду, которая просто замешкалась с отмонтирование файловой системы, |
| ожидая, когда её просто освободит процесс. Это вообще отдельная большая тема. |
| </code> |
| |
| советы [[http://www.ourobengr.com/ha | как не допустить stonith deathmatch]], один из них - не ставить в автозагрузку скрипты запуска //corosync// и //openais//. |
| |
| //**P.P.S**//\\ |
| Можно использовать отдельные адаптеры для репликации, но я так не делал потому что:\\ |
| Цитата из [[http://habrahabr.ru/post/118925/]] |
| <code> |
| терминология: клиентский порт — тот порт, через который идут клиентские запросы. |
| кластерный порт — то, через что идёт репликация. |
| Делается бонд между кластерным портом (который кроссом соединяется) и туннелем в |
| клиентском порте. Если кто-то вынет кластерный провод, трафик пойдёт через туннель в клиентском порте. |
| Если кто-то вынет клиентский провод, кластер останется жить. |
| Если кто-то вынет оба провода, то мы имеем гарантию, что клиент не придёт на сплитбрейновый сервер |
| (т.к. клиентский порт отключен). Когда воткнут клиентский порт, то ПО тут же обнаружит сплитбрейн и отвалится. |
| </code> |
| |
| Но, пока, я думаю как такое организовать..... |
| |
| === Ссылался на.... ==== |
| |
| ----- |
| |
| [[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]] \\ |
| |
| |
| [[http://slackware.su/forum/index.php/topic,19.0.html | Обсуждаем на форуме]] |