LoginSignup
0
2

More than 3 years have passed since last update.

サーバー二台でdocker + MySQLを用いてレプリケーション

Last updated at Posted at 2020-07-27

ラズパイをサーバー化して環境構築をしているのですが、大苦戦中です。
CPUのアーキテクチャが組込用なので便利なdocker imageが全然使えないという。。。
SSL認証のときも大変でしたが、それはまた別の記事で。

※今回はラズパイをDBサーバーとしましたが、通常のオンプレサーバーであっても同じ書き方でできるはずです。

1.やりたいこと

1.1.レプリケーション

サーバー1にマスターDBをおき、サーバー2にスレイブDBをおいて、スレイブでマスターDBの更新を検知して全くDBを保持すること
片方のサーバーが物理的に壊れてもDBのデータは残ります。(うっかりdrop tableなんてオペミスは無理ですが)

1.2.レプリケーションの設定をdockerで簡略化

結構めんどくさいので、新しいサーバーにもdocker-compose up -dの1コマンドで環境を設定できたら楽です

2.手順

2.1.全体の構成

サーバー構成
192.168.0.2 → master用サーバー
192.168.0.3 → slave用サーバー

ディレクトリ構成

├── db
│ ├── Dockerfile
│ ├── conf
│ │ ├── master.cnf
│ │ └── slave.cnf
│ └── sql
│ ├── init_master.sql
│ └── init_slave.sql
├── docker-compose.yml

↑treeコマンドで表示したのですが、みづらいですねすみません。

2.2.docker-compose.ymlの作成

docker-compose.ymlにてdbディレクトリをビルドします
そしてdbディレクトリには必要な設定ファイルを仕込むのですが、まずはdocker-composeだけ載せますと

docker-compose.yml
version: '3'

services:
  db:
    build: ./db
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: db_name
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      TZ: 'Asia/Tokyo'。
    volumes:
      # 初期データを投入するSQLが格納されているdir
      - ./db/sql:/docker-entrypoint-initdb.d
      # 永続化するときにマウントするdir
      - /var/lib/mysql:/var/lib/mysql

build: ./dbにてdocker-compose.ymlと同じ階層のdbディレクトリをビルドしています。

2.3.dockerfileとconfigファイルの作成

次にdockerfileを書きます。
これは一部、マスターとスレーブで書き換えが要ります

Dockerfile
FROM mysql:5.7
# 読み込むconfファイルをマスターかスレーブかでコメントアウトして分岐させる
#ENV conf_file ./conf/slave.cnf
ENV conf_file ./conf/master.cnf

ADD $conf_file /etc/mysql/my.cnf
RUN chmod 644 /etc/mysql/my.cnf

これまではほとんどmasterとslaveで個別の設定はありませんでした。

次にmasterとslaveのそれぞれのconfファイルを設定していきます。

master.conf
[mysqld]
user=mysql
server-id = 1
log-bin
binlog-format = MIXED
slave.conf
[mysqld]
user=mysql
server-id=2
log-bin
read_only

2.4.DB初期化時に読み込まれるファイルの作成

次にdbディレクトリがビルドされるときの初期化のsqlを書きます

init_master.sql
-- slaveが使用するユーザーを設定(slaveのサーバーの内部IPに合わせる)
CREATE USER 'replica'@'192.168.0.3' IDENTIFIED BY 'replica';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.3';
init_slave.sql
-- MASTER_LOG_FILEやMASTER_LOG_POSの調べ方は後述
CHANGE MASTER TO MASTER_HOST='192.168.0.2', 
    MASTER_PORT=3306, 
    MASTER_USER='replica', 
    MASTER_PASSWORD='replica', 
    MASTER_LOG_FILE='3ae7abcabc-bin.000003', 
    MASTER_LOG_POS=1234;

init_slave.sqlのmaster_log_fileやmaster_log_posの調べ方ですが、マスターDBサーバーのコンテナに入って

$docker exec -it <container_id> bash
#mysql -u root -p password
>show master status\G;

こんな順番でコマンドを入力するとマスターのログファイルの位置が取得できます。
mysql 5.7以降だったか、わざわざこんなことをしなくても 
MASTER_AUTO_POSITION=1
と設定するだけでいけるとかなんとか

これでレプリケーションできるかと思います。

何もミスってなければslaveのサーバーにて

$docker exec -it <container_id> bash
#mysql -u root -p password
>show slave status\G;

こんな感じでDBコンテナに入ってコマンドを打つとずらーっと表示されますが

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

この2つのパラメータがYesになります
connectingとか書いてたらだめです。

ずらーっと表示されている下の方にエラー内容が出ます

Last_IO_Errno: 0
Last_IO_Error: 
Last_SQL_Errno: 0
Last_SQL_Error: 

※これは正常な状態です

ここに出てくるエラーナンバーやエラーメッセージを頼りにデバッグしたらできるかと思います。

どうしても自動化しきれていませんが、だいぶ再現するのが楽にはできたかなと思います。
何か補足があったらぜひお願いいたします。

あ、あと既にテーブルがあって運用中のDBをマスタースレーブ構成にしたい場合は、masterでダンプしてそのデータをslaveでリストアして反映する必要があります。

こっちに書きましたので参考までに

参考
http://www.tohoho-web.com/ex/mysql-replication.html

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2