【未完成】【Docker】もう悩まない！MySQLのフェイルオーバーをdocker-composeで爆速構築

# 【Docker】もう悩まない！MySQLのフェイルオーバーをdocker-composeで爆速構築
## 概要
- MHA, master1, master2, slave1, slave2 それぞれのコンテナで動かし**docker-compose**でオーケストレーション
- MHAコンテナがMySQLのmasterコンテナのを監視し、**障害発生時などにフェイルオーバー**を行う

![image](https://qiita-image-store.s3.amazonaws.com/0/62822/ee762f70-c672-f041-bbaa-427820687388.png)

## フェイルオーバーとは
- 稼働中のシステム(master1)に障害が発生した際に、代替システム(master2)がその機能を自動的に引き継ぎ、処理を続行する仕組み。企業の情報システムなどで、サーバの信頼性を高めるためによく用いられる
- AWSのRDSのマルチAZがこれ

## レプリケーションとは
- レプリケーションとは、あるデータベースとまったく同じ内容の複製（レプリカ）を別のコンピュータ上(slave)に作成し、常に内容を同期させる機能。 負荷分散や耐障害性の向上などを目的に行われる。

## 経緯
- １から構築すると**時間がかかる**
- MySQL MHAを使ったフェイルオーバーの環境構築サイトはいくつかあったので、理解のついでにdocker-composeでオーケストレーションをしたかった
- レプリケーションが組めるdocker-composeのサンプルなどはすでにあったが、フェイルオーバーまでなかった
- MySQLレベルの向上のため
- docker普及のため
- 最終的には、[Rancher](http://qiita.com/okamu_/items/da52b4dc12221feca55c)での運用を目指す

## MySQL MHA
### MySQL MHAとは
- (Master High Availability Manager and tools for MySQL) の略
- MySQLマスタ**障害発生時**に、MySQLマスタの**自動フェイルオーバー**を行い高可用性を実現するオープンソースツール
- Perlで実装されている
- MySQLのマスタをフェイルオーバーさせ、スレーブをマスタに昇格させる作業を短時間(10〜30秒程度)で実行できる

### 主な機能
#### **フェイルオーバー機能**
##### 自動
- MHAマネージャがマスタを監視し、マスタに障害が発生するとフェイルオーバーさせます。最新のDB情報を反映しているスレーブから、その他のスレーブに対して差分を適用する動作を行うため、スレーブ間のデータ整合性が保証されます。
- MHA自身では、MySQLのサービス監視せず、監視作業を他の監視ソフトウェアで行い、監視ソフトウェアからの通知によりフェイルオーバーを実行します。

##### 手動
- 手動でのマスタフェイルオーバーも可能

####　マスタ切り替え機能
- オンラインでマスタを別ホストに切り替える機能です。0.5〜2秒ほどの書き込みブロックのみで切り替え可能です。

#### **マスタ昇格指定機能**
- 「特定スレーブのマスタ昇格(昇格不可)指定」が可能です。

### 動作条件
- rootで各ノード間でのSSH公開鍵認証が可能であること (**私はこれを見逃していた...**)
- MySQL 5.0 以降のみサポート
- マスタ昇格候補のサーバでlog-binがenableであること
- マスタ昇格候補サーバにレプリケーション用ユーザが存在すること
- ステートメントベースレプリケーションでは「LOAD DATA INFILE」の使用は禁止

## **結論**
- 「**各ノード間でのSSH公開鍵認証が可能**」というところを見ていなく、ハマってしまった。結局、時間（見積もり）が足りず**期待させておいて未完成**です。ごめんなさい
- 「いいね」で応援していただければ励みになります泣
- **てっきりlinksでどうにかなるものかと思っていたところが誤算**
- 修正次第、更新します。（現在進行中！！）

## ベースimageを作る
- ベースimageを元に、フェイルオーバー環境を構築できるよう設計

#### docker image
- 今回は各コンテナにはperl環境が必要
- master, slaveにはmha-nodeがinstallされていないといけない

![IMG_8767.JPG](https://qiita-image-store.s3.amazonaws.com/0/62822/dbff8138-dd69-818d-3030-0a0c676698f1.jpeg)
手書きです。ごめんなさい！

### 0.基本環境(vvdocker/base-perl)
```
FROM ubuntu

RUN apt-get -y update
RUN apt-get -y install wget git

# MHA NODE
RUN apt-get -y install build-essential devscripts dh-make fakeroot dpkg-dev debhelper libdbi-perl libmysqlclient-dev zlib1g-dev
RUN apt-get -y install libmodule-install-perl

RUN wget http://archive.ubuntu.com/ubuntu/pool/universe/libd/libdbd-mysql-perl/libdbd-mysql-perl_4.033.orig.tar.gz
RUN wget http://archive.ubuntu.com/ubuntu/pool/universe/libd/libdbd-mysql-perl/libdbd-mysql-perl_4.033-1build2.debian.tar.xz

RUN git clone https://github.com/yoshinorim/mha4mysql-node
WORKDIR mha4mysql-node
RUN perl Makefile.PL
RUN make
RUN make install
```
### 1.MHA（vvdocker/manager）
```

FROM vvdocker/base-perl

RUN apt-get install -y libconfig-tiny-perl liblog-dispatch-perl libparallel-forkmanager-perl

# MHA manager
RUN apt-get install -y libconfig-tiny-perl liblog-dispatch-perl libparallel-forkmanager-perl
RUN git clone https://github.com/yoshinorim/mha4mysql-manager.git
WORKDIR mha4mysql-manager
RUN perl Makefile.PL
RUN make
RUN make install

RUN mkdir -p /var/log/masterha/mysql/
RUN cat /usr/local/share/perl/5.20.2/MHA/ServerManager.pm

RUN cp -p samples/scripts/master_ip_failover /usr/local/bin/
RUN chmod 555 /usr/local/bin/master_ip_failover
RUN mkdir -p /etc/masterha/conf
#サンプル----------------------------------------
ADD test.conf /etc/mha.conf
#----------------------------------------------
```
### 2.node(vvdocker/node)
```
FROM vvdocker/base-perl
RUN mkdir work
RUN cp libdbd-mysql-perl_4.033.orig.tar.gz work
WORKDIR work
RUN tar xf libdbd-mysql-perl_4.033.orig.tar.gz
RUN mv DBD-mysql-4.033 libdbd-mysql-perl_4.033
RUN tar xf ../libdbd-mysql-perl_4.033-1build2.debian.tar.xz -C libdbd-mysql-perl_4.033
RUN cd libdbd-mysql-perl_4.033 && dpkg-buildpackage -us -uc
RUN dpkg -i libdbd-mysql-perl_4.033-1build2_amd64.deb

#mysql5.6
RUN wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.14-debian6.0-x86_64.deb
RUN dpkg -i mysql-5.6.14-debian6.0-x86_64.deb
RUN apt-get -y upgrade
RUN apt-get install -y libaio1 m4

RUN install -d /data/mysql
RUN /opt/mysql/server-5.6/scripts/mysql_install_db --datadir=/data/mysql
ENV PATH "/opt/mysql/server-5.6/bin:$PATH"
ENV MANPATH "/opt/mysql/server-5.6/man:$MANPATH"
RUN mysql --version

```
### これらをdocker-hubあたりにpushしておく
```
$ docker push vvdocker/manager
$ docker push vvdocker/node
```

## 実行

+ 実際に環境を作りたいときはここからできるようにと

### docker-compose.yml
```
mha:
  image: vvdocker/manager:dev22
  links:
    - master1:master_1
    - master2:master_2
    - slave1:slave_1
    - slave2:slave_2
  command: masterha_check_repl --conf=/etc/mha.conf && masterha_manager --conf=/etc/mha.conf

master1:
  build: master
  environment:
    - MYSQL_USER=repl
    - MYSQL_PASSWORD=replpass
    - MYSQL_ROOT_PASSWORD=root

master2:
  build: slave
  environment:
    - MYSQL_USER=repl
    - MYSQL_PASSWORD=replpass
    - MYSQL_ROOT_PASSWORD=root
  links:
    - master1:master_1

slave1:
  build: slave
  environment:
    - MYSQL_USER=repl
    - MYSQL_PASSWORD=replpass
    - MYSQL_ROOT_PASSWORD=root
  links:
    - master1:master_1
    - master2:master_2

slave2:
  build: slave
  environment:
    - MYSQL_USER=repl
    - MYSQL_PASSWORD=replpass
    - MYSQL_ROOT_PASSWORD=root
  links:
    - master1:master_1
    - master2:master_2
```

### master(vvdoker/master)
```
FROM vvdocker/node

# my.cnf
COPY conf.d/my.cnf.in my.cnf.in
RUN m4 -DMASTERID=`date +%s` my.cnf.in > /etc/mysql/conf.d/my.cnf

COPY init.d/startup.sql /docker-entrypoint-initdb.d/startup.sql
```

#### startup.sql
```
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY 'replpass';
FLUSH PRIVILEGES;
```

#### my.cnf.in
```
[mysqld]                           
~~~~~~~~~~省略~~~~~~~~~~~~~~~~
server-id               = MASTERID
log_bin                 = /var/log/mysql/mysql-bin.log
bind-address            = 0.0.0.0
~~~~~~~~~~省略~~~~~~~~~~~~~~~~
```

### slave(vvdocker/slave)
```
FROM vvdocker/node

# my.cnf
COPY conf.d/my.cnf.in my.cnf.in
RUN m4 -DSERVERID=`date +%s` my.cnf.in > /etc/mysql/conf.d/my.cnf

COPY init.d/startup.sql /docker-entrypoint-initdb.d/startup.sql
```

#### startup.sql
```
CHANGE MASTER TO MASTER_HOST='master_1', MASTER_USER='repl',MASTER_PASSWORD='replpass', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=120;
FLUSH PRIVILEGES;
```

#### my.cnf.in
```
[mysqld]                           
~~~~~~~~~~省略~~~~~~~~~~~~~~~~
server-id               = SERVERID
log_bin                 = /var/log/mysql/mysql-bin.log
bind-address            = 0.0.0.0
~~~~~~~~~~省略~~~~~~~~~~~~~~~~
```

## 参考サイト
- http://blog.takanabe.tokyo/2016/05/04/2410/
- http://www.ossnews.jp/oss_info/MySQL_MHA