【習作】EC2を起動してステータスチェックに失敗したらリトライするスクリプトを書いた

はじめに

どうも、佐々木です。大好きな夏が終わりかけていて寂しいです。

主にコストダウンを目的として、EC2の起動/停止をスケジューリングしたい場合があります。方法としては、Auto Scalingを使うか、あるいは外部からAPIを叩くことになります。簡単なのはAWS SDKなりAWS CLIなりを使ってAPIを叩く方法です。しかしスケジュールに従った自動起動では、人手を介さない以上、失敗した場合の処理を考慮しておく必要があります。失敗の要因としては、AWS側の問題、システム側の問題、両方が考えられます。自動停止であれば、失敗しても停止しない=起動しっぱなしなので、サービスに影響はありません。しかし自動起動が失敗した場合には、サービス自体が動かない為、利用者に影響を与えてしまいます。

そこで、AWS CLIを利用して、以下のようなシェルスクリプトを書いてみました。

  • EC2を起動する(start-instances)
  • 正常に起動したかステータスを確認する
  • ステータスチェックに成功した場合そのまま終了
  • ステータスチェックに失敗した場合、Stop/Startする
  • ステータスチェックに成功するまでループ

Stop/Startしているのは、AWS側の問題(EC2インスタンスの物理ホストの問題)であった場合、Stop/Startして物理ホストを変更させる為です。

スクリプト

#!/bin/sh

echo "# Start"
i=1

INSTANCE_ID=$1

echo "# 1st Start Instance"
aws ec2 start-instances --instance-ids $INSTANCE_ID
timeout 300 aws ec2 wait instance-status-ok --instance-ids $INSTANCE_ID

status_check=$?
echo "Status: ${status_check}"

while [ $status_check -ne 0 ]
do
  echo "# Stop Instance"
  aws ec2 stop-instances --instance-ids $INSTANCE_ID
  timeout 300 aws ec2 wait instance-stopped --instance-ids $INSTANCE_ID

  i=`expr $i + 1`
  echo "# ${i}nd Start Instance"
  aws ec2 start-instances --instance-ids $INSTANCE_ID
  timeout 300 aws ec2 wait instance-status-ok --instance-ids $INSTANCE_ID

  status_check=$?
  echo "Status: ${status_check}"
done
echo "# End"

こんな感じで、インスタンスIDを引数につけて実行します。

$ ./start_ec2.sh i-XXXXXXXX

ポイントは、aws ec2 waitを使ってステータスを確認していることです。waitでインスタンスの状態を確認するのは以下の5種類があります。

  • instance-exists
  • instance-running
  • instance-status-ok
  • instance-stopped
  • instance-terminated

このうちinstance-runningでは、EC2インスタンスが起動していることは確認できますが、ステータスチェックの失敗は確認できません。System Status Checksは成功したけどInstance Status Checksは失敗した場合など、Status Checks=1/2となっている場合にはOKと判断されてしまいます。そこで今回はinstance-status-okでステータスチェックを確認しています。

またtimeoutコマンドでaws ec2 waitにタイムアウトを設定しています。aws ec2 waitはそのまま実行するとタイムアウトがありません。この為いつまでも起動や停止がしない場合はそこでスクリプトが止まってしまいます。そこでtimeoutコマンドで300秒のタイムアウトを設定しています。

さいごに

今回のスクリプトではステータスチェックに成功しない限り無限ループで起動を試行しますが、3回失敗したらメール通知、のような形にするのも良いですね。 今後もこういったスクリプトを作ったらブログで共有していきます!