EC2とEIPで冗長構成のApache Load Balancerを構築する(Pacemaker)

ELBはオートスケールで可用性も高く、ミドルウェアの心配しないでいいので便利なのですが、IP固定できないなど課題があるのと、障害時の調査がブラックボックスすぎて大変なため、Pacemakerを利用して冗長化構成のLoadBalancerを構築してみました。

CDPで言うFloating IPになります。

CDP:Floating IPパターン - AWS-CloudDesignPattern

利用するEC2

OSはCentOS7で以下の2台のEC2インスタンスを起動します。

冗長化のためにAZは分けてあります。

役割 ホスト名
LB 1台目 srv-lb01
LB 2台目 srv-lb02

LB構築

それぞれのインスタンスでLB構築します。手順は以下の記事の通り。

Apacheのmod_proxy_hcheckを利用してロードバランサーを構築してみる - YOMON8.NET

Pacemaker導入

それぞれのEC2インスタンスでPacemakerをインストールします。

# 必要なパッケージのインストール
yum install pacemaker corosync pcs

# クラスタユーザのパスワード設定
passwd hacluster

# pcs (pacemaker/corosync configuration system)サービスの起動有効化
systemctl start pcsd
systemctl enable pcsd

awsコマンドも利用できるようにしておきます。IAMポリシーの例は以下の通り。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1480492145000",
            "Effect": "Allow",
            "Action": [
                "ec2:AssociateAddress",
                "ec2:Describe*",
                "ec2:DisassociateAddress"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

Pacemakerリソースエージェントデプロイ

こちらのリポジトリを使わせてもらっています。

GitHub - moomindani/aws-eip-resource-agent: Resource Agent for AWS EC2 EIP

VPCのEIPに対応させるためforkさせてもらって少し編集しました。これを両方のEC2インスタンスにデプロイします。

rm -fR /tmp/aws-eip-resource-agent
cd /tmp
git clone https://github.com/yomon8/aws-eip-resource-agent.git
cd aws-eip-resource-agent
git checkout develop
mv eip /usr/lib/ocf/resource.d/heartbeat/
chown root:root /usr/lib/ocf/resource.d/heartbeat/eip 
chmod 0755 /usr/lib/ocf/resource.d/heartbeat/eip

クラスタの構築

この項目の作業は片側のノード(例えばsrv-lb01)のみで実行します。(両ノードでの実行は不要)

クラスタ設定

まずはクラスタを構築します。

# 任意のクラスタの名前
cluster_name=clustername

# LoadBalancerに紐付けるEIP
eip=52.198.xxx.xxx

# 2台のEC2インスタンスのホスト名(ホスト名でアクセスできるようにしておきます)
node1=srv-lb01 
node2=srv-lb02

# haclusterユーザのパスワード
password=p@ssw0rd

# Clusterの初期設定
pcs cluster auth ${node1} ${node2} -u hacluster -p ${password} --force
pcs cluster setup --name ${cluster_name}  ${node1} ${node2}
pcs cluster start --all

# Clusterの詳細設定
pcs property set stonith-enabled=false
pcs property set no-quorum-policy=ignore
pcs property set crmd-transition-delay="0s" 
pcs resource defaults resource-stickiness="200" migration-threshold="2" 

この時点でクラスタが登録できているはずです。pcs status コマンドでエラーが無くクラスタが登録できていることを確認します。

# pcs status
Cluster name: cluster_name
Last updated: Wed Dec  7 22:52:23 2016     Last change: Wed Dec  7 22:52:21 2016 by hacluster via crmd on srv-lb01
Stack: corosync
Current DC: srv-lb01 (version 1.1.13-10.el7_2.4-44eb2dd) - partition with quorum
2 nodes and 0 resources configured

Online: [ srv-lb01 srv-lb02 ]

Full list of resources:


PCSD Status:
  srv-lb01: Online
  srv-lb02: Online

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled

クラスタリソースの登録

# LoadBalancerに紐付けるEIP
eip=52.198.xxx.xxx

# クラスタリソースの登録
# eipの付け替え、EIPの移動には10〜20秒程度かかります
pcs resource create res-eip ocf:heartbeat:eip \
    params \
        elastic_ip="${eip}" \
    op start   timeout="60s" interval="0s"  on-fail="stop" \
    op monitor timeout="60s" interval="10s" on-fail="restart" \
    op stop    timeout="60s" interval="0s"  on-fail="block" 


# HTTPDサービスの死活監視
pcs resource create res-httpd systemd:httpd \
    params \
    op monitor interval="5s" timeout="3s" 

# クラスタリソースのグループ化
pcs resource group add GP_LB res-eip res-httpd
pcs constraint colocation add res-eip res-httpd

pcs status コマンドでもう一度状況を確認してみます。

# pcs status
Cluster name: clustername
Last updated: Wed Dec  7 15:02:14 2016     Last change: Wed Dec  7 14:58:25 2016 by root via cibadmin on srv-lb01
Stack: corosync
Current DC: srv-lb01 (version 1.1.13-10.el7_2.4-44eb2dd) - partition with quorum
2 nodes and 2 resources configured

Online: [ srv-lb01 srv-lb02 ]

Full list of resources:

 Resource Group: GP_LB
     res-eip    (ocf::heartbeat:eip):   Started srv-lb01
     res-httpd  (systemd:httpd):    Started srv-lb01

PCSD Status:
  srv-lb01: Online
  srv-lb01: Online

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled

Failover挙動確認

リソースhttpdの停止

上記の設定ではクラスタの設定にmigration-threshold="2"を入れているので、リソースのチェックに一回失敗した場合も、一度は再起動かけます。

※ ここからは、コンソール2つ上げて片方でcrm_monコマンドやwatch -n 3 pcs statusみたいなコマンドを起動しておくと動きがよく見えます。

httpdのリソースであるres-httpd側の動きを見ています。httpdを停止してみます。

[srv-lb01] # systemctl stop httpd

srv-lb01 上で一度停止したhttpdのサービスが再起動されてきたはずです。そして、もう一度httpdを止めると srv-lb02 にリソースが移動するのが確認できると思います。

failcountの確認とリセット

migration-threshold="2" と設定されているため、failcountが2回になるとフェールオーバーされます。failcountは以下のコマンドで確認できます。

# pcs resource failcount show res-httpd
Failcounts for res-httpd
 search-stress-test-lb02: 2

フェールバックする場合は、事前にfailcountをクリアしてあげる必要があります。

# pcs resource failcount reset res-httpd
# pcs resource failcount show res-httpd
No failcounts for res-httpd

(補足)Failover時の通知

こちらの設定でAmazon SNS通知しています。

Pacemakerでフェールオーバー時にAmazon SNSに通知するResource Agent書いてみた - YOMON8.NET

(補足)failcountをクリアしてもリソース移動できないとき

配置(location)の制約(constraint)が設定されてないでしょうか。

$ pcs constraint location show --full
Location Constraints:
  Resource: GP_LB
    Disabled on: srv-lb01 (score:-INFINITY) (role: Started) (id:cli-ban-GP_LB-on-srv-lb01)

制約が設定されている場合は移動できないのでremoveしてあげます。

$ pcs constraint location remove cli-ban-GP_LB-on-srv-lb01
$ pcs constraint location show --full
Location Constraints:

(補足)pcsコマンドはタブ補完が効きます

pcs コマンドは多機能でサブコマンドやオプションを覚えるの大変ですが、幸いタブ補完が効きます。

(補足)Clusterの削除

設定を最初からやり直したい場合は以下でClusterを破棄します。AMIで展開したい場合なども利用可能です。

pcs cluster destroy