Всем привет!
Как-то раз появилась по работе задача — есть вроде как настроенный тестовый 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 хорошо описана тут, так что дублировать смысла не вижу.
На этом все вроде все, надеюсь кому-то мой опыт пригодится.
Спасибо за внимание.
Автор: aniserg