Кластер Pacemaker+Corosync+HAProxy+Nginx

Для построения кластера высокой доступности, т.е. high availability, будем использовать Pacemaker. Pacemaker - менеджер ресурсов кластера (Cluster Resource Manager), задачей которого является достижение максимальной доступности управляемых им ресурсов и защита их от сбоев как на уровне самих ресурсов, так и на уровне целых узлов кластера. Архитектура pacemaker состоит из трех уровней:

  1. Кластеронезависимый уровень - на этом уровне располагаются сами ресурсы и их скрипты, которыми они управляются и локальный демон, который скрывает от других уровней различия в стандартах, использованных в скриптах (на рисунке зеленый).

  2. Менеджер ресурсов (Pacemaker), который предстовляет из себя мозг. Он реагирует на события, происходящие в кластере: отказ или присоединение узлов, ресурсов, переход узлов в сервисный режим и другие административные действия. Pacemaker исходя из сложившейся ситуации делает расчет наиболее оптимального состояния кластера и дает команды на выполнения действий для достижения этого состояния (остановка/перенос ресурсов или узлов). На рисунке обозначен синим.

  3. Информационный уровень - на этом уровне осуществляется сетевое взаимодействие узлов, т.е. передача сервисных команд (запуск/остановка ресурсов, узлов и т.д.), обмен информацией о полноте состава кластера (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.

  

unix-way