EC2 + Pacemaker/Corosync HA クラスタ ハンズオン

OSS クラスタソフトで 2 ノードの高可用性構成を組み、VIP とサービスを自動フェイルオーバーさせる

Amazon EC2 Pacemaker Corosync pcs fence_aws (STONITH) CLI 操作 上級 所要時間 90〜120 分 v1.0

📋 概要

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 の基本
OSRocky Linux 9(RHEL 9 互換。AlmaLinux 9 / RHEL 9 でも同手順)
費用目安約 0.5〜1 USD(t3.small × 2 台 を 2 時間程度)
ℹ️ 各コンポーネントの役割
  • Corosync — ノード間でハートビートを交換し、クラスタメンバーシップ(誰が生きているか)と通信を担うレイヤー
  • Pacemaker — リソース(VIP・サービス)の起動/停止/監視/フェイルオーバーを制御するクラスタリソースマネージャー
  • pcs — Pacemaker / Corosync を一括設定する CLI ツール(pcsd デーモン経由で全ノードを操作)
  • リソースエージェント — VIP(awsvip / IPaddr2)や Apache などを起動/監視するスクリプト群
  • STONITH(fence_aws) — 応答しないノードを EC2 API で強制停止し、スプリットブレインを防ぐ

🏗️ アーキテクチャ

👤 クライアント → VIP(セカンダリプライベート IP) 例: 10.0.1.100
↓ 通常はアクティブ機が VIP を保持
🖥️ node1(Active)  ⟷ Corosync ハートビート ⟷  🖥️ node2(Standby)
Pacemaker + Apache。両ノードとも同一サブネット内
↓ node1 障害時
❌ node1 ダウン → fence_aws が node1 を EC2 API で停止
node2 が VIP を引き継ぎ Apache を起動(自動フェイルオーバー)

ノード構成(例)

項目node1node2
ホスト名node1node2
プライマリ IP10.0.1.1110.0.1.12
VIP(セカンダリ IP)10.0.1.100(アクティブ側に付与)
役割初期 Active初期 Standby
⚠️ AWS で VIP を扱うときの注意

オンプレでは IPaddr2 リソースが Gratuitous ARP を送ることで VIP を切り替えますが、AWS の VPC ネットワークでは ARP ベースの切り替えが伝播しません。そのため awsvip リソースエージェントで「EC2 のセカンダリプライベート IP(ENI への割り当て)」を AWS API で付け替え、その上で IPaddr2 で OS のインターフェイスに IP を設定します。本ハンズオンは 同一サブネット・同一 AZ 構成を前提とします(マルチ AZ にする場合はルートテーブルを書き換える aws-vpc-move-ip を使います)。

✅ 前提条件

⚠️ リージョンとコストについて

本手順は ap-northeast-1(東京) を使用します。t3.small × 2 台で約 $0.0272/時間です。終了後は必ずクリーンアップしてください。

ℹ️ このハンズオンで作るもの(ゴール)

ブラウザ(または curl)で VIP(10.0.1.100)にアクセスすると Apache の応答が返り、アクティブ機を落とすと 数秒〜数十秒で待機機に切り替わって応答が継続すること。

🖥️ ステップ 1 ― EC2 を 2 台起動する

1-1. EC2 インスタンスを 2 台作成

EC2 コンソールから以下の設定で 2 台起動します(node1 / node2)。

AMIRocky Linux 9(または AlmaLinux 9 / RHEL 9)
インスタンスタイプt3.small
サブネット両ノードとも同一サブネット(同一 AZ)
プライベート IPnode1: 10.0.1.11 / node2: 10.0.1.12(任意の固定値)
キーペア既存のものを指定
1-2. セキュリティグループの設定

クラスタ内通信のため、同一セキュリティグループ内(自己参照)で全トラフィックを許可するか、最低限以下を開けます。

用途プロトコル/ポートソース
SSHTCP 22管理元 IP
HTTP(動作確認)TCP 80管理元 IP
CorosyncUDP 5404-5405同一 SG(自己参照)
pcsdTCP 2224同一 SG(自己参照)
fence(任意)TCP 3121同一 SG(自己参照)
1-3. ホスト名と /etc/hosts を設定(両ノードで実施)
# 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 から

