EC2をELB経由でウェブサーバとして、複数台使用しているときに、1台だけでバッチを実行したいとします。
いままでは、タグにBatchなどをつけることで、バッチを実行するサーバを識別していましたが、immutableな環境にして、サーバをいつでも廃棄できるようにすると、タグを付けるのを忘れたりと面倒です。
そこで、以下の条件で、そのサーバがバッチを実行するサーバかを判定するシェルスクリプトを作成しました。
条件は
- ELB配下のインスタンス
- 有効(InService)なインスタンス
- インスタンスIDを文字列比較して、最も小さなもの
以下のスクリプトを実行するには、IAMのロールなどでELBとEC2へのアクセス権をインスタンスへ付与する必要があります。もしくは、$ aws configure などを実行して、awsのcli環境が使用できるようにしてください。
shell
#!/bin/bash
LOAD_BALANCER_NAME="[ロードバランサ名]"
# Get self instance id and ip address.
MY_INSTANCE=`curl -s 169.254.169.254/latest/meta-data/instance-id/`
# ロードバランサ配下の有効なインスタンスの一覧を取得
INSTANCE_LIST=`aws elb describe-instance-health \
--load-balancer-name ${LOAD_BALANCER_NAME} \
--region ap-northeast-1 \
--query 'InstanceStates[?State==\`InService\`].InstanceId' | jq -r '.[]'`
IS_ACTIVE=0
for INSTANCE in ${INSTANCE_LIST}
do
if [ ${INSTANCE} = ${MY_INSTANCE} ]; then
IS_ACTIVE=1
continue
fi
if [ ${INSTANCE} \< ${MY_INSTANCE} ]; then
exit 1
fi
done
if [ ${IS_ACTIVE} -eq 1 ]; then
exit 0
else
exit 1
fi
このファイルを、check.shなどとして保存し、下記のようにバッチの実行スクリプトを書くことで、ELB配下のすべてのサーバでcronを登録しても、1つのサーバだけで処理が行われます。
shell
#!/bin/bash
check.sh
IS_RUN=$?
if [ IS_RUN -eq 0 ]; then
[バッチの実行]
fi