HaProxyでのMySQL冗長化

前提

Masterサーバ、Slaveサーバ間でレプリケーションが組まれている。ちなみにmysqlのバージョンは5.7。

やりたいこと

WordPressサイトへのアクセスが来たら普段はMasterサーバのMySQLにのみ向かうようにし、Masterサーバダウン時にはSlaveサーバのリードオンリーMySQLに向かうようにする。
これにより、Masterダウン時にも閲覧のみは可能となるようにしておく。

作業記録

haproxyのインストール

#haproxy
yum install haproxy

ログの出力設定

rsyslogのlocalファシリティを使うことがポイント。
デフォルト設定ではlocal2を指定するようなのでそこはいじらない。
また、UDPを受けられるように設定しておく。

cp -ai /etc/rsyslog.conf /etc/rsyslog.conf.org
vi /etc/rsyslog.conf
--- 以下を追記
$ModLoad imudp
$UDPServerRun 514
# haproxy setting
local2.*                                                /var/log/haproxy.log
---
systemctl restart rsyslog

option mysql-check用のMySQLユーザを作成

10.0.3.183、10.0.1.72は自分の環境に合わせて置き換えてください。
haproxyサーバのipアドレスになります。
MasterサーバもSlaveサーバも自身がhaproxyサーバとなるので自分のローカルipアドレスを指定しています。
ここは%でもいけましたが、このユーザはパスワードなしでログインできてしまうので制限をかけないとセキュリティ上よろしくないかも。
あと、2回同じコマンド打っているように見えますが、一回目はパスワードを半角スペースにしてあります。
最初からパスワードなしのユーザを作成しようとしてもエラーが出てしまうのでそうやっています。

GRANT ALL PRIVILEGES ON *.* TO 'haproxy'@'10.0.3.183' IDENTIFIED BY ' ';
GRANT ALL PRIVILEGES ON *.* TO 'haproxy'@'10.0.3.183' IDENTIFIED BY '';
GRANT ALL PRIVILEGES ON *.* TO 'haproxy'@'10.0.1.72' IDENTIFIED BY ' ';
GRANT ALL PRIVILEGES ON *.* TO 'haproxy'@'10.0.1.72' IDENTIFIED BY '';

haproxy.cfgの編集

cp -ai /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.org
vi /etc/haproxy/haproxy.cfg
-----
global
    log 127.0.0.1 local2 notice
    chroot /var/lib/haproxy
    pidfile /var/run/haproxy.pid
    maxconn 4000
    user haproxy
    group haproxy
    daemon
    stats socket /var/lib/haproxy/stats
defaults
    mode tcp
    log global
    retries 3
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout check 10s
    maxconn 3000
listen mysql
    bind 0.0.0.0:3307
    mode tcp
    option mysql-check user haproxy
    balance roundrobin
    server master 10.0.3.183:3306 check
    server slave 10.0.1.72:3306 backup
-----
systemctl start haproxy
systemctl enable haproxy

設定解説

https://cbonte.github.io/haproxy-dconv/1.7/configuration.html
ざっくり解説。

global「グローバル」セクションのパラメーターはプロセス全体に適用される。
log 127.0.0.1 local2 notice前述のとおり。ログを吐きだす為の設定。
chroot /var/lib/haproxyこのパスにchrootしてからサーバープロセスを稼動させる。
pidfile /var/run/haproxy.pidプロセスのIDを格納するファイルのパス名。
maxconn 4000最大同時接続数。frontend の接続の合計。
user haproxyプロセスを実行するユーザー。
group haproxyプロセスを実行するグループ。
daemonプロセスフォークをバックグラウンドにする。推奨モード。
stats socket /var/lib/haproxy/statsこのソケットへの接続は、さまざまな統計出力を返し、さらに一部のコマンドを発行して一部のランタイム設定を変更できるようにします
defaultsglobalセクション以外のセクションにおけるパラメータの「デフォルト値」を指定できるセクション。
mode tcpインスタンスの実行モードまたはプロトコルを設定する。インスタンスは純粋なTCPモードで動作します。
log globalglobalセクションで指定したログ設定を使用する。
retries 3接続失敗後にサーバーで実行する再試行回数を設定する
timeout connect 10sサーバーへの接続試行が成功するまで待機する最大時間を設定します。
timeout client 1mクライアント側の最大非アクティブ時間を設定します。
timeout server 1mサーバー側の最大非アクティブ時間を設定します。
timeout check 10s接続確立後のタイムアウト時間を設定
maxconn 3000最大同時接続数。frontend ごとに適用される。
listen mysqlフロントエンドとバックエンドをまとめて設定できるセクション
bind 0.0.0.0:3307フロントエンドで1つまたは複数のリスニングアドレスやポートを定義します。
mode tcpインスタンスの実行モードまたはプロトコルを設定する。インスタンスは純粋なTCPモードで動作します
option mysql-check user haproxyサーバーのテストにMySQLヘルスチェックを使用する。MySQLへの接続時に使用されるユーザー名。
balance roundrobin負荷分散アルゴリズムを定義
server master 10.0.3.183:3306 checkバックエンドでサーバーを宣言する。利用可能なサーバを指定。
server slave 10.0.1.72:3306 backupバックエンドでサーバーを宣言する。他のすべての非バックアップサーバーが利用できない場合に分散する。

補足

「http」モードと「tcp」モードというのがあり、今回はtcpを指定している。
HTTP関連以外はtcpモードになるだろう。
フロントエンド、バックエンドという概念も重要だ。
フロントエンドはHAProxyによる待ち受けなどの処理を行う。バックエンドは転送先のサーバーを指定する。
今回はフロントエンドとバックエンドをlistenセクションで同時に書いているが、分けるのもありらしい。

テストコマンド

MySQLを片系ダウンさせてもアクセスできることが確認できればOKです。
MySQLのDBユーザ作成の際、ホスト名は”%”などにしてください。
“localhost”で作成したDBユーザでは接続できません。

mysql -u <DBユーザ名> -p -h 127.0.0.1 -P 3307
mysql -u <DBユーザ名> -p -h 10.0.3.183 -P 3307
mysql -u <DBユーザ名> -p -h 10.0.1.72 -P 3307

wp-config.php

WordPressを冗長化する際はwp-config.phpの接続先を変えることをお忘れなく。

/** MySQL のホスト名 */
define( 'DB_HOST', '127.0.0.1:3307' );