tkuchikiの日記

新ブログ https://blog.tkuchiki.net

ステータスが cancelled の状態で動いている Spot Instance を terminate する

Jenkins EC2 Plugin を使っていたら、
ステータスが cancelled なのに動いたままのインスタンスがありました。
今まで cancelled になっていたら terminate されていたので、
cancel = terminate だと思っていたのですが、それは間違いなようです。

詳細は、スポット入札ステータス を参照していただきたいのですが、
スポット入札ステータスコードが、request-canceled-and-instance-running の場合は、

スポットインスタンスがまだ実行されている間に、リクエストをキャンセルしました。リクエストは canceled ですが、インスタンスは running のままです。

となるようです。
ステータスメッセージには、Your Spot request is canceled, but your i-xxxxxxxx is still running. と書かれます。

Spot Instance 自身にスポット入札ステータスを監視させて、request-canceled-and-instance-running の場合は、terminate するようにすれば確実そうですので、
shellscript を書きました。

自分自身に監視させる場合

[ -n "$(aws ec2 describe-spot-instance-requests --filters Name=status-code,Values=request-canceled-and-instance-running Name=instance-id,Values=$(curl -s 169.254.169.254/latest/meta-data/instance-id) | jq .SpotInstanceRequests[])" ] && halt

別のサーバから監視する場合

INSTANCE_IDS=$(echo $(aws ec2 describe-spot-instance-requests --filters Name=status-code,Values=request-canceled-and-instance-running  | jq -r .SpotInstanceRequests[].InstanceId))

[ -n "${INSTANCE_IDS}" ] && aws ec2 terminate-instances --instance-ids ${INSTANCE_IDS}

test -n で aws ec2 describe-spot-instance-requests の結果が空かどうかチェックしています。
空だとステータスコード 1 が返るので、haltterminate-instances も実行されません。
これを cron で数分毎に実行すれば良さそうです。
別のサーバから監視するスクリプトを改変する場合は、
失敗すると意図しないインスタンスが terminate される可能性がありますのでご注意ください。