Обеспечение отказоустойчивости – залог непрерывной работы и вообще полного удовлетворения как пользователей, так и админов. В нашем сегодняшнем материале речь пойдет о том, как можно выполнить кластеризацию BitrixVM с помощью простых и доступных средств, чтобы всем было радостно и ничто не мешало спокойно работать.

Итак, имеем два сервера с BitrixVM и развернутыми на них системами Bitrix24. Первое, что следует сделать – для сохранения однотипности данных на обоих узлах выполнить синхронизацию как между базами данных, так и между файлами bitrix.

Bitrix1 — 172.16.10.1
Bitrix2 — 172.16.10.2

Обязательно пропишем в файлах hosts строки на обеих машинах:

172.16.10.1 bitrix1
172.16.10.2 bitrix2

Для базы данных будем использовать репликацию данных типа master-master. Для этого нам необходимо поправить настройки в файлах /etc/my.cnf

Bitrix рекомендует для переопределения своих собственных настроек создать файл /etc/mysql/conf.d/z_bx_custom.cnf, в котором и следует производить правки:

[root@bitrix1 /]# cat /etc/my.cnf
#
# Basic mysql configuration. Use bvat for advanced settings.
# Parameters set by bvat are stored in /etc/mysql/conf.d/bvat.cnf
# If you want to change any parameter, you'll have to redefine it in #/etc/mysql/conf.d/z_bx_custom.cnf
#

Создадим файл в соответствии с рекомендацией:

touch /etc/mysql/conf.d/z_bx_custom.cnf

[root@bitrix1 /]# nano /etc/mysql/conf.d/z_bx_custom.cnf
[mysqld]

Уникальный идентификатор сервера среди участников репликации:

server-id = 1

Выполняется запись в логи измененных бинарных данных. Без указания этой опции может возникнуть ошибка как в логах, так и при входе в сам bitrix-портал:

Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is #READ #COMMITTED or READ UNCOMMITTED.
binlog_format=row

Логи ошибок:

log=/var/log/mysqld.log
log_error = /var/log/mysqld.log 

Путь к логам транзакций сервера (binlog, который ведет мастер):

log-bin = /var/lib/mysql/server-mysql-bin
log-bin-index = /var/lib/mysql/server-mysql-bin.index 

Путь к relay-логам slave (binlog, скачанный с мастера):

relay-log = /var/lib/mysql/slave-mysql-relay-bin
relay-log-index = /var/lib/mysql/slave-mysql-relay-bin.index 

БД, которые нужно или не нужно реплицировать (выполняем только репликацию для стандартной базы bitrix — sitemanager0):

replicate-do-db = sitemanager0
replicate-ignore-db=test
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
replicate-ignore-db=performance_schema 

Не вести журнал binlog для базы данных:

binlog-ignore-db = information_schema
binlog-ignore-db = mysql
binlog-ignore-db = performance_schema 

Чтобы избежать конфликтов автоинкремента, сообщаем серверу, чтобы id генерировались, начиная с 3-го, прибавляя по 10, т.е. 13, 23, 33, 43 и далее:

auto_increment_increment = 10
auto_increment_offset = 3 

Сохранять логи с мастера в свой binlog, чтобы передать слейву:

log-slave-updates

После этого перезапускаем mysql:

[root@bitrix1 /]# /etc/init.d/mysqld restart

Далее – необходимо перейти на второй BitrixVM, т.е. bitrix2, и выполнить аналогичные настройки для mysql, предварительно также создав файл z_bx_custom.cnf в /etc/mysql/conf.d/, при этом поменяв server-id и auto_increment_offset:

[root@bitrix2 ~]# cat /etc/mysql/conf.d/z_bx_custom.cnf
[mysqld]
server-id = 2
binlog_format=row
 
log=/var/log/mysqld.log
log_error = /var/log/mysqld.log
 
log-bin = /var/lib/mysql/server-mysql-bin
log-bin-index = /var/lib/mysql/server-mysql-bin.index
 
relay-log = /var/lib/mysql/slave-mysql-relay-bin
relay-log-index = /var/lib/mysql/slave-mysql-relay-bin.index
 
replicate-do-db = sitemanager0
replicate-ignore-db=test
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
replicate-ignore-db=performance_schema

binlog-ignore-db = information_schema
binlog-ignore-db = mysql
binlog-ignore-db = performance_schema
auto_increment_increment = 10
auto_increment_offset = 4
 
log-slave-updates

Выполним рестарт mysql на второй машине:

[root@bitrix2 ~]# /etc/init.d/mysqld restart

Для репликации создадим пользователя replicator на обеих машинах:

root@bitrix1 /]# mysql -u root -p
Enter password:
mysql> create user 'replicator'@'%' identified by 'aGiV4uac';
mysql> grant replication slave on *.* to 'replicator'@'%';

root@bitrix2 /]# mysql -u root -p
Enter password:
mysql> create user 'replicator'@'%' identified by 'aGiV4uac';
mysql> grant replication slave on *.* to 'replicator'@'%';

Снова переходим на первую машину и запустим репликацию. Для этого понадобится знать имя master_log и master_log_position второй машины bitrix2:

[root@bitrix2 /]# mysql -u root -p -e 'show master status;'

+-----------------------+--------+------------+-------------------------------------------+
| File                  |Position|Binlog_Do_DB| Binlog_Ignore_DB                          |
+-----------------------+--------+------------+-------------------------------------------+
|server-mysql-bin.000029|  819   |            |information_schema,mysql,performance_schema|
+-----------------------+--------+------------+-------------------------------------------+

Из полученного списка следует, что MASTER_LOG_FILE = server-mysql-bin.000029, а MASTER_LOG_POS = 819

Используем эти данные для настройки репликации на первой машине:

[root@bitrix1 /]# root -p -e "CHANGE MASTER TO MASTER_HOST = '172.16.10.2', MASTER_USER = 'replicator', MASTER_PASSWORD = 'aGiV4uac', MASTER_LOG_FILE = 'server-mysql-bin.000029', MASTER_LOG_POS = 819;"

Запускаем slave:

[root@bitrix1 /]# mysql -u root -p -e 'start slave;'

Проверяем статус:

[root@bitrix1 /]# mysql -u root -p -e 'show slave status \G;'

*************************** 1. row ***************************
  Slave_IO_State: Waiting for master to send event
  Master_Host: 172.16.10.2
  Master_User: replicator
  Master_Port: 3306
  Connect_Retry: 60
  Master_Log_File: server-mysql-bin.000029
  Read_Master_Log_Pos: 819
  Relay_Log_File: slave-mysql-relay-bin.000002
  Relay_Log_Pos: 72951
  Relay_Master_Log_File: server-mysql-bin.000029
  Slave_IO_Running: Yes
  Slave_SQL_Running: Yes
  Replicate_Do_DB: sitemanager0
  Replicate_Ignore_DB: test,information_schema,mysql,performance_schema
  Replicate_Do_Table:
  Replicate_Ignore_Table:
  Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
  Last_Errno: 0
  Last_Error:
  Skip_Counter: 0
  Exec_Master_Log_Pos: 819
  Relay_Log_Space: 73113
  Until_Condition: None
  Until_Log_File:
  Until_Log_Pos: 0
  Master_SSL_Allowed: No
  Master_SSL_CA_File:
  Master_SSL_CA_Path:
  Master_SSL_Cert:
  Master_SSL_Cipher:
  Master_SSL_Key:
  Seconds_Behind_Master: 0
  Master_SSL_Verify_Server_Cert: No
  Last_IO_Errno: 0
  Last_IO_Error:
  Last_SQL_Errno: 0
  Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
  Master_Server_Id: 2

Параметр Seconds_Behind_Master (время отставания реплики от мастера) должно равняться нулю:
Slave_IO_State должно сообщать: «Waiting for master to send even»
Slave_IO_Running = Yes
Slave_SQL_Running = Yes

Если значения в строке Slave_IO_State отсутствует, а Seconds_Behind_Master равно NULL, значит, репликация не началась.

Узнаем master_log и master_log_position первой машины bitrix1:

[root@bitrix1 /]# mysql -u root -p -e 'show master status;'

+-----------------------+--------+------------+-------------------------------------------+
| File                  |Position|Binlog_Do_DB| Binlog_Ignore_DB                          |
+-----------------------+--------+------------+-------------------------------------------+
|server-mysql-bin.000026| 2930   |            |information_schema,mysql,performance_schema|
+-----------------------+--------+------------+-------------------------------------------+

На второй машине bitrix2 настраиваем репликацию:

[root@bitrix2 ~]# mysql -u root -p -e "CHANGE MASTER TO MASTER_HOST = '172.16.10.1', MASTER_USER = 'replicator', MASTER_PASSWORD = 'aGiV4uac', MASTER_LOG_FILE = 'server-mysql-bin.000026', MASTER_LOG_POS = 2930;"

[root@bitrix2 ~]# mysql -u root -p -e 'stop slave;'
[root@bitrix2 ~]# mysql -u root -p -e 'show slave status \G;'

Должны отобразиться параметры: Seconds_Behind_Master, Slave_IO_State, Slave_IO_Running, Slave_SQL_Running с параметрами, аналогичными, как и в случае с настройкой репликации на машине bitrix1.

Далее – необходимо перейти к синхронизации самих данных между Bitrix24. Синхронизацию файлов будем выполнять через csync2.

Установка csync должна быть выполнена на обеих машинах:

[root@bitrix1 /]# yum install csync2
[root@bitrix2 /]# yum install csync2

Включаем на обеих машинах:

chkconfig xinetd on
chkconfig csync2 on

Генерируем сертификаты, находясь на первой машине bitrix1:

[root@bitrix1 /]# openssl genrsa -out /etc/csync2/csync2_ssl_key.pem 1024 
[root@bitrix1 /]# openssl req -new -key /etc/csync2/csync2_ssl_key.pem -out /etc/csync2/csync2_ssl_cert.csr 
[root@bitrix1 /]# openssl x509 -req -days 600 -in /etc/csync2/csync2_ssl_cert.csr -signkey /etc/csync2/csync2_ssl_key.pem -out /etc/csync2/csync2_ssl_cert.pem

Генерируем ключ csync2:

csync2 -k /etc/csync2/csync2.cluster.key

После довольно продолжительного по времени процесса генерирования ключ csync2.cluster.key появится в папке /etc/csync2/

Настройка конфига для csync выглядит так:

[root@bitrix1 /]# cat /etc/csync2/csync2.cfg
group cluster
{
host bitrix1 bitrix2;

key /etc/csync2/csync2.cluster.key;

include /home/bitrix/www;

Исключаем файлы настроек соединения с БД, поскольку используем разные пароли на обеих машинах. Также исключаем директории с кэшем:

exclude /home/bitrix/www/bitrix/php_interface/dbconn.php;
exclude /home/bitrix/www/bitrix/.settings.php;
exclude /home/bitrix/www/bitrix/cache;
exclude /home/bitrix/www/bitrix/managed_cache;

Задаём параметр отбора файлов: остается тот, что самый новый:

auto younger;
}

Копируем сгенерированные ключи вместе с конфигурационным файлом csync2.cfg с bitrix1 на bitrix2, например, по scp:

scp /etc/csync2/csync2* root@172.16.10.2:/test

Построим локальную базу всех файлов проекта, с которой будет работать csync2.

[root@bitrix1 csync2]# csync2 -cr /

После – запускаем:

[root@bitrix1 /]# /usr/sbin/csync2 –xv

В случае ошибок можно использовать /usr/sbin/csync2 –Tv

Если команда завершилась без ошибок, то можно добавлять запись в /etc/crontab на обеих машинах для запуска csync каждую минуту:

*/1 * * * * root /usr/sbin/csync2 -x >/dev/null 2>&1

Остается сделать проверку: создав, к примеру, сообщение в самом портале, чате bitrix24, удалить, создать файл и убедиться, что вносимые изменения переносятся между узлами.

В качестве одного из вариантов единой точки входа можно использовать HAProxy, расположенный на дополнительном сервере. Обзор установки и настройки HAProxy рассматривать в этой статье не будем, т.к. руководств по данному вопросу достаточно, но для примера приведем конфиг файла /etc/haproxy/haproxy.cfg:

[root@haproxy haproxy]# cat haproxy.cfg
global
 log 127.0.0.1 local2 notice
 
 chroot /var/lib/haproxy
 pidfile /var/run/haproxy.pid
 maxconn 4000
 user haproxy
 group haproxy
 daemon
 nbproc 1 # Number of processing cores.
 ulimit-n 65536
 # turn on stats unix socket
 stats socket /var/lib/haproxy/stats

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 5000
 timeout queue        5000
 timeout connect      5000
 timeout client       5000
 timeout server       5000
 timeout http-keep-alive 30
 timeout check           20 #
 maxconn                 3000

frontend bitrix.local
 mode http
 bind :80
 default_backend bitrix
 
backend bitrix
 mode http
 balance roundrobin
 option httpchk
 option httpclose
 server bitrix1 172.16.10.1:80 check
 server bitrix2 172.16.10.2:80 check

Кластеризируйте свои сервера на здоровье и да пребудет с вами Сила!