Для построения кластера высокой доступности, т.е. high availability, будем использовать Pacemaker. Pacemaker - менеджер ресурсов кластера (Cluster Resource Manager), задачей которого является достижение максимальной доступности управляемых им ресурсов и защита их от сбоев как на уровне самих ресурсов, так и на уровне целых узлов кластера. Архитектура pacemaker состоит из трех уровней:
-
Кластеронезависимый уровень - на этом уровне располагаются сами ресурсы и их скрипты, которыми они управляются и локальный демон, который скрывает от других уровней различия в стандартах, использованных в скриптах (на рисунке зеленый).
-
Менеджер ресурсов (Pacemaker), который предстовляет из себя мозг. Он реагирует на события, происходящие в кластере: отказ или присоединение узлов, ресурсов, переход узлов в сервисный режим и другие административные действия. Pacemaker исходя из сложившейся ситуации делает расчет наиболее оптимального состояния кластера и дает команды на выполнения действий для достижения этого состояния (остановка/перенос ресурсов или узлов). На рисунке обозначен синим.
-
Информационный уровень - на этом уровне осуществляется сетевое взаимодействие узлов, т.е. передача сервисных команд (запуск/остановка ресурсов, узлов и т.д.), обмен информацией о полноте состава кластера (quorum) и т.д. На рисунке обозначен красным. Как правило на этом уровне работает Corosync.
В статье рассмотрю как создать простой кластер балансировщик нагрузки HAProxy с плавающим ip адресом. HAProxy будет распределять нагрузку по двум нодам. В случае если работающий балансировзик падает, второй балансировщик автоматически запускается и начинает работать за место первого. Статья не панацея, но как отправная точка на пути к созданию кластера вполне может пригодиться.
Итого такая схема:
Где LB1 и LB2 ноды балансировщики на Centos 7, на которых и будет работать HAProxy посредством Pacemaker+Corosync. App1 и App2 есть ноды приложения, например nginx, которые предполагается настроена на адресах 192.168.100.204 и 192.168.100.205.
Приступаем к установке и настройке нашего кластера.
Для начала надо обеспечить ping по короткому имени всех узлов кластера (lb1 и lb2).
[root@lbX ~]# yum install corosync pcs pacemaker |
Для управления кластером будем пользоваться утилитой pcs. При установке pacemaker автоматически будет создан пользователь hacluster. Для использования pcs, а также для доступа в веб-интерфейс нужно задать пароль пользователю hacluster:
[root@lbX ~]# passwd hacluster Changing password for user hacluster. New password: Retype new password: passwd: all authentication tokens updated successfully. |
Запускаем сервис:
[root@lbX ~]# systemctl start pcsd |
Настраиваем аутентификацию (уже на одном узле):
[root@lb1 ~]# pcs cluster auth lb1 lb2 Username: hacluster Password: lb1: Authorized lb2: Authorized |
После этого кластером можно управлять с одного узла.
Создаем кластер
[root@lb1 ~]# pcs cluster setup --name mycluster lb1 lb2 Shutting down pacemaker/corosync services... Redirecting to /bin/systemctl stop pacemaker.service Redirecting to /bin/systemctl stop corosync.service Killing any remaining services... Removing all cluster configuration files... lb1: Succeeded lb2: Succeeded Synchronizing pcsd certificates on nodes lb1, lb2... lb1: Success lb2: Success Restaring pcsd on the nodes in order to reload the certificates... lb1: Success lb2: Success
|
Запускаем кластер
[root@lb1 ~]# pcs cluster start --all lb2: Starting Cluster... lb1: Starting Cluster... |
Настройка автоматического включения кластера при загрузке:
[root@lb1 ~]# pcs cluster enable --all lb1: Cluster Enabled lb2: Cluster Enabled |
Смотрим результат:
[root@lb1 ~]# pcs status cluster Cluster Status: Last updated: Mon Dec 5 07:50:21 2016 Last change: Mon Dec 5 07:50:05 2016 by hacluster via crmd on lb1 Stack: unknown Current DC: NONE 2 nodes and 0 resources configured Node lb1: UNCLEAN (offline) Node lb2: UNCLEAN (offline)
PCSD Status: lb1: Online lb2: Online |
Проверка синхронизации узлов кластера:
[root@lb1 ~]# corosync-cmapctl | grep members runtime.totem.pg.mrp.srp.members.1.config_version (u64) = 0 runtime.totem.pg.mrp.srp.members.1.ip (str) = r(0) ip(192.168.100.201) runtime.totem.pg.mrp.srp.members.1.join_count (u32) = 1 runtime.totem.pg.mrp.srp.members.1.status (str) = joined runtime.totem.pg.mrp.srp.members.2.config_version (u64) = 0 runtime.totem.pg.mrp.srp.members.2.ip (str) = r(0) ip(192.168.100.202) runtime.totem.pg.mrp.srp.members.2.join_count (u32) = 1 runtime.totem.pg.mrp.srp.members.2.status (str) = joined
[root@lb1 ~]# pcs status corosync Membership information ---------------------- Nodeid Votes Name 1 1 lb1 (local) 2 1 lb2 |
Настройка основных параметров кластера
Механизм STONITH ( Shoot-The-Other-Node-In-The-Head) - лекарстваот Split-Brain
Позволяет выключать/включать/перезагружать узлы кластера. Обычно этот механизм реализуется с помощью специальных сетевых устройств с удаленным управлением или через специальные платы управления сервером. В pacemaker устройства STONITH реализованы в виде кластерных ресурсов.
Для нашего кластера механизм STONITH не нужен, выключаем:
[root@lb1 ~]# pcs property set stonith-enabled=false |
Кворум
Кворум определяет минимальное число работающих узлов в кластере, при котором кластер считается работоспособным. По умолчанию, кворум считается неработоспособным, если число работающих узлов меньше половины от общего числа узлов. Так как узла у нас всего два, то кворума у нас не будет, поэтому отключаем эту политику:
[root@lb1 ~]# pcs property set no-quorum-policy=ignore |
Посмотреть какие у нас в итоге получились настройки можно командой:
[root@lb1 ~]# pcs property Cluster Properties: cluster-infrastructure: corosync cluster-name: mycluster dc-version: 1.1.13-10.el7_2.4-44eb2dd have-watchdog: false last-lrm-refresh: 1480973783 no-quorum-policy: ignore stonith-enabled: false |
Настройки кластера можно проверить с помощью утилиты crm_verify. Опция -L осуществляет диагностику всех работающих узлов кластера.
Чтобы сервисы кластера запускались автоматически при перезагрузке сервера, нужно выполнить на каждом узле кластера:
[root@lbX ~]# systemctl enable pcsd [root@lbX ~]# systemctl enable corosync [root@lbX ~]# systemctl enable pacemaker |
Теперь у нас доступен веб-интерфейс управления кластером по по адресу https://192.168.100.201:2224
Создание виртуального плавающего ip адреса (floatingip) VIP
[root@lb1 ~]# pcs resource create virtual_ip ocf:heartbeat:IPaddr2 ip=192.168.100.203 cidr_netmask=32 op monitor interval=30s [root@lb1 ~]# pcs status resources virtualip (ocf::heartbeat:IPaddr2): Started lb1 |
Если узлы кластера не одинаковы по производительности или доступности, то можно увеличить приоритет одного из узлов, чтобы он был активным всегда когда работает:
[root@lb1 ~]# pcs constraint location virtualip prefers lb1=100 |
Переходим к конфигурированию балансера
Устанавливаем HAProxy:
[root@lbX ~]#yum install -y haproxy |
Открываем конфигурационый файл, переходим к секции default и добавляем строки:
[root@lb1 ~]# vi /etc/haproxy/haproxy.cfg option forwardfor option http-server-close |
Forwardfor опция устанавливает HAProxy добавлять X-Forwarded-For заголовки для каждого запроса-что полезно, если вы хотите, чтобы ваши серверы приложений знали с какого IP-адрес первоначально был отправлен запрос. А опция http-server-close уменьшает задержку между HAProxy и пользователями путем закрытия соединения, но сохраняя keep-alives.
Затем, в конце файла, мы должны определить нашу фронтенд конфигурацию. Мы будем биндить HAProxy на VIP-адрес. Это позволит ему прослушивать трафика, исходящего из плавающего IP-адреса.
Вот какой конфиг в итоге может получиться:
#--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global # to have these messages end up in /var/log/haproxy.log you will # need to: # # 1) configure syslog to accept network log events. This is done # by adding the '-r' option to the SYSLOGD_OPTIONS in # /etc/sysconfig/syslog # # 2) configure local2 events to go to the /var/log/haproxy.log # file. A line like the following can be added to # /etc/sysconfig/syslog # # local2.* /var/log/haproxy.log # log 127.0.0.1 local2
chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon
# turn on stats unix socket stats socket /var/lib/haproxy/stats
#--------------------------------------------------------------------- # common defaults that all the 'listen' and 'backend' sections will # use if not designated in their block #--------------------------------------------------------------------- defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000
#my http server frontend http bind 192.168.100.203:80 default_backend app_pool backend app_pool server app1 192.168.100.204:80 check server app2 192.168.100.205:80 check |
Затем или загружаем ocf ресурс на оба узла lb1 и lb2:
[root@lbX ~]# cd /usr/lib/ocf/resource.d/heartbeat [root@lbX ~]# curl -O https://raw.githubusercontent.com/thisismitch/cluster-agents/master/haproxy [root@lbX ~]#chmod +x haproxy |
Или же, т.к. у нас systemd, исользуем его systemd.
Создаем ресурс Haproxy из веб интерфейса. Идем в RESOURCES->Add, далее интуитивно всё понятно.
Заставим включать HAProxy только на узле с VIP:
[root@lb1 ~]# pcs constraint colocation add haproxy virtualip INFINITY |
Порядок загрузки – сначала VIP, потом стартует HAProxy:
[root@lb1 ~]# pcs constraint order virtualip then haproxy |
Готово. Можно пробовать ребутать балансеры и всё будет работать будто ничего и не происходило. В текущей настройке сервис HAProxy запущен только на одном узле и в случае падения этого узла, переезжает вместе с VIP. Но можно забиндить HAProxy на 0.0.0.0:80 и использовать клон ресурса, что даст запущенный HAProxy сразу на обоих узлах и моментальное подхватывание VIP, без тормозов в запуске демона HAProxy.