OSS クラスタソフトで 2 ノードの高可用性構成を組み、VIP とサービスを自動フェイルオーバーさせる
HA(High Availability=高可用性)クラスタとは、複数のサーバーを 1 つのクラスタとしてまとめ、アクティブ機(現用系)に障害が起きたら自動的にスタンバイ機(待機系)がサービスを引き継ぐ仕組みです。本ハンズオンでは、Linux HA クラスタの定番 OSS である Pacemaker + Corosync を使って、2 台の EC2 で「VIP(仮想 IP)+ Apache」をフェイルオーバーさせる構成を構築します。
オンプレミスの HA クラスタとの最大の違いは、AWS では Gratuitous ARP による VIP の付け替えがそのままでは効かない点と、物理サーバーの電源を落とす STONITH(フェンシング)の代わりに EC2 API でインスタンスを停止する fence_aws を使う点です。この AWS 特有の作法こそが本ハンズオンの肝です。
| 項目 | 内容 |
|---|---|
| 対象サービス | Amazon EC2、IAM、Pacemaker / Corosync / pcs、fence_aws、awsvip |
| 主な学習内容 | クラスタソフトの構成・Corosync ハートビート・リソース管理・STONITH・VIP フェイルオーバー |
| 所要時間 | 90〜120 分 |
| 難易度 | ★★★★☆(上級者向け) |
| 前提知識 | Linux の基本操作(SSH / systemctl)、EC2 / VPC の基本 |
| OS | Rocky Linux 9(RHEL 9 互換。AlmaLinux 9 / RHEL 9 でも同手順) |
| 費用目安 | 約 0.5〜1 USD(t3.small × 2 台 を 2 時間程度) |
| 項目 | node1 | node2 |
|---|---|---|
| ホスト名 | node1 | node2 |
| プライマリ IP | 10.0.1.11 | 10.0.1.12 |
| VIP(セカンダリ IP) | 10.0.1.100(アクティブ側に付与) | |
| 役割 | 初期 Active | 初期 Standby |
オンプレでは IPaddr2 リソースが Gratuitous ARP を送ることで VIP を切り替えますが、AWS の VPC ネットワークでは ARP ベースの切り替えが伝播しません。そのため awsvip リソースエージェントで「EC2 のセカンダリプライベート IP(ENI への割り当て)」を AWS API で付け替え、その上で IPaddr2 で OS のインターフェイスに IP を設定します。本ハンズオンは 同一サブネット・同一 AZ 構成を前提とします(マルチ AZ にする場合はルートテーブルを書き換える aws-vpc-move-ip を使います)。
sudo・systemctl)ができること本手順は ap-northeast-1(東京) を使用します。t3.small × 2 台で約 $0.0272/時間です。終了後は必ずクリーンアップしてください。
ブラウザ(または curl)で VIP(10.0.1.100)にアクセスすると Apache の応答が返り、アクティブ機を落とすと 数秒〜数十秒で待機機に切り替わって応答が継続すること。
EC2 コンソールから以下の設定で 2 台起動します(node1 / node2)。
クラスタ内通信のため、同一セキュリティグループ内(自己参照)で全トラフィックを許可するか、最低限以下を開けます。
| 用途 | プロトコル/ポート | ソース |
|---|---|---|
| SSH | TCP 22 | 管理元 IP |
| HTTP(動作確認) | TCP 80 | 管理元 IP |
| Corosync | UDP 5404-5405 | 同一 SG(自己参照) |
| pcsd | TCP 2224 | 同一 SG(自己参照) |
| fence(任意) | TCP 3121 | 同一 SG(自己参照) |
# node1 で sudo hostnamectl set-hostname node1 # node2 で sudo hostnamectl set-hostname node2 # 両ノードの /etc/hosts に追記 sudo tee -a /etc/hosts <<'EOF' 10.0.1.11 node1 10.0.1.12 node2 EOF
各ノードから相手のホスト名で ping が通れば OK です。
ping -c2 node2 # node1 から ping -c2 node1 # node2 から
awsvip(セカンダリ IP 付け替え)と fence_aws(インスタンス停止)が EC2 API を呼ぶため、両ノードに IAM ロールを付与します。
IAM コンソールでポリシー ha-cluster-policy を作成し、以下を貼り付けます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AwsVip",
"Effect": "Allow",
"Action": [
"ec2:AssignPrivateIpAddresses",
"ec2:UnassignPrivateIpAddresses",
"ec2:DescribeNetworkInterfaces"
],
"Resource": "*"
},
{
"Sid": "FenceAws",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeTags",
"ec2:RebootInstances",
"ec2:StopInstances",
"ec2:StartInstances"
],
"Resource": "*"
}
]
}
学習目的では "Resource": "*" ですが、本番では対象インスタンスの ARN や条件キー(タグ等)で最小権限に絞ってください。
信頼されたエンティティ「EC2」でロール ha-cluster-role を作成し、上記ポリシーをアタッチします。EC2 コンソールで node1 / node2 それぞれを選択 →「アクション」→「セキュリティ」→「IAM ロールを変更」で割り当てます。
EC2 コンソールで各インスタンス →「アクション」→「ネットワーキング」→「ソース/宛先チェックを変更」→ 「停止」にチェック。VIP 宛のトラフィックを正しく受けるために必要です。
awsvip / fence_aws は内部で AWS CLI / API を使います。
sudo dnf install -y awscli # または awscli2 aws sts get-caller-identity # ロールが効いているか確認
aws sts get-caller-identity が assumed-role/ha-cluster-role/... を返せば、インスタンスプロファイルが機能しています。
以下は両ノードで実施します。
Rocky / AlmaLinux / RHEL 9 では HA 系パッケージは専用リポジトリにあります。
sudo dnf config-manager --set-enabled highavailability # RHEL の場合: subscription-manager で HA リポジトリを有効化
sudo dnf install -y pacemaker pcs resource-agents fence-agents-aws
pacemaker — クラスタリソースマネージャーpcs — 設定 CLI と pcsd デーモンresource-agents — IPaddr2 / awsvip / apache などのエージェントfence-agents-aws — STONITH 用 fence_awsインストール時に作成される hacluster ユーザーに同じパスワードを両ノードで設定します。
sudo systemctl enable --now pcsd echo "hacluster:YourClusterP@ss" | sudo chpasswd
sudo dnf install -y httpd
# ノードを判別できるよう、各ノードで異なるテストページを置いておく
echo "<h1>Served by $(hostname)</h1>" | sudo tee /var/www/html/index.html
# Pacemaker の監視用 status ページ設定
sudo tee /etc/httpd/conf.d/serverstatus.conf <<'EOF'
<Location /server-status>
SetHandler server-status
Require local
</Location>
EOF
Apache の起動/停止は Pacemaker が管理します。systemctl enable httpd はしないでください(二重管理になります)。
両ノードで pcs --version と which fence_aws が成功すれば次へ進めます。
以下はどちらか 1 台(node1)でのみ実施します(pcs が両ノードへ設定を配布します)。
sudo pcs host auth node1 node2 -u hacluster -p YourClusterP@ss
node1: Authorized / node2: Authorized と表示されれば成功です。
sudo pcs cluster setup ha_cluster node1 node2 # クラスタを起動し、自動起動を有効化 sudo pcs cluster start --all sudo pcs cluster enable --all
sudo pcs status
出力例(STONITH 未設定なので警告が出ますが、次のステップで設定します)。
Cluster name: ha_cluster Cluster Summary: * Stack: corosync * Current DC: node1 (version ...) - partition with quorum Node List: * Online: [ node1 node2 ]
Online: [ node1 node2 ] と両ノードが表示されれば、Corosync によるクラスタメンバーシップが確立しています。
STONITH は「応答しなくなったノードを強制的に停止し、両ノードが同時に VIP を持つスプリットブレインを防ぐ」機能です。AWS では fence_aws が EC2 API でインスタンスを停止/再起動します。
# 各ノードで自分のインスタンス ID を確認(IMDSv2) TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" \ -H "X-aws-ec2-metadata-token-ttl-seconds: 60") curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \ http://169.254.169.254/latest/meta-data/instance-id; echo
node1 / node2 のインスタンス ID(例: i-0aaa... / i-0bbb...)を控えます。
pcmk_host_map で「Pacemaker のノード名 = EC2 インスタンス ID」を対応付けます。
sudo pcs stonith create clusterfence fence_aws \ region=ap-northeast-1 \ pcmk_host_map="node1:i-0aaaaaaaaaaaaaaaa;node2:i-0bbbbbbbbbbbbbbbb" \ power_timeout=120 \ pcmk_reboot_timeout=180 \ pcmk_reboot_retries=2 \ op monitor interval=120s
アクセスキーを直接渡さず、ステップ 2 で付与した IAM ロール(インスタンスプロファイル)で認証されます。
sudo pcs stonith status # node2 を fence(強制停止)してみる ※node2 は実際に停止します sudo pcs stonith fence node2
pcs stonith fence node2 は node2 を実際に停止します。検証後は EC2 コンソールから node2 を起動し、sudo pcs cluster start で復帰させてください。
sudo pcs stonith status で clusterfence ... Started と表示されれば STONITH が有効です。
VIP(awsvip + IPaddr2)と Apache を 1 つのリソースグループにまとめ、常に同じノードでまとめてフェイルオーバーするようにします。node1 で実施します。
VIP に使うセカンダリプライベート IP(例: 10.0.1.100)を指定します。サブネットの CIDR 範囲内で未使用のものを選びます。
sudo pcs resource create privip awsvip \ secondary_private_ip=10.0.1.100 \ op monitor interval=30s \ --group ha_group
sudo pcs resource create vip IPaddr2 \ ip=10.0.1.100 cidr_netmask=24 \ nic=eth0 \ op monitor interval=30s \ --group ha_group
sudo pcs resource create webserver apache \ configfile=/etc/httpd/conf/httpd.conf \ statusurl="http://127.0.0.1/server-status" \ op monitor interval=20s \ --group ha_group
同じ --group ha_group に入れたリソースは、定義順に同一ノードで起動し(privip → vip → webserver)、フェイルオーバー時もまとめて移動します。
sudo pcs status # どのノードに VIP が付いたか確認 ip addr show eth0 | grep 10.0.1.100
同一ノード(例 node1)で privip / vip / webserver がすべて Started になり、そのノードの eth0 に 10.0.1.100 が付いていれば成功です。クライアントから curl http://10.0.1.100/ で「Served by node1」が返ります。
アクティブ機を落として、VIP と Apache が待機機へ自動的に移動することを確認します。
# 1秒ごとに VIP へアクセスし、応答ノードの変化を観察 while true; do curl -s --max-time 2 http://10.0.1.100/ ; sleep 1; done
アクティブ機をスタンバイにすると、リソースが計画的に移動します。
# node1 をスタンバイへ(node1 上で実行) sudo pcs node standby node1 sudo pcs status # ha_group が node2 に移動 # 元に戻す sudo pcs node unstandby node1
# アクティブ機(例 node1)を OS ごと落とす sudo systemctl poweroff # node1 上で実行 # または EC2 コンソールから node1 を「停止」
監視中の curl ループで、応答が一時的に途切れた後に 「Served by node2」 に切り替わるのを確認します。
# node2 で sudo pcs status ip addr show eth0 | grep 10.0.1.100 # VIP が node2 に移動している
アクティブ機を落としてから数秒〜数十秒で curl の応答が node2 のものに切り替われば、HA クラスタによる自動フェイルオーバーが成功しています。停止した node1 を起動し直すと Online に復帰します(リソースは原則そのまま node2 に残ります)。
| コマンド | 用途 |
|---|---|
pcs status | クラスタ全体の状態確認 |
pcs resource | リソース一覧・操作 |
pcs node standby <node> | ノードを待機状態にしリソースを退避 |
pcs resource move <rsc> <node> | リソースを指定ノードへ移動 |
pcs stonith status | フェンシングデバイスの状態 |
pcs cluster stop --all | クラスタ全体を停止 |
crm_mon -1 | 状態のワンショット表示 |
two_node: 1 が pcs により自動設定される)resource-stickiness で制御)awsvip(セカンダリ IP)または aws-vpc-move-ip(ルートテーブル)を使うfence_aws で EC2 API 経由 → IAM 権限が必須課金を止めるため、以下の順で削除します。
検証が終わったら必ず EC2 を削除してください。
# どちらかのノードで sudo pcs cluster stop --all sudo pcs cluster destroy
EC2 コンソールで node1 / node2 を選択 →「インスタンスを終了」。
不要であれば ha-cluster-role と ha-cluster-policy を削除します。
セキュリティグループ、Elastic IP(使った場合)など残存リソースがないか確認します。VIP に使ったセカンダリ IP はインスタンス終了時に解放されます。