Сергей Довганюк
Отказоустойчивый кластер с минимальным бюджетом
Как с минимальным бюджетом эффективно построить отказоустойчивый кластер и использовать его в качестве платформы для критически важных приложений на примере СУБД Oracle 9i.
Когда работа предприятия зависит от функционирования серверов, всегда хочется быть уверенным в их надежности. И надежность эту даже можно измерить.
Применительно к серверам эта величина называется «доступность» или «готовность», измеряется в процентах и означает, сколько времени в году сервер исправно функционирует. Идеальное ее значение – 100%.
В таблице 1 приведены типичные значения готовности и расчетное время простоя для каждой из них.
Таблица 1. Типичные значения готовности
Готовность, %
|
Время простоя в год
|
99
|
3.5 дня
|
99.9
|
9 часов
|
99.99
|
52.5 минуты
|
99.999
|
5 минут
|
Что делать, чтобы увеличить этот показатель? Оптимальное решение – это дублирование всех узлов (т.е. серверов). Это решение позволит дописать к показателю готовности еще одну «9». А два функционально идентичных сервера, работающих как один, – это уже кластер.
Варианты построения кластера выбираются в каждом конкретном случае. Я хочу привести пример построения кластера на примере СУБД Oracle 9i.
Как я и писал выше, есть несколько вариантов решений. Их можно разделить по нескольким критериям: стоимость решения, оперативность восстановления системы после сбоя (см. таблицу 2).
Таблица 2. Варианты построения кластера
|
Высокая стоимость
|
Удовлетворительная стоимость
|
Восстановление в реальном (или почти) времени
|
- Использование встроенных средств Oracle для организации репликации в реальном времени между несколькими серверами (книга из документации под названием «Oracle Data Guard Concepts and Administration»)
«+»
высокая надежность (в идеале, максимально возможная);
гарантия сохранения информации на уровне транзакции;
практически полная незаметность факта сбоя для пользователя
«–»
высокая стоимость лицензии
- Использование специализированных аппаратных средств (сервер с высоким показателем доступности)
«+»
высокая надежность;
«–»
стоимость решения еще дороже, чем стоимость предыдущего варианта
|
«+»
высокая надежность;
низкая стоимость решения
«–»
возможные ошибки при записи данных из-за программного сбоя (драйвер диска и т. д.) будут немедленно скопированы на все узлы кластера;
небольшая задержка при переключении с одного узла кластера на другой
|
Восстановление с задержкой
|
|
«+»
простота конфигурирования
«–»
в зависимости от алгоритма может приводить к значительной загрузке системы;
синхронизация данных происходит при окончании работы с файлом, что может при активной работе с диском привести к значительной задержке в синхронизации данных;
требует дополнительной настройки для автоматического переключения с одного сервера на другой (возможно, что и на основе того же Heartbeat)
- Средства Oracle для организации репликации (книга из документации под названием «Oracle 9i Advanced Replication»)
«+»
работает в рамках лицензии Oracle Standard Edition;
основано на встроенных механизмах Oracle
«–»
недостаток, общий для данной группы – отложенная синхронизация
|
Поскольку основное требование к кластеру – высокая степень доступности, то варианты из нижнего ряда второй таблицы отвергаем сразу. Рассмотрим оставшиеся варианты с учетом требуемого бюджета. Выбираем DRBD + Heartbeat.
Перевод статьи, посвященной бюджетным системам высокой готовности, в которой рассматривается выбранное нами решение, находится по адресу: http://www.opennet.ru/docs/RUS/ha_cluster.
Назначение DRBD и Heartbeat
DRBD – это блочное устройство, которое позволяет организовывать зеркалирование (RAID1-массив) через сеть. На каждом из узлов DRBD связывает виртуальное устройство /dev/drbdX (Х – номер) и локальный раздел диска, далее не доступный напрямую. Запись информации осуществляется на первичном узле (DRBD разрешает запись только на первичном узле) на устройство /dev/drbdX, которое передает эти данные для записи на связанный локальный раздел диска и отсылает по сети на другие узлы кластера. Чтение данных происходит с локального раздела.
Для управления кластером и переключения с одного узла кластера на другой (запуск/останов необходимых сервисов и т. д.) используется другой пакет, менеджер кластера – Heartbeat.
Свежую версию DRBD, на момент написания статьи, можно было взять по ссылке http://oss.linbit.com/drbd/0.7/drbd-0.7.17.tar.gz, а версию Heartbeat – http://linux-ha.org/download/heartbeat-2.0.2.tar.gz.
В нашем кластере два узла, один из них является ведущим (основным), второй ведомым (вторичным).
Конфигурация системы
За основу берем однодисковый вариант дистрибутива ALT Linux Master 2.4.
В качестве узлов кластера используются две системы. Одна (основная) – это 2 х Xeon 2.8 ГГц, 1 Гб, 2 x RAID1 (/dev/sda и /dev/sdb; 4 диска Seagate SCSI 73 Гб, 10000 rpm). Вторая проще – Athlon 1700+, 256 Мб, ATA WD 80 Гб (/dev/hda) + RAID1 (/dev/sda; 2 х ATA WD 80 Гб). На обоих узлах по две сетевые карты, одна будет использоваться для выхода в корпоративную сеть, вторая (желательно gigabit ethernet)– используется DRBD для синхронизации дисков. Скорость работы этого сетевого RAID-массива не будет выше, чем скорость вашей сети. Еще соединим оба узла через COM-порты (нуль модем) для того, чтобы Heartbeat мог с большей вероятностью определить, «умер» один из узлов кластера или нет. Может так случиться, что между узлами пропадет связь через Ethernet и тогда получится, что каждый узел будет считать себя главным, справедливо полагая, что другие узлы «мертвы» (т.н. split-brain или раздвоение личности), чего стоит всячески избегать.
На каждом из узлов должен быть выделен раздел для использования с DRBD. Выделим на обеих машинах по RAID1-массиву. Во время и после установки операционной системы (вплоть до установки DRBD) они должны оставаться неиспользуемыми!
Схема построения кластера
Порядок установки системы
Для начала нужно установить Oracle на основном узле кластера. Затем создать базу. Предполагается, что сам Oracle и база имеют некую общую родительскую директорию (например /D01). После этого, используя конфигурационные файлы от первой установки, Oracle устанавливается и на вторичном узле. Делается это для того, чтобы быть уверенным, что Oracle работает (!) на обоих узлах в идентичной (!) конфигурации.
Затем устанавливаем DRBD и Heartbeat. Конфигурируем их. Создаем раздел на основном узле кластера на запасенном RAID1-массиве. Oracle переносим во временную директорию. Настраиваем DRBD и монтируем созданный раздел к той директории, в которой был установлен Oracle (в нашем случае /D01) и переносим Oracle обратно из временной директории. Проверяем работоспособность последнего и работоспособность кластера в целом.
А теперь все то же самое подробнее.
Установка Oracle 9i
Свои действия я основывал на информации из нескольких источниках:
Я не буду описывать весь подготовительный процесс, о котором вы можете прочесть в фирменной документации. Остановлюсь только на отличительных особенностях для нашей ситуации. Учитывая, что мы с вами создаем кластер, то на разных узлах пользователь oracle и группы, с которыми он связан, должны иметь одинаковые идентификаторы (uid и gid)
altora1#> groupadd –g 789 oracle
altora1#> useradd –g oracle –u 1234 oracle
и
altora2#> groupadd –g 789 oracle
altora2#> useradd –g oracle –u 1234 oracle
Заметьте: и номера, и имена одинаковы на обоих узлах!
В качестве точки монтирования будем использовать каталог /D01. Итак.
Для упрощения установки и автоматизации процесса запуска Oracle будем использовать скрипты из пакетов oracle-preinstall и oracle9-tuning из репозитория Alt Linux:
- /etc/profile.d/oracle9.sh – установки по умолчанию для всех пользователей. Нам лишь нужно установить и изменить под свою конфигурацию;
- /etc/rc.d/init.d/oracle-lsnr – скрипт для запуска/остановки Oracle Listener;
- /etc/rc.d/init.d/oracle-db – скрипт для запуска/остановки Oracle Database.
Устанавливаем (если этого не было сделано ранее) библиотеку libstdc++-libc6.1-1.so.2, она необходима для установки JRE. Устанавливаем gcc версии 2.96 и изменяем ссылку /usr/bin/gcc так, чтобы ссылалась на gcc-2.96 (после окончания установки Oracle не забудьте изменить ссылку обратно).
Заменяем родной JRE (1.3.1.0.0) инсталлятора Oracle на JRE версии 1.3.1_17, взятый с сайта SUN (http://java.sun.com/j2se/1.3/download.html). После установки rpm-пакета переписываем JRE из директории /usr/java/jre1.3.1_17 в директорию первого диска инсталляции Oracle: /Disk1/stage/Components/oracle.swd.jre/1.3.1.0.0/1/DataFiles/Expand/jre/linux. Этим мы решаем проблему несовместимости glibc. И не забываем поменять владельца для JRE:
#>chown –R oracle:oracle /Disk1/…/jre/linux
Стоит отметить, что таким способом можно решить проблему только с инсталлятором, клиентские GUI-приложения используют JRE версии 1.1.8. Для него мне не удалось найти подходящего обновленного JRE ни у SUN, ни на www.blackdown.org. Но в принципе клиентское GUI ПО на сервере не особо и нужно. Способ же, описанный в вышеупомянутом руководстве, работает для обоих типов JRE.
При создании базы вы можете столкнуться с одной интересной проблемой. При установке мастер «зависает» перед самым моментом начала создания базы. Мой опыт подсказывает, что путь к тому месту, где должна обитать база, слишком длинный (больше некоторого числа символов). Сокращение длины пути к базе способно решить эту проблему.
Вы можете дать этому свое объяснение, но для себя я сделал вывод, что такова особенность работы мастера и/или JRE и просто надо иметь это в виду.
Остановкой Oracle управляет скрипт /$ORACLE_HOME/bin/dbshut. В этом скрипте на строках под номерами 79 и 84 расположены пары команд:
…
connect internal
shutdown
…
Нас интересует команда shutdown. Как вы наверное уже знаете, эта команда указывает Oracle завершить работу. В приведенном варианте команды Oracle ждет отключения всех пользователей и после этого завершает работу. Но иногда так происходит, что Oracle не завершает работу даже после отключения всех пользователей, как бы «зависает». Для того чтобы переключения между узлами кластера происходили быстрее, советую слегка изменить команду shutdown. Допишем к ней параметр immediate. Данный параметр указывает Oracle завершить работу не дожидаясь отключения пользователей. Более подробно о команде можно прочитать в книге «Oracle9i Database Administrator’s Guide» из фирменной документации.
Копируем скрипты oracle9.sh, oracle-lsnr и oracle-db с главного узла на резервный и повторяем процедуру установки Oracle для резервного узла без создания базы. Таким образом, на обоих узлах Oracle будет работать в одинаковом окружении.
На основном узле останавливаем Oracle, если он запущен, и копируем базу (т.н. холодная копия) на резервный узел в то же самое место, где она находится на основном узле. Файлы базы находятся в каталоге /$ORACLE_BASE/oradata/$dbname. Где $ORACLE_BASE задается в oracle9.sh, а $dbname – имя вашей базы, которое вы указали при ее создании.
Копируем файл /etc/oratab с основного узла на резервный и запускаем Oracle на резервном узле для проверки его работы.
После проверки работоспособности удаляем все содержимое точки монтирования (/D01) на резервном узле.
Установка DRBD
Для установки DRBD нужно иметь исходные тексты ядра. Исходные тексты должны быть именно от того ядра, для которого будет собираться drbd, иначе при попытке загрузки модуля (если его вообще удастся собрать) будут появляться ошибки «unresolved symbols». Мне не удалось найти точно те исходники, из которых было собрано ядро из дистрибутива, и поэтому я буду использовать самое свежее ядро на момент написания статьи – 2.4.32.
Нужно позаботиться, чтобы новое ядро было собрано в той же конфигурации, что и ядро, использовавшееся до него. Спасибо Михаилу Шигорину за подсказку, где найти оригинальный конфигурационный файл. В моем случае он находится в /boot/config-*. Копируем его вместо конфига нового ядра:
#> cp /boot/config-2.4.26-std-smp-alt6 /usr/src/linux/.config
Компилируем ядро, устанавливаем. Проверяем работоспособность системы на новом ядре.
Компилируем DRBD:
#> cd /usr/src/drbd-0.7.17
#> make clean all
Устанавливаем:
#> make install
Модуль находится в /lib/modules/2.4.32/kernel/drivers/block/. Подробное описание процесса компиляции и установки находится в файле INSTALL из пакета исходников DRBD.
Перед настройкой DRBD нужно разбить запасенные диски на обоих узлах на разделы (раздел может быть и единственный). При этом те разделы, которые будут использоваться с DRBD, желательно сделать одного размера. Для этого используем fdisk или аналог. Например, на обоих узлах разобьем диски на два раздела: основной – 35 Гб, для использования с DRBD и логический – остальное пространство диска.
Настраиваем DRBD. Настройка производится через конфигурационный файл /etc/drbd.conf. Файл должен быть идентичен на обоих узлах кластера.
Добавим модуль drbd в /etc/modules.
При установке init скрипт для DRBD копируется в /etc/rc.d/init.d/drbd. Устанавливаем его:
#> chkconfig --add drbd
Этот скрипт инициализирует подсистему DRBD, используя параметры из файла /etc/drbd.conf. Результат работы скрипта аналогичен команде:
#> drbdadm up all
Теперь перезапускаем наш кластер и в /var/log/messages должны увидеть что-то вроде этого.
О том, что модуль загружен:
drbd: initialised. Version: 0.7.17 (api:77/proto:74)
drbd: SVN Revision: 2093 build by root@altora1, 2006-03-14 18:42:04
drbd: registered as block device major 147
|
О том, что запущен сервис DRBD:
drbd0: Creating state block
drbd0: resync bitmap: bits=8513804 words=266058
drbd0: size = 32 GB (34055216 KB)
drbd0: 34055216 KB now marked out-of-sync by on disk bit-map.
drbd0: Assuming that all blocks are out of sync (aka FullSync)
drbd0: 34055216 KB now marked out-of-sync by on disk bit-map.
drbd0: drbdsetup [2119]: cstate Unconfigured --> StandAlone
drbd0: drbdsetup [2122]: cstate StandAlone --> Unconnected
drbd0: drbd0_receiver [2123]: cstate Unconnected --> WFConnection
drbd0: drbd0_receiver [2123]: cstate WFConnection --> WFReportParams
drbd0: Handshake successful: DRBD Network Protocol version 74
drbd0: Connection established.
drbd0: I am(S): 0:00000001:00000001:00000001:00000001:00
drbd0: Peer(S): 0:00000001:00000001:00000001:00000001:00
drbd0: drbd0_receiver [2123]: cstate WFReportParams --> Connected
drbd0: I am inconsistent, but there is no sync? BOTH nodes inconsistent!
drbd0: Secondary/Unknown --> Secondary/Secondary
|
Дело в том, что изначально DRBD ничего не знает о том, какой из узлов ведущий, а какой ведомый. И теперь мы должны определиться с этим и «сказать» DRBD. Делается это командой:
#> drbdadm -- --do-what-I-say primary all
запущенной на ведущем узле. После чего начинается процесс синхронизации дисков на обоих узлах кластера и содержимое раздела диска основного узла копируется на раздел диска ведомого узла. Будьте внимательны и аккуратны, советую проверить перед выполнением вышеприведенной команды еще раз конфигурационный файл DRBD!
За процессом синхронизации можно наблюдать набрав:
#> cat /proc/drbd
Вывод будет примерно следующим:
Основной узел:
version: 0.7.17 (api:77/proto:74)
SVN Revision: 2093 build by root@altora1, 2006-03-14 18:42:04
0: cs:Connected st:Primary/Secondary ld:Consistent
ns:636228 nr:2984 dw:639212 dr:337464 al:22 bm:44 lo:0 pe:0 ua:0 ap:0
[====>...............] sync’ed: 20% (27200/34000)M
...
...
1: cs:Unconfigured
|
Ведомый узел:
version: 0.7.17 (api:77/proto:74)
SVN Revision: 2093 build by root@altora1, 2006-03-14 18:42:04
0: cs:Connected st: Secondary/Primary ld:Inconsistent
ns:636228 nr:2984 dw:639212 dr:337464 al:22 bm:44 lo:0 pe:0 ua:0 ap:0
[====>...............] sync’ed: 20% (27200/34000)M
...
...
1: cs:Unconfigured
|
Создаем файловую систему на устройстве DRBD, желательно чтобы она была журналируемой, это позволит ускорить запуск сервисов на резервном узле (иначе перед запуском будет проведена проверка диска):
#> mkreiserfs /dev/drbd0
Останавливаем Oracle, если он работает. Переносим Oracle (бинарные файлы и базу) во временную директорию, например, так:
#> mv /D01/Ora /root/Oracle
Монтируем устройство DRBD в /D01:
#> mount -t reiserfs /dev/drbd0 /D01
Копируем Oracle обратно в /D01. Пробуем запустить Oracle.
Установка Heartbeat
Компиляция и установка Heartbeat довольно проста и проходит в 3 этапа:
#> cd /usr/src/heartbeat-2.0.4
#> ./ConfigureMe configure
При первой попытке конфигуратор наверняка выдаст сообщения о том, что для установки Heartbeat не хватает нескольких пакетов. Перечень необходимых пакетов конфигуратор выдает в конце работы единым списком. Я советую установить все требуемые пакеты и те, что обязательны (ERROR), и те, что желательны (WARNING).
Компилируем и устанавливаем:
#> ./ConfigureMe make
#> ./ConfigureMe install
Для настройки Heartbeat использует 3 файла, находящиеся в директории /etc/ha.d:
- /etc/ha.d/ha.cf – общая настройка;
- /etc/ha.d/haresources – этот файл описывает ресурсы, которые следует перемещать от узла к узлу;
- /etc/ha.d/authkeys – файл аутентификации.
Выполняем команду:
#> chkconfig --add heartbeat
для установки init-скрипта пакета Heartbeat.
Перезапускаем кластер. В логах должно появиться чтото вроде этого:
heartbeat: [1630]: info: Configuration validated. Starting heartbeat 2.0.4
heartbeat: [1631]: info: heartbeat: version 2.0.4
heartbeat: [1631]: info: Heartbeat generation: 7
...
ResourceManager[2195]: info: Running /etc/init.d/oracle-db start
...
oracle-db: Starting Oracle database: succeeded
...
ResourceManager[2195]: info: Running /etc/init.d/oracle-lsnr start
...
oracle-lsnr: Starting Oracle Net8 listener: succeeded
...
ResourceManager[2195]: info: Running /etc/init.d/httpd start
...
Mar 17 14:35:24 altora1 httpd: httpd startup succeeded
...
heartbeat: [2185]: info: local HA resource acquisition completed (standby).
heartbeat: [1631]: info: Standby resource acquisition done [foreign].
heartbeat: [1631]: info: Initial resource acquisition complete (auto_failback)
heartbeat: [1631]: info: remote resource transition completed.
|
Поздравляю, ваш кластер работает!
Эксплуатация
Порядок включения узлов не имеет значения, т.к. узел, запустившийся первым, будет ждать запуска другого узла (в файле /etc/drbd.conf параметр wfc-timeout). Что делать, если один из узлов не стартует, мы обсудим ниже.
Порядок выключения узлов кластера зависит от приложений, запущенных на этом кластере. Для нашего случая мы должны добиться, чтобы информация, хранящаяся в базе Oracle, по завершении работы кластера была в идентичном состоянии на обоих узлах и была «цельной» (consistent). Мне представляется, что единственный способ этого добиться – выключать главный узел первым, тогда Oracle успешно завершит работу, и даже если Heartbeat на резервном узле успеет запустить Oracle, то это уже не должно повлечь за собой какое-либо изменение данных в базе, т.к. резервный узел также будет завершать свою работу.
Так что же делать, если один из узлов не запускается? Перезагружаем рабочий узел и загружаем систему в однопользовательском режиме. В этом режиме ни DRBD, ни Heartbeat не запускаются. Редактируем конфигурационный файл /etc/drbd.conf и устанавливаем параметр wfc-timeout в значение, отличное от 0, например, 1 (равно 1 секунде). Снова перезагружаем узел уже в обычном режиме.
Как повлияет синхронизация данных по сети на скорость работы с Oracle и как значительно может уменьшиться производительность по сравнению с одиночным сервером? Здесь многое зависит как от скорости используемого сетевого соединения, так и от режима работы Oracle. Значительное падение цен сделало доступным гигабитные решения для бюджетного сектора. Учитывая, что DRBD буферизирует данные и то, что скорость работы современных жестких дисков в реальных условиях пока еще значительно меньше, чем пропускная способность гигабитной сети, то в данном случае узким местом скорее станет скорость работы с дисками. В любом случае вы не должны заметить сколько-нибудь значительного проигрыша. Если вы используете сеть 100 Mbit, то здесь тоже не все безнадежно. Если большая часть запросов к базе (как правило) составляет запросы на выборку, то работа в основном будет идти с диском на главном узле, и здесь скорость соединения в 100 Mbit практически никак не скажется на производительности кластера. Если же основная работа с Oracle состоит в добавлении новых записей, то все зависит от объема новых данных, поступающих на запись. На основе своего опыта могу сказать, что Oracle на удаление и потом вставку 20000 записей тратил около 15 секунды на одиночном сервере. В объемах это где-то 5-10 Мб, учитывая индексы и служебную информацию. То есть у нас остается даже запас. Такова специфика работы сервера баз данных, хотя если бы мы с вами организовывали файл-сервер, то наверняка заметили бы падение производительности.
Что повлечет для клиентского ПО переход с одного узла кластера на другой? Соединения клиентского ПО с Oracle будут потеряны. Пользователям необходимо будет по истечении пары минут заново подключиться к Oracle, желательно, чтобы используемое вами клиентское ПО имело такую возможность. Время перехода с одного узла кластера на другой составляет менее минуты.
Если вы используете единый источник бесперебойного питания для обоих узлов кластера, то для увеличения времени работы от батареи в случае отключения электроснабжения советую в качестве второго узла кластера использовать более «легкую» машину (меньше CPU, жестких дисков и прочего). И при переходе кластера на работу от батареи оставлять рабочим только резервный узел. Делается это путем настройки демона, следящего за состоянием батареи, так, чтобы система на главном узле останавливалась, например, после 5 минут (чтобы не реагировать на кратковременные перебои) работы от батареи, а на резервном узле работала бы уже до исчерпания заряда батареи. Выбор соответствующего демона зависит от марки используемой вами батареи. Для широко распространенных батарей фирмы APC можно использовать демон apcupsd (http://www.sourceforge.net/projects/apcupsd). Он позволяет организовать взаимодействие по сети.
И не забывайте о резервном копировании, ведь кластер – это не панацея, а лишь одно из средств.