Keepalivedで実現する高可用性構成:CentOS/RHELにおけるIPフェイルオーバーの設定方法
本記事では、企業LANからインターネットへアクセスするための2台のSquidプロキシサーバー(Linux)を使用した、高可用性(HA)フェイルオーバー構成について解説します。フェイルオーバー構成を構築するために、keepalivedを使ってHAクラスターを作成します。
HAクラスターとは、グループ内のいずれかのサーバーにハードウェアやソフトウェアの障害が発生した場合でも、アプリケーションのダウンタイムを最小限に抑えられるよう、冗長性を組み込んだサーバーの集合体です。この定義に基づくと、HAクラスターを正しく動作させるには、以下の要素を実装する必要があります。
- サーバーの状態監視(ヘルスチェック)
- サーバー障害発生時のリソース自動切り替え
keepalivedは、この両方の機能を提供します。keepalivedはLinuxシステム上で動作するシステムデーモンで、サービスのフェイルオーバーと負荷分散を可能にします。フェイルオーバーは、メインサーバーに障害が発生した際に仮想IPアドレス(フローティングIP)を別のサーバーへ切り替えることで実現されます。サーバー間でIPアドレスを自動的に切り替えるために、keepalivedはVRRP(Virtual Router Redundancy Protocol:仮想ルータ冗長プロトコル)を使用します。
VRRPの基本原理
まず、VRRPに関する基本的な理論と主要な用語を確認しておきましょう。
- VIP(Virtual IP) — 仮想IPアドレス。障害発生時にサーバー間で自動的に切り替わるIPアドレスです。
- Master(マスター) — 現在VIPがアクティブになっているサーバーです。
- Backup(バックアップ) — マスターに障害が発生した際にVIPが切り替わる先のサーバーです。
- VRID(Virtual Router ID) — 仮想ルーターID。同じ仮想IP(VIP)を共有するサーバー群は「仮想ルーター」と呼ばれる論理的なグループを形成し、その一意の識別子は1〜255の範囲で指定します。1台のサーバーが複数のVRIDに同時に所属することも可能ですが、各VRIDには固有の仮想IPアドレスが必要です。
基本的な動作アルゴリズム
- マスターサーバーは一定間隔でVRRPパケット(ハートビート)をマルチキャストアドレス224.0.0.18宛てに送信し、すべてのスレーブサーバーはこのアドレスを監視しています。マルチキャストとは、1つの送信元から複数の受信者へデータを送る通信方式のことです。
ヒント: サーバーをマルチキャストモードで動作させるには、ネットワーク機器がマルチキャストトラフィックに対応している必要があります。 - スレーブサーバーがハートビートパケットを受信しなくなると、マスター選出プロセスが開始されます。優先度に基づいて自身がマスターになると、そのサーバーはVIPを有効化し、gratuitous ARP(無償ARP)を送信します。gratuitous ARPは特殊なARP応答の一種で、ネットワークスイッチのMACテーブルを更新し、仮想IPアドレスの所有者が変更されたこと、およびトラフィックの転送先となる新しいMACアドレスをネットワーク全体に通知する役割を果たします。
CentOSへのkeepalivedのインストールと設定
ここでは、CentOS 7が稼働しSquidがインストール済みの2台のLinuxサーバー(proxy-serv01とproxy-serv02)に、keepalivedをインストールして設定します。今回の構成では、最もシンプルな負荷分散方式であるラウンドロビンDNSを使用します。この方式では、1つのDNS名に対して複数のIPアドレスを登録し、クライアントはそれらのアドレスを順番に取得します。そのため、1つのDNS名(proxy-serv)に対して2つの仮想IPアドレスを登録する必要があります。ネットワーク構成図は以下の通りです。
各Linuxサーバーには2つの物理ネットワークインターフェースがあります。eth1にはグローバル(ホワイト)IPアドレスが割り当てられ、eth0はローカルネットワークに接続されています。
実際の(リアル)IPアドレスとして以下を使用します。
192.168.2.251 — proxy-server01用 192.168.2.252 — proxy-server02用
障害発生時にサーバー間で自動的に切り替わる仮想IPアドレスとしては、以下を使用します。
192.168.2.101 192.168.2.102
重要: VRRPを設定する際、実際のサーバーIPアドレスを仮想IPとして使用してはいけません。サーバーに障害が発生すると、そのアドレスは次のサーバーへ移行しますが、フェイルバック後に最初のサーバーがネットワークから孤立してしまう可能性があるためです。これは、IPアドレスを取り戻すためにはサーバーがVRRPパケットをネットワークに送信する必要があるものの、送信元となるIPアドレスが存在しないためです。
両方のサーバーにyumパッケージマネージャー(CentOS 8以降ではdnf)を使ってkeepalivedをインストールします。
# yum install keepalived
両サーバーへのインストール完了後、keepalivedの設定ファイルを編集します。
# nano /etc/keepalived/keepalived.conf
両サーバーで異なるパラメータを設定します。主な設定項目は以下の通りです。
- vrrp_instance <name> — VRRPインスタンスを定義するセクションです。
- state <MASTER|BACKUP> — 起動時のノードの初期状態を指定します。
- interface <interface name> — VRRPが動作するインターフェースを指定します。
- virtual_router_id <0〜255の数値> — VRRPインスタンスの一意な識別子です。すべてのサーバーで同じ値である必要があります。
- priority <0〜255の数値> — サーバーの優先度を設定します。より高い優先度を持つサーバーがMASTERになります。
- virtual_ipaddress — MASTER状態のサーバーでアクティブになる仮想IPアドレスのブロックです。VRRPインスタンス内の全サーバーで同じ内容である必要があります。
注意: VRRP設定の例ではauthenticationオプションが使われているケースをよく見かけますが、keepalivedのドキュメントによれば、認証機能は2004年のRFC3768仕様においてVRRPv2から削除されました。実際のセキュリティ効果がなかったためです。この設定オプションの使用は推奨されません。
現在のネットワーク構成でマルチキャストが使用できない場合は、keepalivedが提供するユニキャストオプションを利用できます。ユニキャストモードでは、VRRPハートビートパケットがリストに従って各サーバーへ直接送信されます。ユニキャストを使用するには、以下のオプションが必要です。
- unicast_src_ip — VRRPパケットの送信元アドレス
- unicast_peer — VRRPパケットの送信先となるサーバーIPアドレスのブロック
この構成では、proxy_ip1とproxy_ip2という2つのVRRPインスタンスを定義します。通常運用時には、proxy-serv01が仮想IP 192.168.2.101のMASTERとなり、192.168.2.102のBACKUPとなります。逆にproxy-serv02は、仮想IP 192.168.2.102のMASTERであり、192.168.2.101のBACKUPとなります。
サーバーでファイアウォールが有効になっている場合は、iptablesでマルチキャストトラフィックとVRRPを許可するルールを追加する必要があります。
# iptables -A INPUT -i eth0 -d 224.0.0.0/8 -j ACCEPT # iptables -A INPUT -p vrrp -i eth0 -j ACCEPT
両サーバーでkeepalivedサービスの自動起動を有効にし、サービスを開始します。
# systemctl enable keepalived # systemctl start keepalived
keepalivedの起動後、設定ファイルに記述された仮想IPアドレスがインターフェースに割り当てられます。各サーバーのeth0の現在のIPアドレスを確認してみましょう。
# ip a show eth0
これで、proxy-serv01には192.168.2.101と192.168.2.251が、proxy-serv02には192.168.2.102と192.168.2.252が割り当てられているはずです。
keepalivedでアプリケーションやインターフェースのヘルスチェックを行う方法
VRRPプロトコル自体がサーバーの状態監視を提供します。例えば、物理サーバーの障害やスイッチ・サーバーのNICポート障害などには有効です。しかし、それ以外の問題も発生する可能性があります。
- プロキシサーバー(またはその他のアプリケーション)のエラー — クライアントがサーバーの仮想アドレスにアクセスすると、ブラウザ上で「プロキシサーバーが利用できない」というエラーメッセージが表示されます。
- 2つ目のインターフェース経由のインターネット接続障害 — クライアントがサーバーの仮想アドレスにアクセスしても、接続を確立できずエラーになります。
こうした状況に対応するために、以下のオプションを使用します。
- track_interface — インターフェースの状態を監視し、リスト内のいずれかのインターフェースがDOWNになると、該当するVRRPインスタンスをFAULT状態に設定します。
- track_script — スクリプトを使ってHAアプリケーションのヘルスチェックを行います。チェック成功時は0を、失敗時は1を返すスクリプトを使用します。
設定を更新し、eth1インターフェースの監視を追加しましょう(デフォルトでは、VRRPインスタンスは自身がバインドされているインターフェース、つまり現構成ではeth0のみをチェックします)。
track_interface {
eth1
}
track_scriptディレクティブは、vrrp_scriptブロックで定義されたパラメータに従ってスクリプトを実行します。書式は以下の通りです。
vrrp_script <name> {
script <"実行ファイルへのパス">
interval <秒数> — スクリプトの実行周期(デフォルトは1秒)
fall <回数> — FAULT状態へ移行するまでに、スクリプトがゼロ以外の値を返した回数
rise <回数> — FAULT状態から復帰(フェイルバック)するまでに、スクリプトがゼロを返した回数
timeout <秒数> — スクリプトの結果を待つ時間(時間切れの場合は非ゼロ値を返したものとみなされる)
weight <数値> — FAULT状態になった際にサーバー優先度から減算される値。デフォルトは0で、この場合fallパラメータで指定した回数だけスクリプトが失敗するとサーバーはFAULT状態になる
}
Squidプロキシのヘルスチェックを設定してみましょう。次のコマンドで、squidプロセスが稼働しているかどうかを確認できます。
# squid -k check
3秒ごとに実行されるvrrp_scriptを作成します。このブロックはvrrp_instanceブロックの外側で定義します。
vrrp_script chk_squid_service {
script "/usr/sbin/squid -k check"
interval 3
}
このスクリプトを監視対象として、両方のvrrp_instanceブロックに追加します。
track_script {
chk_squid_service
}
これで、Squidに障害が発生した場合、仮想IPアドレスがもう一方のサーバーへ切り替わります。
また、サーバーの状態が変化した際に実行する追加アクションを指定することもできます。
Squidがすべてのインターフェースからの接続を受け付ける設定(http_port 0.0.0.0:3128など)になっていれば、仮想IPアドレスが切り替わっても問題は発生せず、Squidは新しいアドレス宛ての接続も受け付けます。しかし、特定のIPアドレスを指定している場合はどうでしょうか。
http_port 192.168.2.101:3128 http_port 192.168.2.102:3128
この場合、システムに新しいアドレスが出現しても、Squidはそれを認識せず、クライアントからのリクエストをそのアドレスでリッスンしません。仮想IPアドレスの切り替え時に追加の処理が必要なケースに対応するため、keepalivedではサーバーの状態が変化したとき(MASTERからBACKUPへ、またはその逆)にスクリプトを実行できるようになっています。これは以下のオプションで実装します。
notify "実行ファイルへのパス"
障害発生時のkeepalivedフェイルオーバーのテスト
仮想IPの設定が完了したら、障害が正しく処理されることを確認しましょう。最初のテストは、サーバー障害のシミュレーションです。proxy-serv01のeth0を無効化すると、VRRPハートビートパケットの送信が停止します。すると、proxy-serv02が仮想IPアドレス192.168.2.101を引き継ぐはずです。次のコマンドで確認します。
# ip a show eth0
期待どおり、proxy-serv02が仮想IPアドレス192.168.2.101を有効化しました。ログを確認してみましょう。
cat /var/log/messages | grep -i keepalived
| proxy-serv01側 | proxy-serv02側 |
Keepalived_vrrp[xxxxx]: Kernel is reporting: interface eth0 DOWN Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering FAULT STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) removing protocol VIPs. Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Now in FAULT state |
Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Transition to MASTER STATE |
| keepalivedがeth0のDOWN状態を検知し、proxy_ip1 VRRPインスタンスをFAULT状態に設定することで、仮想IPアドレスを解放します。 | keepalivedがproxy_ip1 VRRPインスタンスをMASTER状態に設定し、eth0上でIPアドレス192.168.2.101を有効化してgratuitous ARPを送信します。 |
さらに、proxy-serv01のeth0を再度有効化した際に、仮想IPアドレス192.168.2.101が元のサーバーへ戻ることも確認してください。
| proxy-serv01側 | proxy-serv02側 |
Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) forcing a new MASTER election Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Transition to MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) setting protocol VIPs. Keepalived_vrrp[xxxxx]: Sending gratuitous ARP on eth0 for 192.168.2.101 |
Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Received advert with higher priority 255, ours 100 Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering BACKUP STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) removing protocol VIPs. |
| keepalivedがeth0の復旧を検知し、proxy_ip1 VRRPインスタンスのマスター選出を開始します。MASTER状態を獲得すると、サーバーはeth0上でIPアドレス192.168.2.101を有効化し、gratuitous ARPを送信します。 | keepalivedがproxy_ip1 VRRPインスタンスについてより高い優先度を持つパケットを受信し、proxy_ip1をBACKUP状態へ切り替えてIPアドレスを解放します。 |
2つ目のテストは、外部ネットワークインターフェース障害のシミュレーションです。proxy-serv01の外部ネットワークインターフェースeth1を無効化し、ログで結果を確認します。
| proxy-serv01側 | proxy-serv02側 |
Keepalived_vrrp[xxxxx]: Kernel is reporting: interface eth1 DOWN Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering FAULT STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) removing protocol VIPs. Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Now in FAULT state |
Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Transition to MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) setting protocol VIPs. Keepalived_vrrp[xxxxx]: Sending gratuitous ARP on eth0 for 192.168.2.101 |
| keepalivedがeth1のDOWN状態を検知し、proxy_ip1 VRRPインスタンスをFAULT状態に設定することで、仮想IPアドレスを解放します。 | keepalivedがproxy_ip1 VRRPインスタンスをMASTER状態に設定し、eth0上でIPアドレス192.168.2.101を有効化してgratuitous ARPを送信します。 |
3つ目のテストは、Squid障害のシミュレーションです。次のコマンドでサービスを手動で停止します。
# systemctl stop squid
ログで結果を確認します。
| proxy-serv01側 | proxy-serv02側 |
Keepalived_vrrp[xxxxx]: VRRP_Script(chk_squid_service) failed Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering FAULT STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) removing protocol VIPs. Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Now in FAULT state |
Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Transition to MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) Entering MASTER STATE Keepalived_vrrp[xxxxx]: VRRP_Instance(proxy_ip1) setting protocol VIPs. Keepalived_vrrp[xxxxx]: Sending gratuitous ARP on eth0 for 192.168.2.101 |
| Squidプロキシサービスの稼働をチェックするスクリプトがエラーを返します。keepalivedはproxy_ip1 VRRPインスタンスをFAULT状態に設定し、仮想IPアドレスを解放します。 | keepalivedがproxy_ip1 VRRPインスタンスをMASTER状態に設定し、eth0上でIPアドレス192.168.2.101を有効化してgratuitous ARPを送信します。 |
3つのテストすべてが正常に完了し、keepalivedが正しく構成されていることが確認できました。今後の記事では、Pacemakerを使ったHAクラスターの構成方法と、それぞれの特徴について解説する予定です。
proxy-serv01の最終設定ファイル(/etc/keepalived/keepalived.conf)
vrrp_script chk_squid_service {
script "/usr/sbin/squid -k check"
interval 3
}
vrrp_instance proxy_ip1 {
state MASTER
interface eth0
virtual_router_id 1
priority 255
virtual_ipaddress {
192.168.2.101/24 dev eth0 label eth0:1
}
track_interface {
eth1
}
track_script {
chk_squid_service
}
}
vrrp_instance proxy_ip2 {
state BACKUP
interface eth0
virtual_router_id 2
priority 100
virtual_ipaddress {
192.168.2.102/24 dev eth0 label eth0:2
}
track_interface {
eth1
}
track_script {
chk_squid_service
}
}
proxy-serv02の最終設定ファイル(/etc/keepalived/keepalived.conf)
vrrp_script chk_squid_service {
script "/usr/sbin/squid -k check"
interval 3
}
vrrp_instance proxy_ip1 {
state BACKUP
interface eth0
virtual_router_id 1
priority 100
virtual_ipaddress {
192.168.2.101/24 dev eth0 label eth0:1
}
track_interface {
eth1
}
track_script {
chk_squid_service
}
}
vrrp_instance proxy_ip2 {
state MASTER
interface eth0
virtual_router_id 2
priority 255
virtual_ipaddress {
192.168.2.102/24 dev eth0 label eth0:2
}
track_interface {
eth1
}
track_script {
chk_squid_service
}
}
-
Linuxの時刻をNTPサーバーと同期する方法【systemd対応・非対応両方を解説】
パソコンの内蔵時計は完璧ではありません。数日、数週間、あるいは数か月が経つと時刻が徐々にずれ込み、実際の時間を正しく表示しなくなります。たとえば、実際には「10時33分」なのに「10時30分」と表示されるといった具合です。昔のパソコンでは、定期的に手動で時計を合わせるのが一般的でした。しかし、インターネット接続が普及して以降、現代のOSはNTPサーバーの助けを借りて時計を自動的に調整するようになりました。NTPとは?NTPは「Network Time Protocol(ネットワーク・タイム・プロトコル)」の略称です。ネットワーク接続を通じてコンピューターの時計を同期させ、常に正確な時刻を保つた
-
NginxでDDoS攻撃を防ぐ方法|トラフィック監視からIP遮断まで徹底解説
DDoS(Distributed Denial of Service)攻撃とは、大量の不正な通信によってサーバーのリソースを食い潰し、正常なサービスを妨害するサイバー攻撃のことです。いわばコンピューターの世界における「組織的な襲撃」であり、無数の悪意あるリクエストが重なり合うことで、経験豊富な管理者が運用するサーバーでさえも機能停止に追い込まれるほどの脅威となります。さらに厄介なのは、こうした攻撃には複数の手口が存在するという点です。幸いにも、サーバー側の設定を適切に行えば、これらの攻撃に効果的に対抗できます。 NginxはUnix系マシンで広く利用されている人気の高いWebサーバーソフトウ