1. MySQLの高可用性(HA)構成パターンの比較
本番環境でデータベースサーバーを1台のみ運用することは、いわば時限爆弾を抱えているようなものです。ディスクの高負荷やネットワークの輻輳、OSパッチ適用のための再起動だけでも、サービス全体が即座に停止してしまいます。99.9%のSLA(稼働率)を維持するため、インフラチームは通常、以下の4つのアプローチから選択します。
- DNSフェイルオーバー: 1つのDNSレコードに複数のIPを紐付け、障害時にIPを切り替える手法。
- 単一HAProxy(Single LB): MySQLクラスタの前面に1台のHAProxyを配置し、接続のバランシングやヘルスチェックを行う手法。
- Keepalived + HAProxy(Virtual IPを用いたActive-Passive構成): VRRP(Virtual Router Redundancy Protocol)プロトコルを介して2台のHAProxyノードを並行稼働させ、Virtual IP(VIP)を共有する手法。Activeノードがダウンすると、VIPが自動的にPassiveノードへフェイルオーバーします。
- MySQL InnoDB Cluster / Galera Cluster: マルチマスターの同期クラスタであり、データベースエンジン層で新しいノードを自動選出する手法。
2. 各ソリューションのメリット・デメリット
万能なソリューションは存在しません。要件やシステム規模に適した手法を選択することが重要です。
DNSフェイルオーバー
- メリット: 設定が非常に容易で、複雑なクラスタ管理ツールの追加導入が不要。
- デメリット: クライアント側のTTLやDNSキャッシュに完全に依存します。サーバー停止時、クライアントが新しいIPを認識するまでに通常5〜15分(ISPによっては数時間)かかり、長時間のダウンタイムが発生します。
単一HAProxy
- メリット: インテリジェントなルーティングが可能で、TCP層(レイヤー4)での正確なMySQLヘルスチェックを実行できます。
- デメリット: 単一障害点(SPOF)となります。背後のMySQLクラスタが正常に稼働していても、HAProxyがダウンするとアプリケーション全体の接続が切断されます。
MySQL InnoDB Cluster / Galera Cluster
- メリット: リアルタイムでデータを同期し、ノード間の完全な整合性を保証します。
- デメリット: 運用が非常に複雑でリソース消費も大きくなります。書き込みトラフィックが高い環境ではデッドロックが発生しやすくなります。また、スプリットブレイン対策として最低3ノードが必要です。
Keepalived + HAProxy(Virtual IP)
- メリット: フェイルオーバーが極めて高速(1〜2秒未満)。HAProxyの単一障害点問題を完全に解消します。非常に軽量で、従来のMySQL Master-Replica構成とも相性抜群です。
- デメリット: VRRPプロトコルを正常に機能させるため、内部ネットワーク環境がマルチキャストまたはユニキャストのパケット転送をサポートしている必要があります。
3. 中小規模システムにKeepalived + HAProxyが最適な理由
中小規模のシステムにおいて、Keepalived + HAProxy構成はコストパフォーマンスに極めて優れています。3〜5ノードの大規模なクラスタを管理・維持する必要はありません。バックエンドアプリケーションは単一の接続先であるVirtual IP(VIP)のみを指定すれば十分です。
ノードの監視、クエリのルーティング、障害サーバーの切り離しはシステムが自動的に処理します。実際、約1,500 QPSを処理するMySQL環境において、このアーキテクチャではメインノードの障害時に約800msでフェイルオーバーを完了し、ユーザー側の502/504エラーを完全に防ぐことができました。
4. ステップバイステップ導入手順
今回は、同一LAN内にある2台のUbuntu/Debianサーバーを使用した実践例を紹介します。
- Node 1(Primary LB / MySQL Master): IP
192.168.1.10 - Node 2(Backup LB / MySQL Replica): IP
192.168.1.11 - Virtual IP(共有VIP):
192.168.1.100(アプリケーションはこのIPに接続)
ステップ1:MySQLヘルスチェック用ユーザーの作成
両方のノードでMySQLにログインし、HAProxyのヘルスチェック専用ユーザーを作成します。このユーザーにデータアクセスの権限は不要です。
mysql -u root -p -e "CREATE USER 'haproxy_check'@'%' IDENTIFIED BY ''; FLUSH PRIVILEGES;"
ステップ2:HAProxy、Keepalivedおよびユーティリティツールのインストール
両方のサーバーでインストールコマンドを実行します。
sudo apt update
sudo apt install -y haproxy keepalived psmisc
ステップ3:HAProxyの設定
両ノードの /etc/haproxy/haproxy.cfg を開き、ポート3306のプロキシ設定を追加します。
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
defaults
log global
mode tcp
option tcplog
option dontlognull
retries 3
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend mysql_front
bind *:3306
mode tcp
default_backend mysql_back
backend mysql_back
mode tcp
option mysql-check user haproxy_check
server db01 192.168.1.10:3306 check inter 2000 rise 2 fall 3
server db02 192.168.1.11:3306 check backup inter 2000 rise 2 fall 3
HAProxyを再起動し、自動起動を有効化します。
sudo systemctl restart haproxy
sudo systemctl enable haproxy
ステップ4:Virtual IPを管理するKeepalivedの設定
まず、ネットワークインターフェースがまだそのIPを保持していなくても、カーネルがVIPにバインドできるように設定します。
echo "net.ipv4.ip_nonlocal_bind=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
両サーバーの /usr/local/bin/check_haproxy.sh にHAProxyプロセスの監視スクリプトを作成します。
cat << 'EOF' | sudo tee /usr/local/bin/check_haproxy.sh
#!/bin/bash
killall -0 haproxy
EOF
sudo chmod +x /usr/local/bin/check_haproxy.sh
Node 1(Master) の /etc/keepalived/keepalived.conf を設定します。
vrrp_script check_haproxy {
script "/usr/local/bin/check_haproxy.sh"
interval 2
weight 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 101
advert_int 1
authentication {
auth_type PASS
auth_pass SecretHAProxyPass123
}
virtual_ipaddress {
192.168.1.100/24 dev eth0
}
track_script {
check_haproxy
}
}
Node 2(Backup) の /etc/keepalived/keepalived.conf を設定します(priorityを100に下げます)。
vrrp_script check_haproxy {
script "/usr/local/bin/check_haproxy.sh"
interval 2
weight 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass SecretHAProxyPass123
}
virtual_ipaddress {
192.168.1.100/24 dev eth0
}
track_script {
check_haproxy
}
}
両サーバーでKeepalivedサービスを起動・有効化します。
sudo systemctl restart keepalived
sudo systemctl enable keepalived
ステップ5:実際のフェイルオーバー動作確認
Node 1で現在のIP割り当てを確認します。
ip addr show eth0
Virtual IP 192.168.1.100 がNode 1の eth0 インターフェースに割り当てられていることが確認できます。ここで障害をシミュレートするため、Node 1のHAProxyサービスを停止してみます。
sudo systemctl stop haproxy
Node 2のターミナルを開き、再度IPを確認します。
ip addr show eth0
Virtual IP 192.168.1.100 が瞬時にNode 2へと引き継がれました。192.168.1.100:3306 に接続しているアプリケーションは、手動での対応やソースコードの設定変更を行うことなく、クエリの送受信を継続できます。