🔑 ステップ 2 ― IAM ロールとネットワーク設定

awsvip(セカンダリ IP 付け替え)と fence_aws(インスタンス停止)が EC2 API を呼ぶため、両ノードに IAM ロールを付与します。

2-1. 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 を絞る

学習目的では "Resource": "*" ですが、本番では対象インスタンスの ARN や条件キー(タグ等)で最小権限に絞ってください。

2-2. IAM ロールを作成してアタッチ

信頼されたエンティティ「EC2」でロール ha-cluster-role を作成し、上記ポリシーをアタッチします。EC2 コンソールで node1 / node2 それぞれを選択 →「アクション」→「セキュリティ」→「IAM ロールを変更」で割り当てます。

2-3. 送信元/送信先チェックを無効化(VIP のため)

EC2 コンソールで各インスタンス →「アクション」→「ネットワーキング」→「ソース/宛先チェックを変更」→ 「停止」にチェック。VIP 宛のトラフィックを正しく受けるために必要です。

2-4. AWS CLI をインストール(両ノード)

awsvip / fence_aws は内部で AWS CLI / API を使います。

sudo dnf install -y awscli   # または awscli2
aws sts get-caller-identity   # ロールが効いているか確認
✅ 確認ポイント

aws sts get-caller-identityassumed-role/ha-cluster-role/... を返せば、インスタンスプロファイルが機能しています。

📦 ステップ 3 ― クラスタソフトのインストール

以下は両ノードで実施します。

3-1. HighAvailability リポジトリを有効化

Rocky / AlmaLinux / RHEL 9 では HA 系パッケージは専用リポジトリにあります。

sudo dnf config-manager --set-enabled highavailability
# RHEL の場合: subscription-manager で HA リポジトリを有効化
3-2. パッケージをインストール
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
3-3. pcsd を起動し、クラスタ管理ユーザーのパスワードを設定

インストール時に作成される hacluster ユーザーに同じパスワードを両ノードで設定します。

sudo systemctl enable --now pcsd
echo "hacluster:YourClusterP@ss" | sudo chpasswd
3-4. Apache をインストール(後で VIP と一緒にフェイルオーバーさせる対象)
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
ℹ️ httpd は systemd で起動しない

Apache の起動/停止は Pacemaker が管理します。systemctl enable httpdしないでください(二重管理になります)。

✅ 確認ポイント

両ノードで pcs --versionwhich fence_aws が成功すれば次へ進めます。

🔗 ステップ 4 ― クラスタの作成

以下はどちらか 1 台(node1)でのみ実施します(pcs が両ノードへ設定を配布します)。

4-1. ノード間認証
sudo pcs host auth node1 node2 -u hacluster -p YourClusterP@ss

node1: Authorized / node2: Authorized と表示されれば成功です。

4-2. クラスタを構成
sudo pcs cluster setup ha_cluster node1 node2

# クラスタを起動し、自動起動を有効化
sudo pcs cluster start --all
sudo pcs cluster enable --all
4-3. クラスタの状態を確認
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 によるクラスタメンバーシップが確立しています。

🛡️ ステップ 5 ― STONITH(fence_aws)の設定

STONITH は「応答しなくなったノードを強制的に停止し、両ノードが同時に VIP を持つスプリットブレインを防ぐ」機能です。AWS では fence_aws が EC2 API でインスタンスを停止/再起動します。

5-1. インスタンス ID を確認
# 各ノードで自分のインスタンス 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...)を控えます。

5-2. fence_aws リソースを作成

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
ℹ️ 認証は IAM ロールを使用

アクセスキーを直接渡さず、ステップ 2 で付与した IAM ロール(インスタンスプロファイル)で認証されます。

5-3. STONITH の動作確認(任意・破壊的)
sudo pcs stonith status

# node2 を fence(強制停止)してみる ※node2 は実際に停止します
sudo pcs stonith fence node2
⚠️ fence テストは実機に影響します

