Собираем InnoDB cluster из mysql 5.7 на centos 7

от автора

Всем привет!

Как-то раз появилась по работе задача — есть вроде как настроенный тестовый innoDB cluster на нескольких виртуалках с centos 7.5, надо его поизучать и добавить еще пару нод. Можно ломать и издеваться как угодно. Звучит заманчиво.

До этого у меня опыта работы с этим кластером не было, ну да гугл в помощь.
За несколькими исключениями, все ссылки что в нем, что в яндексе вели либо на dev.mysql.com, либо на эту статью на Хабре. Вроде как по ней и был настроен кластер из двух нод.

Чтож, статью я прочитал, несколько удивился сложности добавления нод и отсутствию многих подробностей, ну да ладно. Добавил с грехом пополам новую ноду (часть команд не пригодилась, часть вообще все ломала), после чего начал экспериментировать с перезапуском нод и т.д.

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

При создании нового кластера к сожалению возникла не меньшая куча проблем и нестыковок. Возможно дело в версиях программ, я пробовал mysql 5.7. Возможно в дистрибутиве. В итоге я прекратил бездумные потуги делать все по бумажке и стал настраивать его методом тыка. И гугла.

Пара приятных вечеров и ночей и кластер собрался и даже отказался рушиться.
При этом способ его создания заметно отличался от предыдущих попыток и мне захотелось им поделиться, т.к. на просторах интернета других актуальных подробных понятных инструкций по настройке inndoDB cluster я не нашел.

Итак, имеем три одинаковых виртуалки со свежеустановленным Centos 7.5 minimal 1804 и отключенными selinux и firewalld:

1.1.1.1
1.1.1.2
1.1.1.3

По работе я использовал mysql 5.7, так что ее и используем. Начнем с 1.1.1.1:

1. Установим репозиторий mysql-community:

rpm -i https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm

Выключим репозиторий для 8, включим для 5.7 и проверим — если все ок, то устанавливаем mysql:

yum install yum-utils yum-config-manager --disable mysql80-community yum-config-manager --enable mysql57-community yum repolist yum install mysql-community-server mysql-shell

2. Приводим /etc/my.cnf к такому виду:

[mysqld]  datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock  symbolic-links=0  log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid  bind-address=0.0.0.0 port=3301 # Replication part server_id=1 gtid_mode=ON enforce_gtid_consistency=ON master_info_repository=TABLE relay_log_info_repository=TABLE binlog_checksum=NONE log_slave_updates=ON log_bin=binlog binlog_format=ROW plugin-load = group_replication.so # Group replication part transaction_write_set_extraction=XXHASH64 loose-group_replication_start_on_boot = OFF loose-group_replication_local_address = 1.1.1.1:33011 loose-group_replication_bootstrap_group = OFF report_port = 3301 report_host = 1.1.1.1 

Здесь 3301 это порт, на котором будет слушать mysql, а 33011 порт, на котором ноды общаются между собой.

3. Запустим mysql и выполним предварительную настройку:

systemctl start mysqld grep 'password' /var/log/mysqld.log mysql_secure_installation

4. Ну и создадим кластер, а так же отдельного пользователя для управления им. Если вы знаете заранее ip-адреса нод, то можно их сразу перечислить в ipWhitelist. Сделаем вид, что мы пока не знаем про 1.1.1.2. и 1.1.1.3:

mysqlsh > \c 127.0.0.1:3301 > dba.configureLocalInstance("127.0.0.1:3301", {mycnfPath: "/etc/my.cnf", clusterAdmin: "cladmin", clusterAdminPassword: "SomePassword!123"}) > \c cladmin@1.1.1.1:3301 > dba.checkInstanceConfiguration() > cl=dba.createCluster('TestCluster', {ipWhitelist: '1.1.1.1'}) > dba.configureLocalInstance() > cl.status()

Готово! cl.status должен вывести что-то типа этого:

{     "clusterName": "TestCluster",     "defaultReplicaSet": {         "name": "default",         "primary": "1.1.1.1:3301",         "ssl": "REQUIRED",         "status": "OK_NO_TOLERANCE",         "statusText": "Cluster is NOT tolerant to any failures.",         "topology": {             "1.1.1.1:3301": {                 "address": "1.1.1.1:3301",                 "mode": "R/W",                 "readReplicas": {},                 "role": "HA",                 "status": "ONLINE"             }         }     },     "groupInformationSourceMember": "mysql://cladmin@1.1.1.1:3301" } 

При изменении кластера надо будет выполнять на всех нодах локально команду dba.configureLocalInstance() для сохранения изменений:

WARNING: On instance '1.1.1.1:3301' membership change cannot be persisted since MySQL version 5.7.23 does not support the SET PERSIST command (MySQL version >= 8.0.11 required). Please use the <Dba>.configureLocalInstance command locally to persist the changes.

