Amazon EC2でLinuxクラスターを作ってみます。
使用するLinuxディストリビューションはRed Hat 9.5で、ミドルウェアはCorosyncとPacemakerです。
Corosyncがクラスターに属するサーバー(クラスターではノードと呼びます)の管理と生存監視を行い、Pacemakerが可用性を上げたいアプリケーションやサービス(クラスターではリソースと呼びます)の管理と生存監視を行います。
これらのミドルウェアの設定ヒューマンインターフェイスとしてpcsコマンドとpcsdサービスというものを使用します。
またcorosyncがノードを管理する一環で電源管理を行うための機能としてfenceというものがあります。
情報量多いですね。。。
やりたいことは以下です。
vsftpdをインストールしたLinuxサーバーを2台用意し、片方のサーバーでFTPサーバーを提供します。
なんらかのトラブルによってサービス提供しているサーバーがFTPサーバーの役割を果たせない状態になった場合に自動でもう一台のサーバーに接続が向くようにしてFTPサーバーの提供を継続できるようにする。
これを以下の方法で実現します。
- VPCのCIDRに属さないIPアドレスを用意する。(決めるだけ)
- これを仮想IPとしてFTPサーバーを提供するサーバーに割り当てる 。
- FTPクライアントは仮想IPで接続する。
- 障害発生時にはこの仮想IPをもう一台のサーバーに付け替える。
結果、FTPクライアントは接続先のIPアドレスを変更することなくFTPサーバーへ接続することができます。
さてやっていきます。
1. EC2インスタンスを作成する
使用するAMIは「RHEL_HA-9.5.0_HVM-20250313-x86_64-0-Hourly2-GP3」というものでRed Hat社公式のAMIです。
"HA"は"High Availability"の略で、これがついていないとクラスターを構築するためのパッケージがインストールできないので気を付けてください。
SecurityGroupやIAMロールは適当なものを用意してください。
IAMロールには最低限 ec2:CreateRoute 権限が必要です。
今回は更に ec2:DescribeInstances も必要となっています。
2. 各種ミドルウェアをインストールしクラスター構築の準備を行う
この作業は2台のEC2、それぞれで行います。
# 不足しているパッケージをインストール
dnf install -y fence-agents-aws resource-agents-cloud
# haclusterユーザーのパスワードを設定
echo ${HACLUSTER_PASS} | passwd --stdin hacluster
# pcsdを有効化し、起動
systemctl enable pcsd
systemctl start pcsd
# 仮想IPの名前解決をできるように設定
echo ${PRIVATE_VIP} vpcip>> /etc/hosts
# vsftpdをインストール
dnf install -y vsftpd
3. クラスターを構築
この作業はどちらかのEC2で1回だけ行います。
# 作業しているEC2のプライベートIPを取得
THIS_INSTANCE_ID=i-xxxxxxxxxxxxxxxxx
THIS_INSTANCE_PRIVATE_IP=`aws ec2 describe-instances --instance-ids ${THIS_INSTANCE_ID} --query 'Reservations[0].Instances[0].NetworkInterfaces[0].PrivateIpAddress' --output text`
# 作業しているEC2とは別のEC2のプライベートIPを取得
OTHER_INSTANCE_ID=i-yyyyyyyyyyyyyyyyy
OTHER_INSTANCE_PRIVATE_IP=`aws ec2 describe-instances --instance-ids ${OTHER_INSTANCE_ID} --query 'Reservations[0].Instances[0].NetworkInterfaces[0].PrivateIpAddress' --output text`
# pcsの認証
pcs host auth -u hacluster -p ${HACLUSTER_PASS} ${OTHER_INSTANCE_PRIVATE_IP} ${THIS_INSTANCE_PRIVATE_IP}
# クラスターを作成
pcs cluster setup is_integration_cluster ${OTHER_INSTANCE_PRIVATE_IP} ${THIS_INSTANCE_PRIVATE_IP}
# クラスターを有効化
pcs cluster enable --all
# クラスターを開始
pcs cluster start --all
# クラスターのステータスを確認
pcs cluster status
# fencingを作成
pcs stonith create my_cluster_fence fence_aws region=ap-northeast-1 \
pcmk_host_map="${OTHER_INSTANCE_PRIVATE_IP}:${OTHER_INSTANCE_ID};${THIS_INSTANCE_PRIVATE_IP}:${THIS_INSTANCE_ID}" \
power_timeout=240 pcmk_reboot_timeout=300 pcmk_reboot_retries=4
# fencingを確認
pcs stonith config my_cluster_fence
# クラスターの確認間隔を設定
pcs property set cluster-recheck-interval=30s
# vsftpdのリソースを作成
pcs resource create vsftpd systemd:vsftpd
pcs resource meta vsftpd failure-timeout=20s
# VPCのルートテーブルに仮想IPのルートを追加(ルーティング先はEC2インスタンス)
aws ec2 create-route --route-table-id ${ROUTE_TABLE_ID} --destination-cidr-block ${PRIVATE_VIP}/32 --instance-id ${OTHER_INSTANCE_ID}
# 仮想IPのリソースを作成
pcs resource create vpcip aws-vpc-move-ip ip=${PRIVATE_VIP} interface=eth0 routing_table=${ROUTE_TABLE_ID}
# 仮想IPのリソースとvsftpdのリソースが一致するよう紐づける
pcs constraint colocation add vsftpd with vpcip INFINITY
構築が終わると構築作業をした方ではないEC2インスタンスがサービス提供をしている状態になります。
ルートテーブルを見ると仮想IPの向き先が構築作業をした方ではないEC2インスタンスになっています。
試しに構築作業をした方ではないEC2インスタンスでvsftpdを停止してみます。
暫く(30秒くらい)するとルートテーブルの仮想IPの向き先が構築作業をしたEC2インスタンスに変わりました!
ほとんどの場合ロードバランサーで事足りるのでクラスターを構築する必要はないですがFTPサーバーにロードバランサーが使えないのでそんな時はクラスターを。。。いえ、FTP使うのを再考しましょう!(笑)