Open10

MySQLで自動フェイルオーバーのやり方を探る

maruwaremaruware

クラウドに甘やかされて育ってしまい全然わからないので探る

maruwaremaruware

ググるとMHAとmysqlfailoverとOrchestratorの3つが主に使われているミドルウェアっぽい

maruwaremaruware

Orchestratorは小規模にはちょっと大袈裟な感じがある。
mysqlfailoverから始めてみるのが良いだろうか。

maruwaremaruware

まずレプリケーション状態を作る

この辺りを参考にする
https://ngyuki.hatenablog.com/entry/2019/02/18/103036
https://qiita.com/takyam/items/f13bc4a1db0433ffb958

MySQL8だとmysqlfailoverが怪しいのでMySQL5.7にする。

docker-compose.yml
  mysql_master:
    image: mysql:5.7
    command:
      - --default_authentication_plugin=mysql_native_password
      - --gtid_mode=ON
      - --enforce_gtid_consistency=ON
      - --master-info-repository=TABLE
      - --relay-log=relay-bin
      - --relay-log-recovery=1
      - --relay-log-info-repository=TABLE
      - --log-bin=mysql-bin
      - --server_id=1
    environment: &environment
      TZ: Asia/Tokyo
      MYSQL_ALLOW_EMPTY_PASSWORD: 1
      MYSQL_DATABASE: dev
      MYSQL_USER: dbuser
      MYSQL_PASSWORD: secret
      MYSQL_ROOT_PASSWORD: rootsecret
      MYSQL_REPLICATION_USER: repl
      MYSQL_REPLICATION_PASSWORD: replsecret
    volumes:
      - db-data:/var/lib/mysql
      - ./mysql/init.sh:/docker-entrypoint-initdb.d/init.sh:ro

  mysql_slave:
    image: mysql:5.7
    depends_on:
      - mysql_master
    command:
      - --default_authentication_plugin=mysql_native_password
      - --gtid_mode=ON
      - --enforce_gtid_consistency=ON
      - --master-info-repository=TABLE
      - --relay-log=relay-bin
      - --relay-log-recovery=1
      - --relay-log-info-repository=TABLE
      - --log-bin=mysql-bin
      - --server_id=2
    environment:
      <<: *environment
      MYSQL_REPLICATION_HOST: mysql_master
    volumes:
      - ./mysql/init.sh:/docker-entrypoint-initdb.d/init.sh:ro
init.sh
#!/bin/bash
if [ -v MYSQL_REPLICATION_USER -a -v MYSQL_REPLICATION_PASSWORD ]; then
  mysql -u root -p$MYSQL_ROOT_PASSWORD -v mysql <<SQL
    CREATE USER '$MYSQL_REPLICATION_USER'@'%' IDENTIFIED BY '$MYSQL_REPLICATION_PASSWORD';
    GRANT REPLICATION SLAVE ON *.* TO '$MYSQL_REPLICATION_USER'@'%';
SQL
fi
mysql -u root -p$MYSQL_ROOT_PASSWORD -v mysql <<SQL
  RESET MASTER;
SQL

if [ -v MYSQL_REPLICATION_USER -a -v MYSQL_REPLICATION_PASSWORD -a -v MYSQL_REPLICATION_HOST ]; then
  mysqladmin ping --wait=5 -h "$MYSQL_REPLICATION_HOST"
  mysql -u root -p$MYSQL_ROOT_PASSWORD -v <<SQL
    CHANGE MASTER TO
      MASTER_HOST = '$MYSQL_REPLICATION_HOST',
      MASTER_USER = '$MYSQL_REPLICATION_USER',
      MASTER_PASSWORD = '$MYSQL_REPLICATION_PASSWORD',
      MASTER_AUTO_POSITION = 1,
      MASTER_DELAY = 10;
    START SLAVE;
SQL
fi
maruwaremaruware
docker-compose.yml
  mysqlfailover:
    image: sandeepsukhani/mysql-utilities
    command:
      - mysqlfailover
      - --master=root:rootsecret@mysql_master:3306
      - --slaves=root:rootsecret@mysql_slave:3306
      - --failover-mode=auto
      - --candidates=root:rootsecret@mysql_slave:3306
      - --rpl-user='repl:replsecret'
    tty: true
    links:
      - mysql_master
      - mysql_slave

これで起動までいけた。

辿り着くまでmysqlfailoverがよくわからないエラーで落ちて詰まっていたが、

docker-compose run mysqlfailover mysqlrplcheck  --master=root:rootsecret@mysql_master:3306 --slave=root:rootsecret@mysql_slave:3306

上記のように mysqlrplcheck を使うと問題が判別しやすい。