概要
ユーザーデータでやってたけど、Amazon Linux2からUpstartが廃止されてSystemdに移行されたこともあり、今後も何かあると正直めんどくさいと思ったからCloudWatch Eventsに移行しました。
なぜまだスポットインスタンスなんて使っているの?
Fargateにしたいけど高いからです。オンデマンドと比べて8%~20%超で割高なのでまだ使えないです。
あとは起動が若干遅かったりするみたいなので。
やり方
CloudWatch Event を作成
以下のコンディションで作成すると全てのスポットインスタンスの中断が拾えます。
{
"detail-type": [
"EC2 Spot Instance Interruption Warning"
],
"source": [
"aws.ec2"
]
}
Lambda Function を作成
CloudWatch Event の通知先にする Lambda Function を作成します。
今のアプリケーションは以下の構成で動いています。
- LB
- AutoScaling Group
- ECS(EC2)
なので、イベントが通知されたら以下の処理を Lambda で実行するように実装します。(boto3)
- autoscaling.describe_auto_scaling_instance
s でインスタンスの情報を取得
- autoscaling.detach_instances
で AutoScaling Group からインスタンスをデタッチ
- この時 ShouldDecrementDesiredCapacity=False
で DesiredCapacity を変更しないように注意
- ecs.list_container_instances
で containerInstanceArns
を取得
- ecs.update_container_instances_state
で DRAINING
まとめ
AutoScaling Group の Desired Capacity を変更しないことと、即座に ECS Instance を DRAINING にすることでパフォーマンスに影響させることなくスケーリングを持続できます。
注意すること
中断リクエストから EC2 Instance の Terminate まで2分しか余裕がないので、Fluentd などでログを転送している場合などは Flush のインターバルを考慮するなど、アプリケーションが中断される際に気をつけることを先にやっておくと良いかもしれません。