[アップデート] EC2 Auto Scaling のインスタンス更新機能で、自動ロールバックの条件に任意の CloudWatch アラームを含めることが出来るようになりました

2023.08.10

いわさです。

AWS では、起動テンプレートと Auto Scaling グループを使うことで EC2 インスタンスのスケールアウト、スケールインを自動化することが出来ます。
そして、Auto Scaling グループではインスタンス更新機能があり、グループ内で稼働中のインスタンスを指定したルールに従って新しいインスタンスに置き換える機能があります。

このインスタンス更新機能ですが、新しく置き換わるインスタンスに何らかの問題が生じた(起動テンプレートや AMI に不備があるなど)場合に備えたオプションとして「自動ロールバック」の機能があります。
何らかの理由でインスタンス更新に失敗した場合に自動で、置き換わる前の古い構成に基づいたインスタンスが起動しなおされるというものです。

以前までは自動ロールバックの条件は「インスタンス更新に失敗した場合」という Auto Scaling グループにお任せすることしか出来なかったのですが、先日のアップデートで任意の CloudWatch アラームをインスタンス更新処理に関連付けて、自動ロールバックをトリガーさせることが出来るようになりました。

本日は実際にこちらを使ってみましたので、注意点なども含めて解説したいと思います。

インスタンス更新機能と CloudWatch アラーム

Auto Scaling グループの作成後に、対象グループの「インスタンスの更新」タブからアドホックで実行することが出来ます。

インスタンスの更新情報としては、例えば起動テンプレートの新しいバージョンを使うとか、あるいはインスタンス更新の際に複数台で構成されている場合に何台づつ置き換えを行っていくかなどを指定することが出来ます。
今回こちらの設定に次のように CloudWatch アラームを指定することが出来るようになりました。

インスタンスの更新中に、関連付けした CloudWatch アラームが「アラーム状態」になった際に自動ロールバックが開始されます。
CloudWatch アラームは最大 10 件まで関連づけすることが出来るとのことです。

CloudWatch アラームが作動する環境を用意する

この機能のユースケースとしては自動ロールバックのトリガーとして、例えば Auto Scaling グループの集計メトリクス(全体の CPU 使用率とか)や、あるいはロードバランサーのエラーステータスコードなどを対象にする用途で用意されたもののようです。

ここではシンプルに対象 Auto Scaling グループの CPUUtilization に対して静的しきい値を設定したアラームを作成してみます。
この時点ではグループ内に正常なインスタンスが存在しており、アラームは次のように正常な状態となっています。

ここで、起動テンプレートの新しいバージョンを作成しましょう。
新しい起動テンプレートで開始された EC2 インスタンスは次の記事を参考に自動で CPU 使用率が負荷状態となってしまうように構成してみます。

#!/bin/bash
dnf install stress -y
stress -i 1

試しに上記をユーザーデータへ設定し Amazon Linux 2023 を起動させてみると次のように開始直後から平均 CPU 使用率が高い状態となっていました。
良さそうです。

このユーザーデータを起動テンプレートにも設定しておきます。
これで、この起動テンプレートを使って先程の Auto Scaling グループでインスタンスが起動されると、CloudWatch アラームが、アラーム状態となるはず。

自動ロールバックを有効化してのインスタンス更新が必要

では Auto Scaling グループのインスタンス更新を行ってみましょう。
いくつか注意点があります、まずは当たり前ですが CloudWatch アラームを関連付けることを忘れないように。デフォルトでは何も設定されておらず、前回使われたアラームが使われるわけでもないようです。

また、自動ロールバックはデフォルトでは毎回無効になっています。
「必要な設定」を変更しつついくつかの前提条件を満たすことで自動ロールバックを有効化させることが出来ます。
前提条件については冒頭の公式ドキュメントも併せてご確認ください。有効化出来ないよくあるパターンだとデフォルトバージョンや Latest バージョンを使用している場合などです。

なお自動ロールバックが有効になっていない場合は、CloudWatch アラームによってインスタンス更新は失敗となりますが、ロールバックはしません。

ちなみにデータ不足あるいは、既にアラーム状態であるアラームを指定するとインスタンス更新操作がそもそも失敗しますので、事前にアラームの状態を確認しておきましょう。

A CloudWatch monitor is in alarm. The instance refresh cannot start.

1 台起動された Auto Scaling グループで実行

まずは希望する台数が 1 台の Auto Scaling グループで実行してみました。
インスタンス更新を開始すると、早速次のようにインスタンスの置き換えが開始されました。

新しい EC2 インスタンスが起動され、古いインスタンスは終了されています。
新しいインスタンスの CPU 使用率は期待どおり高い状態ですね。

しかし、インスタンス更新ステータスは正常で終了してしまいました。
CloudWatch アラームが発生する前に完了してしまいましたね。

少し経ってから CloudWatch アラームがアラーム状態に変わりました。
ただし、既にインスタンス更新は完了しているので、ここからロールバックされたりはしません。

ローリングアップデートさせてみる

今度は Auto Scaling グループの希望する台数を複数台にして、ローリングアップデートを試みてみます。
今回は 3 台で実施してみました。

インスタンス更新時のパラメータで「最小正常率」が 90 % になっているため、1 台づつ更新されるはず。
おっ、今度は 1 台づつゆっくり更新されているせいか、インスタンス更新中に CloudWatch アラームがアラーム状態となりました。

インスタンスの更新ステータスが「失敗」になり、ロールバックが進行しています。
また、ロールバックの理由には「この CloudWatch アラームに引っかかってるでー」と記載されてますね。良いぞ。

ロールバックが進行し、起動テンプレートの新しいバージョンによって作成された CPU 使用率が異常なインスタンスが全て終了となり、旧バージョンのインスタンスが新規で開始されていますね。

このままロールバックが正常に完了しました。

さいごに

本日は EC2 Auto Scaling のインスタンス更新機能で、自動ロールバックの条件に任意の CloudWatch アラームを含めることが出来るようになったので確認してみました。

インスタンス更新のタイミングとアラーム状態になるタイミングにずれがあるとうまく動作しませんでしたので、アラーム条件は少し気をつける必要がありますね。反応が遅いアラームを設定するとインスタンス更新が先に完了してしまいそうです。