フェイルオーバー時に、アプリサーバからMySQLへの接続先を変更する方法として、”アプリサーバへ /etc/hosts を rsync で配布する” といった方法をとります。
いままでは、MySQLサーバのIPアドレスの付け替えや、HAProxyの設定変更を自動で行う、などといった方法がありましたが、これは、敷居低めで実装できるのが嬉しいです。
動作イメージは下のようになります。
mysql1が壊れたとき、mysql2が自動でマスターに昇格してサービスを継続します。
詳しく説明します。
app1、app2の /etc/hosts には、MySQLマスターのホスト名 mysql-master.myservice.com と mysql1 のIPアドレスを紐づける記述しておきます。
app1、app2のアプリケーションは、このホスト名 mysql-master.myservice.com 宛にMySQL接続をします。
フェイルオーバー時には、mysql-master.myservice.com の IPアドレスを mysql2 のものに変更した /etc/hosts を rsync で差し替えます。
サーバIDとIPアドレスはこのようになっているとします。
app1(100.100.100.1) :アプリケーション1 + MHAマネージャ
app2(100.100.100.2) :アプリケーション2
mysql1(200.200.200.1) :MySQLマスタ
mysql2(200.200.200.2) :MySQLスレーブ
試験環境は、CentOS 6.5、MySQL 5.6です。
MySQLは、既にインストールされている状態ではじめます。
MHAマネージャは、app1サーバにセットアップします。
◆ 事前準備
1) sshのrootユーザで各サーバにログインできるようにしておく。
app1 -> app1, app2, mysql1, mysql2
mysql1 -> mysql2
mysql2 -> mysql1
2) MySQLの設定を編集(mysql1, mysql2)
/etc/my.cnfの[mysqld]に、log-bin、server-idを設定。
default-character-setの設定はオフにしておきます。
vim /etc/my.cnf
[client]
#default-character-set=utf8
3) MySQL接続ユーザ、レプリケーション用ユーザを作る(mysql1)
MHAマネージャから、rootユーザでMySQLアクセスできるようにしておく。
mysql1 -> mysql2 レプリケーションの為のユーザを作る。
4) MySQLマスタ -> スレーブのレプリケーションを構築しておく。(mysql1, mysql2)
※ 準同期レプリケーションを設定しておくと、レプリケーションの安全性が高まります。
参考) 準同期レプリケーションの実装方法 - サーバサイドWiki - Confluence
※ MySQL 5.6では、mysql2の/var/lib/mysql/auto.cnfを削除してrestartしておく。
(masterとslaveとで、server-uuidがかぶっていなければOK。)
※ 今回は、スレーブにread_onlyは付けないでおきました。
5) MySQLホスト名を /etc/hosts に記述する。(app1, app2)
# vim /etc/hosts
---
200.200.200.1 mysql-master.myservice.com
---
アプリケーションからは、mysql-master.myservice.com 宛に接続するようにしておきましょう。
◆ MHAのインストール
1) mysql1, mysql2サーバに、MHAノード(mha4mysql-node)をインストール
# cd /usr/local/src
# yum -y install epel-release
# curl -o mha4mysql-node-0.56-0.el6.noarch.rpm "http://www.mysql.gr.jp/frame/modules/bwiki/index.php?plugin=attach&pcmd=open&file=mha4mysql-node-0.56-0.el6.noarch.rpm&refer=matsunobu"
# yum localinstall mha4mysql-node-0.56-0.el6.noarch.rpm
# rpm -ql mha4mysql-node
2) app1サーバに、MHAマネージャ(mha4mysql-manager)をインストール
※ 依存ライブラリを先にインストールする必要があります。先にMHAノードのインストールをします。
# cd /usr/local/src
# yum -y install epel-release
# curl -o mha4mysql-node-0.56-0.el6.noarch.rpm "http://www.mysql.gr.jp/frame/modules/bwiki/index.php?plugin=attach&pcmd=open&file=mha4mysql-node-0.56-0.el6.noarch.rpm&refer=matsunobu"
# curl -o mha4mysql-manager-0.56-0.el6.noarch.rpm "http://www.mysql.gr.jp/frame/modules/bwiki/index.php?plugin=attach&pcmd=open&file=mha4mysql-manager-0.56-0.el6.noarch.rpm&refer=matsunobu"
# yum localinstall mha4mysql-node-0.56-0.el6.noarch.rpm
# yum localinstall mha4mysql-manager-0.56-0.el6.noarch.rpm
# rpm -ql mha4mysql-manager
◆ MHAの設定ファイルを用意
app1サーバで用意します。
設定ファイル類を置くディレクトリを作成
# mkdir /usr/share/masterha
ログファイル用のディレクトリを作成
# mkdir -p /var/log/masterha/mysql/
MHA設定ファイルを書く。
# vim /usr/share/masterha/masterha_default.cnf
---
[server default]
# mysql user and password
user=root
password=xxxxxxxxxxxxxxxxxxxxxxxxxxxx
ssh_user=root
# working directory on the manager
manager_workdir=/var/log/masterha/mysql
# working directory on MySQL servers
remote_workdir=/var/log/masterha/mysql
# MySQL TCP connection check
ping_type=CONNECT
# failover script
master_ip_failover_script=/usr/share/masterha/master_ip_failover.sh
master_ip_online_change_script=/usr/share/masterha/master_ip_failover.sh
[server1]
hostname=200.200.200.1
[server2]
hostname=200.200.200.2
candidate_master=1
---
◆ フェイルオーバー時に実行するスクリプトを用意
app1サーバで用意します。
※ rootによるssh疎通を要チェックしておきましょう。
rsyncで /etc/hosts を配布するスクリプトを設置します。
このスクリプトが、フェイルオーバー時に実行されます。
# vim /usr/share/masterha/master_ip_failover.sh
---
#!/bin/bash
DIR=/usr/share/masterha
if [ "$1" = "--command=start" ]; then
# app1
rsync -avz ${DIR}/hosts 100.100.100.1:/etc/hosts
# app2
rsync -avz ${DIR}/hosts 100.100.100.2:/etc/hosts
fi
---
# chmod 755 /usr/share/masterha/master_ip_failover.sh
フェイルオーバー時に app1,app2 サーバへ配布する /etc/hosts ファイルを設置します。
mysql-master.myservice.com のIPアドレスを mysql2のモノにします。
# vim hosts
mysql-master.myservice.com のIPアドレスを mysql2のモノにします。
---
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
200.200.200.2 mysql-master.myservice.com
---
◆ MHAをスタート
app1サーバでMHAを実行します。
sshコネクションをチェック
# masterha_check_ssh --conf=/usr/share/masterha/masterha_default.cnf
MySQLコネクションをチェック
# masterha_check_repl --conf=/usr/share/masterha/masterha_default.cnf
MHAマネージャの起動を試す(フォアグランド)
# masterha_manager --conf=/usr/share/masterha/masterha_default.cnf
[Ctrl + c]で抜けます。
MHAマネージャの起動(バックグランド)
# nohup masterha_manager --conf=/usr/share/masterha/masterha_default.cnf < /dev/null > /var/log/masterha/mysql/manager.log 2>&1 &
# ps aux | grep masterha_manager
# tail -f /var/log/masterha/mysql/manager.log
---
FriJan 24 23:35:09 2014 - [info] Ping(CONNECT) succeeded, waiting until MySQL doesn't respond..
---
上記のように出ているでしょうか?出ていたらおkです。
mysql1のmysqlをストップしたり、アクセス制限を掛けたりしてフェイルオーバーできるかチェックしてみましょう。
※ MHAマネージャを停止したいときは?以下のコマンドを叩きます。
# masterha_stop --conf=/usr/share/masterha/masterha_default.cnf
※ フェイルオーバーを実行した後は下記のファイルを削除してから、MHAを立ち上げる必要があります。
成功していた場合
# rm /var/log/masterha/mysql/masterha_default.failover.complete
失敗していた場合
# rm /var/log/masterha/mysql/masterha_default.failover.error
◆ MHAマネージャをデーモン化
Upstart を使って、MHAマネージャをデーモン化してみます。
なにかしらの原因で、MHAマネージャが落ちたときに自動で立ち上げ直してくれます。
一般的には、daemontoolsが使われていますが、Upstartの方がデフォルトで入っているし、らくちんです。
ここでは "respawn limit"によりプロセスの再起動回数を制限します。 10秒間に5回以上再起動が起きた場合には、自動的に停止され、再起動されなくなります。
設定ファイルを用意
# vim /etc/init/mha.conf
---
description "MySQL-MHA"
author "Takeshi Yako <yako.takeshi@googlemail.com>"
start on runlevel [2345]
stop on runlevel [016]
chdir /usr/share/masterha/
respawn
respawn limit 5 10
exec /usr/bin/masterha_manager --conf=/usr/share/masterha/masterha_default.cnf >> /var/log/masterha/mysql/manager.log 2>&1
---
設定を反映します。
# initctl reload-configuration
# initctl list | grep mha
起動します。
# initctl start mha
確認。
# initctl list | grep mha
# ps auxf | grep masterha_manager
# tail -f /var/log/masterha/mysql/manager.log
停止するときは?
# initctl stop mha
参考)Upstart を使ってお手軽 daemon 化
http://heartbeats.jp/hbblog/2013/02/upstart-daemon.html
◆ まとめ
MySQL for MHAをセットアップして、/etc/hostsや、rsyncなどの枯れたモノを使ってMySQLをフェイルオーバできるようにしました。
インフラ構成が比較的ちいさなサービスなどで、”MySQLのHA構成が欲しい”という要望があったときに、使えたりしそうです。
試してみてください。
試してみてください。