pcs stonith fence node2 は node2 を実際に停止します。検証後は EC2 コンソールから node2 を起動し、sudo pcs cluster start で復帰させてください。

✅ 確認ポイント

sudo pcs stonith statusclusterfence ... Started と表示されれば STONITH が有効です。

🌐 ステップ 6 ― VIP と Apache のリソース化

VIP(awsvip + IPaddr2)と Apache を 1 つのリソースグループにまとめ、常に同じノードでまとめてフェイルオーバーするようにします。node1 で実施します。

6-1. awsvip リソース(セカンダリ IP の AWS 側付け替え)

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
6-2. IPaddr2 リソース(OS インターフェイスへの IP 付与)
sudo pcs resource create vip IPaddr2 \
  ip=10.0.1.100 cidr_netmask=24 \
  nic=eth0 \
  op monitor interval=30s \
  --group ha_group
6-3. Apache リソース
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)、フェイルオーバー時もまとめて移動します。

6-4. 状態確認
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」が返ります。

🔁 ステップ 7 ― フェイルオーバーの検証

アクティブ機を落として、VIP と Apache が待機機へ自動的に移動することを確認します。

7-1. 継続監視を開始(クライアント or 別端末から)
# 1秒ごとに VIP へアクセスし、応答ノードの変化を観察
while true; do curl -s --max-time 2 http://10.0.1.100/ ; sleep 1; done
7-2. 方法 A: クラスタとして「正常な切り替え」を試す

アクティブ機をスタンバイにすると、リソースが計画的に移動します。

# node1 をスタンバイへ(node1 上で実行)
sudo pcs node standby node1
sudo pcs status   # ha_group が node2 に移動

# 元に戻す
sudo pcs node unstandby node1
7-3. 方法 B: 障害をシミュレート(アクティブ機を強制停止)
# アクティブ機(例 node1)を OS ごと落とす
sudo systemctl poweroff   # node1 上で実行
# または EC2 コンソールから node1 を「停止」

監視中の curl ループで、応答が一時的に途切れた後に 「Served by node2」 に切り替わるのを確認します。

7-4. 切り替わりの確認
# node2 で
sudo pcs status
ip addr show eth0 | grep 10.0.1.100   # VIP が node2 に移動している
✅ 確認ポイント

アクティブ機を落としてから数秒〜数十秒で curl の応答が node2 のものに切り替われば、HA クラスタによる自動フェイルオーバーが成功しています。停止した node1 を起動し直すと Online に復帰します(リソースは原則そのまま node2 に残ります)。

💡 学習ポイント

主要な pcs コマンド

コマンド用途
pcs statusクラスタ全体の状態確認
pcs resourceリソース一覧・操作
pcs node standby <node>ノードを待機状態にしリソースを退避
pcs resource move <rsc> <node>リソースを指定ノードへ移動
pcs stonith statusフェンシングデバイスの状態
pcs cluster stop --allクラスタ全体を停止
crm_mon -1状態のワンショット表示

HA クラスタの重要概念

AWS 特有のポイント(試験・実務)

🧹 クリーンアップ

課金を止めるため、以下の順で削除します。

⚠️ EC2 は起動中ずっと課金されます

検証が終わったら必ず EC2 を削除してください。

1. クラスタを停止・破棄
# どちらかのノードで
sudo pcs cluster stop --all
sudo pcs cluster destroy
2. EC2 インスタンスを終了

EC2 コンソールで node1 / node2 を選択 →「インスタンスを終了」。

3. IAM ロール・ポリシーを削除

不要であれば ha-cluster-roleha-cluster-policy を削除します。

4. その他の確認

セキュリティグループ、Elastic IP(使った場合)など残存リソースがないか確認します。VIP に使ったセカンダリ IP はインスタンス終了時に解放されます。

✅ クリーンアップ完了チェックリスト
  • ☐ クラスタを destroy した
  • ☐ node1 / node2 を終了した
  • ☐ IAM ロール / ポリシーを削除した(不要な場合)
  • ☐ 余分なセキュリティグループ / EIP が残っていない