Показать статистику
0 голосов
от (17.4тыс. баллов)
Кто поделится инструкцией по настройке репликации в режиме мастер-мастер между двумя серверами под управлением Убунту?
686 просмотров 1 ответов
от (4.6тыс. баллов)
+1
Интересует этот же вопрос. +1
от (17.4тыс. баллов)
0
Я видел несколько толковых статей на английском. Если никто не предложит ничего лучше, постараюсь перевести кое-что. Сейчас как раз занят задачей настройки репликации, приходится по различным мануалам ходить.

1 Ответ

0 голосов
от (17.4тыс. баллов)

Вообщем, мне удалось успешно решить задачу по настройке Master-Master MySQL репликации между двумя удаленными серверами. Репликацию настраивал поверх OpenVPN канала, который предварительно настроил по инструкции взятой здесь ("Настройка OpenVPN - перевод официальной документации").

Для чистоты пошаговки сообщаю, что все делалось на Ubuntu 18.04

lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.2 LTS
Release:        18.04
Codename:       bionic

Первый сервер

Итак, после настройки OpenVPN, имея уже установленный MySQL, редактируем /etc/my.cnf. Для начала найдем где он:

egrep -v '^$|^#' /etc/mysql/my.cnf
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

Как видно из вывода выше, по стандартному файла нет, а лежит он здесь:

root@ubuntu-8gb-hel1-1:/etc/mysql/mysql.conf.d# ls
mysqld.cnf  mysqld_safe_syslog.cnf

Имя файла - mysqld.cnf.  Приведем файл к такому виду:

[mysqld_safe]
socket          = /var/run/mysqld/mysqld.sock
nice            = 0
[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
bind-address            = 0.0.0.0
key_buffer_size         = 16M
max_allowed_packet      = 16M
thread_stack            = 192K
thread_cache_size       = 8
myisam-recover-options  = BACKUP
query_cache_limit       = 1M
query_cache_size        = 16M
log_error = /var/log/mysql/error.log
server-id               = 2
log_bin                 = /var/log/mysql/mysql-bin.log
log_bin_index           = /var/log/mysql/mysql-bin.log.index
relay_log               = /var/log/mysql/mysql-relay-bin
relay_log_index         = /var/log/mysql/mysql-relay-bin.index
expire_logs_days        = 10
max_binlog_size         = 100M
log_slave_updates       = 1
auto-increment-increment = 2
auto-increment-offset = 2
slave_exec_mode         = IDEMPOTENT

Ключевых моментов здесь несколько. 

  • MySQL был перевешен на все имеющиеся адреса (bind-address= 0.0.0.0) 
  • добавлен log_bin и остальные параметры для репликации

Поскольку я буду гонять репликацию через тунель OpenVPN, мне нужно разрешить трафик только по этому внутреннему туннельному интерфейсу и запретить все ненужное (держать порт 3306 открытым на весь мир не тру).

tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 10.8.0.1  netmask 255.255.255.255  destination 10.8.0.2
        inet6 fe80::782e:bdb2:60ef:cb76  prefixlen 64  scopeid 0x20<link>
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (UNSPEC)
        RX packets 32386  bytes 8441773 (8.4 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 32429  bytes 8292722 (8.2 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Итак, как видно из вывода выше, мой внутренний адрес 10.8.0.1.

Далее задействуем iptables что бы разрешить трафик MyQL только по OpenVPN.

iptables -A INPUT -s 127.0.0.1/32 -d 127.0.0.1/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 10.8.0.6/32 -d 10.8.0.6/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 10.8.0.6/32 -d 10.8.0.1/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 10.8.0.1/32 -d 10.8.0.6/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 3306 -j DROP

Что бы правила сохранились и после рестарта системы, смотрите инструкцию тут.

Далее создадим пользователя для репликации:

mysql -u root -p [root_password]
CREATE USER 'replicator'@'10.8.0.6' IDENTIFIED BY '[myC001p@ssw0rd]';
GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'10.8.0.6' IDENTIFIED BY '[myC001p@ssw0rd]';

Обратите внимание. Адрес 10.8.0.6 - это адрес моего второго сервера, который подключен по OpenVPN к текущей машине. Важный момент - для репликации пароль пользователя не должен превышать 32 символа. Если зададите более длинный пароль, прийдется тратить время и менять его. Я на этот момент таки напоролся, потому что официальная документация об этом не предупреждает (либо я невниимательно читал).

Теперь переходим к настройке второго сервера.

Второй сервер

На второй машине у меня точно такая же убунту, поэтому расположение конфига тоже. как и для первого сервака. Редактируем файл /etc/mysql/mysql.conf.d/mysqld.cnf:

[mysqld_safe]
socket          = /var/run/mysqld/mysqld.sock
nice            = 0
[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
bind-address            = 0.0.0.0
key_buffer_size         = 16M
max_allowed_packet      = 16M
thread_stack            = 192K
thread_cache_size       = 8
myisam-recover-options  = BACKUP
query_cache_limit       = 1M
query_cache_size        = 16M
log_error = /var/log/mysql/error.log
server-id               = 1
log_bin                 = /var/log/mysql/mysql-bin.log
log_bin_index           = /var/log/mysql/mysql-bin.log.index
relay_log               = /var/log/mysql/mysql-relay-bin
relay_log_index         = /var/log/mysql/mysql-relay-bin.index
expire_logs_days        = 10
max_binlog_size         = 100M
log_slave_updates       = 1
auto-increment-increment = 2
auto-increment-offset   = 1
slave_exec_mode         = IDEMPOTENT

Далее аналогичным образом создадим пользователя для репликации. Только теперь у этого пользователя будет адрес первого сервера (откуда он будет подключаться):

mysql -u root -p [root_password]
CREATE USER 'replicator'@'10.8.0.1' IDENTIFIED BY '[myC001p@ssw0rd]';
GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'10.8.0.1' IDENTIFIED BY '[myC001p@ssw0rd]';

Теоретически, пароли можно (и наверное нужно) иметь разные. Для безопасности. Но что бы не запутаться, я оставил один пароль на обоих машинах.

Далее внесем правила в iptables (они точно такие же как и на первой машине):

iptables -A INPUT -s 127.0.0.1/32 -d 127.0.0.1/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 10.8.0.6/32 -d 10.8.0.6/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 10.8.0.6/32 -d 10.8.0.1/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 10.8.0.1/32 -d 10.8.0.6/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 3306 -j DROP

Теперь, если вам нужно реплицировать данные между уже настроенными серерами (как было в моем случае - база уже существовала), эту базу нужно перекинуть чепез mysqldump и восстановить на той машине, где ее нет. Иначе репликация будет ругаться что какая то таблица не найдена и т.п. Это важный момент, потому что я этого изначально не знал и пришлось потратить лишние 10 минут что бы это выяснить.

Далее нужно активировать саму репликацию.

от (17.4тыс. баллов)
0

Продолжение

Оба сервера настроены, включаем репликацию

Заходим на первый сервер, идем в mysql и выполняем:

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 |   488168 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

Тепепь идем на второй сервер и включаем репликацию с указанной позиции (4889168):

STOP SLAVE;
CHANGE MASTER TO MASTER_HOST = '10.8.0.6', MASTER_USER = 'replicator', MASTER_PASSWORD = 'myC001p@ssw0rd', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 48168; 
START SLAVE;

Симметрично повторяем шаги для второго сервера. На втором сервере смотрим тоже самое:

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 |  1024406 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

И теперь идем на первый сервер и включаем репликацию:

STOP SLAVE;
CHANGE MASTER TO MASTER_HOST = '10.8.0.1', MASTER_USER = 'replicator', MASTER_PASSWORD = 'myC001p@ssw0rd', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 1024406; 
START SLAVE;

На этом настройка закончена.

Как проверить что все работает? Идем на любой из серверов, создаем пустую базу данных и убеждаемся что на втором сервере все работает.

Индикацией того что все успешно сделано будет вывод с каждого из серверов:

mysql> pager less;
PAGER set to 'less'
mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.8.0.6
                  Master_User: replication
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000005
          Read_Master_Log_Pos: 490967
               Relay_Log_File: mysql-relay-bin.000015
                Relay_Log_Pos: 491180
        Relay_Master_Log_File: mysql-bin.000005
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           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: 490967
  Relay_Log_Space: 491434
              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: 1
                  Master_UUID: 26a385be-d0d2-11e8-81d5-42010aa60002
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 

Ключевыми являются два сообщения:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

На этом все. Если кто заметит неточности или если у кого то возникнут вопросы по настройке - велкам. 

...