Т.к. мы собираемся добавить еще парочку нод, то не закрываем связь с сервером 1.1.1.1, он нам еще пригодится.

Теперь попробуем добавить в кластер ноду 1.1.1.2. Для этого выполняем на ней все те же команды до 3 шага включительно, не забывая поменять server_id, loose-group_replication_local_address и report_host.

4. Выполняем на 1.1.1.2:

mysql -p > set GLOBAL group_replication_allow_local_disjoint_gtids_join=ON;

Я пытался задавать эту переменную через mysqlsh, переключаясь в режим sql, но действия там никак не влияли на нее в mysql. Далее:

mysqlsh > \c 127.0.0.1:3301 > dba.configureLocalInstance("127.0.0.1:3301", {mycnfPath: "/etc/my.cnf", clusterAdmin: "cladmin", clusterAdminPassword: "SomePassword!123"}) > \c cladmin@1.1.1.2:3301 > dba.checkInstanceConfiguration()

5. Возвращаемся к первой ноде 1.1.1.1. Если закрыли соединение, то можно быстро подключиться к кластеру так:

mysqlsh --uri cladmin@1.1.1.1:3301 --cluster > \sql > STOP GROUP_REPLICATION; > SET GLOBAL group_replication_ip_whitelist="1.1.1.1,1.1.1.2"; > START GROUP_REPLICATION; > \js > cluster.addInstance('cladmin@1.1.1.2:3301', {ipWhitelist: '1.1.1.1,1.1.1.2'}) > cluster.status() 

Почему-то при добавлении ноды без опции ipWhitelist он ей не передается автоматически, поэтому указываем вручную.
Если whitelist у вас изначально настроен на все ноды или подсеть, то команды в sql режиме можно пропустить.

Не забываем выполнить dba.configureLocalInstance() на всех нодах для сохранения конфигурации.

Получился кластер их двух нод:

{     "clusterName": "TestCluster",     "defaultReplicaSet": {         "name": "default",         "primary": "1.1.1.1:3301",         "ssl": "REQUIRED",         "status": "OK_NO_TOLERANCE",         "statusText": "Cluster is NOT tolerant to any failures.",         "topology": {             "1.1.1.1:3301": {                 "address": "1.1.1.1:3301",                 "mode": "R/W",                 "readReplicas": {},                 "role": "HA",                 "status": "ONLINE"             },             "1.1.1.2:3301": {                 "address": "1.1.1.2:3301",                 "mode": "R/O",                 "readReplicas": {},                 "role": "HA",                 "status": "ONLINE"             }         }     },     "groupInformationSourceMember": "mysql://cladmin@1.1.1.1:3301" } 

Чтож, кластер из двух нод есть, но в режиме «Cluster is NOT tolerant to any failures.»
Добавим третью, алгоритм в принципе не отличается от добавления второй.

Если вам опять требуется поменять whitelist, то выполнять команды надо на r/w ноде, т.к. на r/o нодах это ни к чему вроде не приводит. При этом r/o ноды отвалятся и их надо будет пересоединить, попутно сообщив новый whitelist.
В нашем случае:

> cluster.rejoinInstance('cladmin@1.1.1.2:3301', {ipWhitelist: '1.1.1.1,1.1.1.2,1.1.1.3'})

Ну и опять же не забываем выполнить dba.configureLocalInstance() на всех нодах для сохранения конфигурации.

Кластер из трех нод выглядит так:

{     "clusterName": "TestCluster",     "defaultReplicaSet": {         "name": "default",         "primary": "1.1.1.1:3301",         "ssl": "REQUIRED",         "status": "OK",         "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",         "topology": {             "1.1.1.1:3301": {                 "address": "1.1.1.1:3301",                 "mode": "R/W",                 "readReplicas": {},                 "role": "HA",                 "status": "ONLINE"             },             "1.1.1.2:3301": {                 "address": "1.1.1.2:3301",                 "mode": "R/O",                 "readReplicas": {},                 "role": "HA",                 "status": "ONLINE"             },             "1.1.1.3:3301": {                 "address": "1.1.1.3:3301",                 "mode": "R/O",                 "readReplicas": {},                 "role": "HA",                 "status": "ONLINE"             }         }     },     "groupInformationSourceMember": "mysql://cladmin@1.1.1.1:3301" } 

В случае, если кластер развалился до состояния одной ноды, его надо будет запускать с параметром loose-group_replication_bootstrap_group = ON в /etc/my.cnf
После запуска параметр надо будет выключить обратно, иначе эта нода всегда будет отделяться от кластера и поддерживать свой.

Установка mysql-router хорошо описана тут, так что дублировать смысла не вижу.

На этом все вроде все, надеюсь кому-то мой опыт пригодится.
Спасибо за внимание.


ссылка на оригинал статьи https://habr.com/post/423587/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *