[Системное администрирование, MySQL, IT-инфраструктура] Безотказный Zabbix: миграция с асинхронной на групповую репликацию

Автор Сообщение
news_bot ®

Стаж: 6 лет 3 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
17-Май-2021 00:30

ВведениеZabbix поддерживает несколько баз данных, но под рассмотрение попали только MySQL и PostgreSQL, как наиболее подходящие под мою установку. PostgreSQL с его repomgr и pgbouncer или каким-нибудь stolon с одной стороны и MySQL Group Replication с другой. Из-за использования MySQL в текущей конфигурации и тяге к стандартной комплектации, выбор пал на второй вариант.Так что же такое MySQL Group Replication. Как видно из названия, это группа серверов, хранящая одинаковый набор данных. Максимальное количество узлов в группе ограничивается 9-ю. Может работать в режиме single-primary или multi-primary. Но самое интересное всё работает автоматически, будь то выборы нового ведущего сервера, определение поломанного узла, Split-brain или восстановление БД. Поставляется данный функционал в качестве плагинов group_replication и mysql_clone, связь происходит по Group Communication System протоколу в основе которого лежит алгоритм Паксос. Поддерживается данный тип репликации с версий 5.7.17 и 8.0.1. Моя текущая установка работает на Zabbix 5.0 LTS и MySQL 5.7, миграцию будем проводить с повышением версии MySQL на 8.0, так интереснее ).Мониторинг репликацииДа да. Это как TDD, только в администрировании, сначала нужно подготовить мониторинг, чтобы новый кластер сразу попал на радары нашей системы мониторинга и не одна проблема не ускользнула от её зоркого взгляда. Так как у вас еще нет групповой репликации (ГР), то вывод команд указанных ниже будет пустым, поэтому я привожу пример выводов с работающего кластера.Основным источником информации о статусе узлов служит команда:SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+--------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME              | MEMBER_ID                             | MEMBER_HOST  | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+--------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 500049c2-99b7-11e9-8d36-e4434b5f9d0c | example1.com |      3306   | ONLINE       | SECONDARY   | 8.0.13         |
| group_replication_applier | 50024be2-9889-11eb-83da-e4434ba03de0 | example2.com |      3306   | ONLINE       | PRIMARY     | 8.0.13         |
| group_replication_applier | 500b2035-986e-11eb-a9f8-564d00018ad1 | example3.com |      3306   | ONLINE       | SECONDARY   | 8.0.13         |
+---------------------------+--------------------------------------+--------------+-------------+--------------+-------------+----------------+
Значение колонки MEMBER_STATE может быть разное. Статусы можно посмотреть на странице официальной документации https://dev.mysql.com/doc/refman/8.0/en/group-replication-server-states.html. Если сервер к примеру корректно перезагружен или выключен, он исчезнет из этой таблицы, поэтому желательно знать общее количество узлов в вашей схеме и следить за их количеством.Дополнительно нужно следить за производительностью каждого узла:SELECT * FROM performance_schema.replication_group_member_stats\G
*************************** 1. row ***************************
                              CHANNEL_NAME: group_replication_applier
                                   VIEW_ID: 16178860996821458:41
                                 MEMBER_ID: 500049c2-99b7-11e9-8d36-e4434b5f9d0c
               COUNT_TRANSACTIONS_IN_QUEUE: 0
                COUNT_TRANSACTIONS_CHECKED: 75715997
                  COUNT_CONFLICTS_DETECTED: 0
        COUNT_TRANSACTIONS_ROWS_VALIDATING: 1957048
        TRANSACTIONS_COMMITTED_ALL_MEMBERS: 500049c2-99b7-11e9-8d36-e4434b5f9d0c:1-1821470279,
500293cf-594c-11ea-aafd-e4434ba03de0:1-622868371,
5000d25c-059e-11e8-822b-564d00018ad1:1-140221041,
c9aae4fb-97a6-11eb-89d1-e4434b5f9d0c:1-125382195
            LAST_CONFLICT_FREE_TRANSACTION: c9aae4fb-97a6-11eb-89d1-e4434b5f9d0c:125471159
COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE: 0
         COUNT_TRANSACTIONS_REMOTE_APPLIED: 5664
         COUNT_TRANSACTIONS_LOCAL_PROPOSED: 75710337
         COUNT_TRANSACTIONS_LOCAL_ROLLBACK: 0
*************************** 2. row ***************************
                              CHANNEL_NAME: group_replication_applier
                                   VIEW_ID: 16178860996821458:41
                                 MEMBER_ID: 50024be2-9889-11eb-83da-e4434ba03de0
               COUNT_TRANSACTIONS_IN_QUEUE: 0
                COUNT_TRANSACTIONS_CHECKED: 75720452
                  COUNT_CONFLICTS_DETECTED: 0
        COUNT_TRANSACTIONS_ROWS_VALIDATING: 1955202
        TRANSACTIONS_COMMITTED_ALL_MEMBERS: 500049c2-99b7-11e9-8d36-e4434b5f9d0c:1-1821470279,
500293cf-594c-11ea-aafd-e4434ba03de0:1-622868371,
5000d25c-059e-11e8-822b-564d00018ad1:1-140221041,
c9aae4fb-97a6-11eb-89d1-e4434b5f9d0c:1-125377993
            LAST_CONFLICT_FREE_TRANSACTION: c9aae4fb-97a6-11eb-89d1-e4434b5f9d0c:125470919
COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE: 0
         COUNT_TRANSACTIONS_REMOTE_APPLIED: 75711354
         COUNT_TRANSACTIONS_LOCAL_PROPOSED: 9105
         COUNT_TRANSACTIONS_LOCAL_ROLLBACK: 0
*************************** 3. row ***************************
                              CHANNEL_NAME: group_replication_applier
                                   VIEW_ID: 16178860996821458:41
                                 MEMBER_ID: 500b2035-986e-11eb-a9f8-564d00018ad1
               COUNT_TRANSACTIONS_IN_QUEUE: 38727
                COUNT_TRANSACTIONS_CHECKED: 49955241
                  COUNT_CONFLICTS_DETECTED: 0
        COUNT_TRANSACTIONS_ROWS_VALIDATING: 1250063
        TRANSACTIONS_COMMITTED_ALL_MEMBERS: 500049c2-99b7-11e9-8d36-e4434b5f9d0c:1-1821470279,
500293cf-594c-11ea-aafd-e4434ba03de0:1-622868371,
5000d25c-059e-11e8-822b-564d00018ad1:1-140221041,
c9aae4fb-97a6-11eb-89d1-e4434b5f9d0c:1-125382195
            LAST_CONFLICT_FREE_TRANSACTION: c9aae4fb-97a6-11eb-89d1-e4434b5f9d0c:125430975
COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE: 47096
         COUNT_TRANSACTIONS_REMOTE_APPLIED: 49908155
         COUNT_TRANSACTIONS_LOCAL_PROPOSED: 0
         COUNT_TRANSACTIONS_LOCAL_ROLLBACK: 0
3 rows in set (0.00 sec)
Тут нас интересуют в первую очередь COUNT_TRANSACTIONS_IN_QUEUE, похож на Seconds_Behind_Master в асинхронной репликации. Как видно на третьем сервере количество транзакций в очереди слишком большое, а это повод начать разбираться что же здесь не так.Резервное копированиеЯ надеюсь, у вас делается регулярное резервное копирование базы данных (БД) и конечно на специально выделенный сервер. Так же желательно убедиться перед миграцией, что на всех узлах с БД есть запас по месту, превышающий в два с половиной раза размер каталога с базой. Это нам понадобится для создания локальной резервной копии, на случай если что-то пойдёт не так, и позволит нам вернуть всё как было. Если у вас файловая система с поддержкой моментальных снимков, не в чём себе не отказывайте, но свободного места должно быть много, так как в самые тяжёлые таблицы будет добавлен дополнительный столбец, а это повлечёт за собой их пересоздание.План миграцииВ идеальном варианте, нужно провести тестовую миграцию на каком-нибудь тестовом кластере. Но если всё делать правильно и не пренебрегать созданием резервных копий, то всегда можно будет откатиться назад. План действий на случай непредвиденных обстоятельств, тоже желательно написать.Если всё идёт гладко:
  • Пропиливаем необходимые дырки в файрволле (для общения узлов между собой нужно открыть TCP 33061 порт). Выписываем необходимые сертификаты;
  • Собираем репозиторий с MySQL 8.0 (FreeBSD, Poudriere - у каждого свои причуды);
  • В системе мониторинга переводим серверы в режим обслуживания, уведомляем всех пользователей Zabbix (чтобы никто не удивлялся);
  • Выключаем репликацию на всех узлах, которые были Secondary для этого сервера (мы же не хотим, чтобы какие-нибудь наши изменения улетели на действующие сервера). Выключаем репликацию на текущем узле;
  • Выключаем MySQL 5.7 сервер на первом подопытном узле;
  • Делаем резервное копирование БД с сохранением атрибутов файлов (сохраняем рядом, чтобы быстро восстановить базу);
  • Обновляем пакеты на новую версию с новыми зависимостями;
  • Запускаем MySQL 8.0 сервер (mysql_upgrade не нужен, с 8 версии это действо происходит автоматически);
  • Добавляем первичные ключи в таблицы, в которых их нет (требования групповой репликации, иначе операции добавления, удаления и т. д. работать не будут). Операция длительная, зависит от размера таблиц и производительности сервера;
  • Включаем репликацию на этом сервере, отреплецируем все изменения, выключаем репликацию (подтянем изменённые данные с действующего сервера, накопившееся за время наших манипуляций);
  • Сбрасываем все упоминания об асинхронной репликации на данном сервере (команда RESET SLAVE ALL;);
  • Настраиваем групповую репликацию и проверяем всё ли работает;
  • Переключаем Zabbix сервер и Zabbix фронтенд на БД с ГР;
  • Настраиваем групповую репликацию на других узлах (делаем шаги с 4 по 8, только с удалением каталога с БД перед 8 шагом, т. к. нам нужна чистая установка);
  • Перенастраиваем мониторинг;
  • Переделываем Ansible Playbook'и и конфигурационные файлы;
  • Меняем скрипты и задачи по переключению мастера;
  • Настраиваем HADNS;
  • Обновляем документацию;
На непредвиденный случай:
  • Останавливаем MySQL сервер;
  • Возвращаем предыдущие версии пакетов;
  • Удаляем каталог с БД и восстанавливаем из локальной резервной копии, запускаем MySQL сервер;
  • Настраиваем асинхронную репликацию;
Откатываемся бесконечное количество раз, пока всё не пройдёт гладко.Далее подробно рассмотрим 9, 12 и 14 шаги.Шаг 9: Добавление первичных ключейНаличие первичных ключей является одним из основных моментов для правильного функционирования групповой репликации. Все требования можно посмотреть здесь.Отсутствие первичных ключей можно выяснить запросом взятым вот отсюда.
SELECT tables.table_schema , tables.table_name , tables.engine
FROM information_schema.tables
LEFT JOIN (
SELECT table_schema , table_name
FROM information_schema.statistics
GROUP BY table_schema, table_name, index_name HAVING
SUM( case when non_unique = 0 and nullable != 'YES' then 1 else 0 end ) = count(*) ) puks
ON tables.table_schema = puks.table_schema and tables.table_name = puks.table_name
WHERE puks.table_name is null
AND tables.table_type = 'BASE TABLE' AND Engine="InnoDB";
Какой тип ключей и для каких колонок его создать я подсмотрел на форуме Zabbix, вот тут. Чтобы не поломалось обновление Zabbix, в таблице dbversion добавляем первичный ключ по существующему столбцу. Ниже необходимые запросы.
ALTER TABLE history ADD COLUMN `id` BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT;
ALTER TABLE history_uint ADD COLUMN `id` BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT;
ALTER TABLE history_text ADD COLUMN `id` BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT;
ALTER TABLE history_str ADD COLUMN `id` BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT;
ALTER TABLE history_log ADD COLUMN `id` BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT;
ALTER TABLE dbversion ADD PRIMARY KEY (mandatory);
Напоминаю действие занимает большое количество времени на больших таблицах. Надеюсь, когда-нибудь это внесут в схему БД для Zabbix.Шаг 12: Запуск групповой репликацииВсе настройки, относящиеся к групповой репликации, я собрал в одном месте в конфигурационном файле.
server-id=[номер сервера в кластере по порядку]
gtid_mode=ON
enforce_gtid_consistency=ON
log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
master_info_repository=TABLE
relay_log_info_repository=TABLE
transaction_write_set_extraction=XXHASH64
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
plugin_load_add='group_replication.so;mysql_clone.so'
ssl-ca=/usr/local/etc/ssl/mysql/ca.crt
ssl-cert=/usr/local/etc/ssl/mysql/server.crt
ssl-key=/usr/local/etc/ssl/mysql/server.key
group_replication_ssl_mode=VERIFY_IDENTITY
group_replication_group_name="[одинаковое на всех узлах, генерируем один раз командой SELECT UUID();]"
group_replication_start_on_boot=off # включаем после добавления всех узлов в группу
group_replication_local_address="[полное имя текущего сервера].com:33061"
group_replication_group_seeds="example1.com:33061,example2.com:33061,example3.com:33061"
group_replication_ip_allowlist="2.2.2.2/32,3.3.3.3/32,4.4.4.4/32"
group_replication_member_weight=50
group_replication_recovery_use_ssl=ON
group_replication_recovery_ssl_verify_server_cert=ON
group_replication_recovery_ssl_ca=/usr/local/etc/ssl/mysql/ca.crt
group_replication_recovery_ssl_cert=/usr/local/etc/ssl/mysql/server.crt
group_replication_recovery_ssl_key=/usr/local/etc/ssl/mysql/server.key
Добавляем это всё в my.cnf, дубликаты переменных, которые встречаются в файле до этого, необходимо удалить. Теперь можно перезапустить сервер, либо проверить значение переменных как написано ниже и поменять их вручную. Обратите внимание на переменную group_replication_start_on_boot, она выключена, поэтому при рестарте репликация не запустится.Проверяем значение переменных командой SHOW VARIABLES LIKE 'binlog_format'; меняем с помощью команды SET GLOBAL binlog_format = RAW; это относится к переменным в верхней части конфига, остальные настройки подтянутся при активации групповой репликации.Переменные group_replication_ssl_mode и group_replication_recovery_ssl_verify_server_cert установлены в максимально безопасный режим с проверкой сертификата сервера, так что при выписывании сертификата укажите в Subject Alternative Name (SAN) полные имена всех улов кластера, которые есть в group_replication_group_seeds.В переменной group_replication_member_weight можно указать вес узла. Полезно, когда у вас один сервер, это виртуалка, для него можно указать вес поменьше и при следующих выборах мастера он победит в последнюю очередь.Создаём пользователя для работы репликации:
SET SQL_LOG_BIN=0;
CREATE USER 'replication'@'%' IDENTIFIED BY '[придумайте пароль]' REQUIRE SSL;
GRANT replication slave ON *.* TO 'replication'@'%';
GRANT BACKUP_ADMIN ON *.* TO 'replication'@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
Устанавливаем плагины и проверяем статус:
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
INSTALL PLUGIN clone SONAME 'mysql_clone.so';
SHOW PLUGINS;
Настраиваем пользователя, используемого при восстановлении БД с работающего сервера:
CHANGE REPLICATION SOURCE TO SOURCE_USER='replication', SOURCE_PASSWORD='[придуманный пароль]' \\
  FOR CHANNEL 'group_replication_recovery';
Первый запуск группы. Переменную group_replication_bootstrap_group включаем только на первом сервере, на остальных, просто запускаем групповую репликацию:
SET GLOBAL group_replication_bootstrap_group=ON; # выполняем только на первом сервере
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF; # выполняем только на первом сервере
Если никаких ошибок команда не вернула, то можно посмотреть информацию о вновь созданной группе:
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+---------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE  |
+---------------------------+--------------------------------------+-------------+-------------+---------------+
| group_replication_applier | ce9be252-2b71-11e6-b8f4-00212844f856 |example1.com |       3306  | ONLINE        |
+---------------------------+--------------------------------------+-------------+-------------+---------------+
Проверьте дополнительно логи MySQL сервера на содержание в них ошибок.Шаг 14: Добавление узла в группуПосле того как вы переключили Zabbix сервер и фронтенд на сервер с ГР, можно добавить оставшиеся узлы в кластер. Для этого выключаем MySQL сервер, делаем локальную копию, обновляем пакеты и удаляем текущий каталог с БД.Запускаем чистую базу данных и проделываем всё тоже самое как в 12-ом шаге, с добавлением специфичных для этого сервера настроек (server-id, group_replication_local_address). Так как группа уже запущена, использовать переменную group_replication_bootstrap_group не нужно.На этом этапе и будет использоваться так называемый Distributed Recovery механизм в который входит mysql_clone плагин. При подключении к узлу донору в первую очередь он попытается использовать бинарный лог, если информации в нём будет недостаточно, он полностью скопирует базу, включая созданного для репликации пользователя.Проверьте статус группы и что сервер добавился в неё, а так же его производительность, успевает ли узел применять все транзакции.После добавления оставшихся серверов, поменяйте в конфиге my.cnf значения переменной group_replication_start_on_boot с off на on и перезагрузите MySQL сервер на любом ведомом сервере и проверьте что он остался в группе.Полезные командыSELECT * FROM performance_schema.replication_group_members; - показывает статус всех узлов в группе.SELECT * FROM performance_schema.replication_group_member_stats\G - показывает производительность каждого отдельного узла.SELECT group_replication_set_as_primary('[uuid узла]'); - переключение ведущего узла.Безотказный Zabbix серверА что же с Zabbix сервером спросите вы, если дочитаете до этого момента, а всё просто. Я сделал так чтобы он постоянно следовал за ведущим сервером групповой репликации. В кроне на каждом сервере запускается скрипт, который проверяет что узел сейчас Primary в ГП, если да, то запускает Zabbix сервер, если нет, то останавливает его. Дальше включается в работу HADNS, он проверяет на каком сервере запущен Zabbix и отдает нужный IP адрес для DNS записи.ЗаключениеВозможно, сделано не всё так элегантно как хотелось бы. Вы наверно захотите использовать mysql-shell, mysqlrouter и преобразовать Group Replication в InnoDB Cluster, а может добавить HAProxy, особенно это полезно, когда разворачиваешь Zabbix с нуля. Надеюсь, этот рассказ послужит неплохой отправной точкой и будет полезен. Спасибо за внимание!Дополнительная литератураhttps://dev.mysql.com/doc/refman/8.0/en/group-replication.htmlhttps://blog.zabbix.com/scaling-zabbix-with-mysql-innodb-cluster/8472/https://en.wikipedia.org/wiki/Paxos_(computer_science)
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_sistemnoe_administrirovanie (Системное администрирование), #_mysql, #_itinfrastruktura (IT-инфраструктура), #_monitoring, #_zabbix, #_mysql, #_replica, #_cluster, #_faulttolerant, #_sistemnoe_administrirovanie (
Системное администрирование
)
, #_mysql, #_itinfrastruktura (
IT-инфраструктура
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 17-Май 10:57
Часовой пояс: UTC + 5