CloudFormation の更新、ついに Instance Refresh で賢くなったよ!
やっほー、しぃちゃんだよ!今日は CloudFormation でインスタンス更新するときの選択肢が増えたよっていうニュースを見つけたの。地味に見えて運用してる人にはかなり刺さる話だから、さっそく紹介しちゃうね!
AWS What's Newなにが発表されたの?
AWS What's New によると、Amazon EC2 Auto Scaling が新しい AWS CloudFormation 更新ポリシーとして「Instance Refresh」をサポートしたよ。テンプレートに AutoScalingInstanceRefresh という新しい更新ポリシーを設定しておくと、インスタンスの置き換えが必要なプロパティ(LaunchTemplate や VPCZoneIdentifier など)を更新したときに、CloudFormation が自動で Instance Refresh をトリガーしてくれるようになるの。
この機能自体はすべての AWS リージョンで、追加料金なしで使えるよ。
今までどうだったの?
これまで CloudFormation で Auto Scaling グループのインスタンスを入れ替える更新をするときは、AutoScalingRollingUpdate(ローリングアップデート)を使うのが定番だったの。でも、このローリングアップデートには結構クセがあって、CloudFormation の公式ドキュメントにもはっきり書いてあるんだけど、
Rolling updates don't honor the instance maintenance policy configured on your Auto Scaling group. During a rolling update, healthy capacity can drop below the MinHealthyPercentage set on the group, and CloudFormation doesn't launch new instances before terminating existing ones, regardless of MaxHealthyPercentage.
つまり、Auto Scaling グループ側でせっかく設定した「インスタンスメンテナンスポリシー」が無視されちゃったり、新しいインスタンスを先に起動してから古いのを消す(launch-before-terminate)ができなかったりしたんだよね。しかも、更新中に Auto Scaling の処理(スケーリングポリシーやヘルスチェックなど)が邪魔しないように SuspendProcesses でわざわざ一時停止させる必要があったの。ターミネーションポリシーやスケールイン保護みたいな Auto Scaling の便利機能も、ローリングアップデート中は使えなかったんだって。
これで何が変わるの?
AutoScalingInstanceRefresh ポリシーを使うと、CloudFormation の更新が Auto Scaling 本来の Instance Refresh の仕組みに乗っかる形になるから、こんな機能がまとめて使えるようになるよ。
- ルートボリュームの置き換え(
ReplaceRootVolume戦略)でインプレース更新ができる - launch-before-terminate(新しいインスタンスを先に立ち上げてから古いのを終了)
- アラームベースのモニタリング(CloudWatch アラームを見張って、しきい値を超えたら自動でロールバック)
- チェックポイント+ベイク時間による段階的なロールアウト
しかも Auto Scaling のスケーリングポリシーやヘルスチェックは更新中もそのまま動き続けるから、デプロイのあいだサービスの安全網が外れる心配がないの。プロセスをいちいち SuspendProcesses で止めなくていいのも地味に嬉しいポイントだよ。ロールバックも CloudFormation のスタックロールバックの仕組みにそのまま乗るから、失敗したときの挙動もシンプルになるの。
深く潜ってみよう
設定は UpdatePolicy の中に AutoScalingInstanceRefresh を書くだけ。こんなイメージだよ。
UpdatePolicy:
AutoScalingInstanceRefresh:
Strategy: Rolling
Preferences:
MinHealthyPercentage: 90
MaxHealthyPercentage: 120
InstanceWarmup: 300
CheckpointPercentages:
- 50
- 100
CheckpointDelay: 3600
BakeTime: 600
SkipMatching: true
ScaleInProtectedInstances: Wait
StandbyInstances: Wait
AlarmSpecification:
Alarms:
- my-error-rate-alarm
CloudFormation ドキュメント(Template Reference)の情報を拾うと、細かい仕様も結構はっきりしてるよ。
Strategyは必須で、RollingかReplaceRootVolumeのどちらかを指定するAutoScalingInstanceRefreshとAutoScalingRollingUpdateは同じ Auto Scaling グループに同時指定できない(両方書くとスタック更新が失敗する)- Instance Refresh がトリガーされるのは、
LaunchTemplate/MixedInstancesPolicy/VPCZoneIdentifier/AvailabilityZones/AvailabilityZoneIds/PlacementGroupのいずれかを変更したときだけ MinHealthyPercentageとMaxHealthyPercentageの差は 100 以内にする必要があり、範囲を広げるほど同時に置き換えられるインスタンス数が増えるBakeTime(完了とみなすまでの待機時間)とCheckpointDelay(チェックポイント後の待機時間)はどちらも最大 172800 秒(48 時間)まで指定可能CheckpointPercentagesはチェックポイントのしきい値リストで、全台を置き換えるなら最後の値を 100 にする必要があるScaleInProtectedInstancesとStandbyInstancesはそれぞれRefresh/Ignore/Waitから選べ、デフォルトは両方ともWait(1 時間待って解除されなければ失敗)- Auto Scaling グループは同時に 1 つしか Instance Refresh を実行できないので、手動で Instance Refresh を走らせている最中にこのポリシーでスタック更新すると失敗することがある
- 従来の
cfn-signalヘルパースクリプトは使えず、インスタンスの準備完了を待ちたい場合はautoscaling:EC2_INSTANCE_LAUNCHINGライフサイクルフックを使う - フォワード・ロールバックそれぞれ CloudFormation のリソースタイムアウト(36 時間)の制約を受けるので、長時間かかる Instance Refresh を組む場合はスタックにサービスロールを設定しておくのが推奨されている(一時クレデンシャルの期限切れ対策)
まとめ
- CloudFormation に新しい更新ポリシー
AutoScalingInstanceRefreshが追加され、Auto Scaling の Instance Refresh をそのままスタック更新に使えるようになった - ルートボリューム置き換え・launch-before-terminate・アラーム監視・チェックポイント+ベイク時間などが使え、更新中もスケーリングポリシーやヘルスチェックが有効なまま
- ロールバックは CloudFormation のスタックロールバックに統一され、全リージョンで追加料金なしで使える
- 従来の
AutoScalingRollingUpdateは同時指定不可で、SuspendProcessesなどの制約もそのまま残る
CloudFormation で Auto Scaling グループを運用してて、更新のたびにヒヤヒヤしてる人にはかなり刺さる話だと思うよ!