マネージドサービス部 佐竹です。
本ブログでは、Amazon EC2 において「オンデマンドキャパシティー予約」の監視が可能となったというアップデートについて記載していきます。
- はじめに
- アップデートで監視が可能となった3つのオプション
- AWS Health Dashboard と E メールで行われる通知
- EventBridge events を利用した通知
- CloudWatch メトリクスで ODCR を監視する
- まとめ
はじめに
2023年3月末頃に、以下のドキュメントにある通り EC2 のオンデマンドキャパシティー予約("ODCR" とも省略します)が監視可能となりました。
まずはこの「オンデマンドキャパシティー予約」についての簡単な説明を行い、その後にこの機能が内包する課題について整理していきます。
オンデマンドキャパシティー予約について
本機能の詳細な仕様については以下の過去ブログに譲るとして、ここではざっくりと概要と利用時の注意点を記載します。
以下の通り、3つにまとめました。
- オンデマンドキャパシティー予約は"オンデマンドの費用"(定価)を毎時間支払うことでキャパシティーを予約することが可能になる機能
- キャパシティーを予約しインスタンスに割り当てておくことで、EC2 起動時の InsufficientInstanceCapacity エラーの回避が可能になる
- ただし、オンデマンドキャパシティー予約は実際にインスタンスを起動していなくても「予約している」だけで費用が請求され続ける
例えるなら、オンデマンドキャパシティー予約は「座席の確保」です。座席を確保しておけば、その場所に行ったとき自分はいつでも席に座れます。
ただし、座席を確保している場合、その座席には他の人は座ることができません。このため座席を確保している=予約している時間は「座ってようが座ってなかろうが、使用料を頂きますよ」という契約です。
運用上の課題と Savings Plans でのディスカウント
運用上の課題について記載します。
先の例の通り「座席の確保」を購入したとして、注意すべき点は何でしょうか?
そう、「座席の確保権」そのものを返却しないと、「座ってようが座ってなかろうが」いつまでもお金がかかるということです。
このため、オンデマンドキャパシティー予約が不要になった場合は、その予約を取り消す必要があります。予め「期限」を設定することもできますが、期限を設定しない利用方法の方が多いでしょう。
もしインスタンスの利用が終了しても、オンデマンドキャパシティー予約を取り消さない場合、以下の費用が発生します。
Unused Reservation
Linux t4g.nano のキャパシティーを予約し、それを利用していない時間には、以下の明細が Bills に表示されます。
- $0.0054 per Unused Reservation Linux t4g.nano Instance Hour
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406214019.png)
実際の Bills の画面キャプチャは上の通りです。
このように、オンデマンドキャパシティー予約を意図せず残し続けると無駄な費用(Unused Reservation)が発生し続けてしまいます。
今回は、このような無駄なコストを如何に検知して防止するか、というコスト最適化運用の話をしていきます。
Savings Plans でのディスカウントに注意
ただ、ここで同時に掲載されている以下の明細が気になるでしょう。
- Unused OD Capacity Reservation for t4g.nano Linux instance usage covered by Compute Savings Plans
これは、Savings Plans がオンデマンドキャパシティー予約をディスカウントした明細です。
オンデマンドキャパシティー予約の費用は、Savings Plans から見ると通常の EC2 インスタンスのオンデマンド費用と同じ扱いです。よって、Savings Plans によってディスカウントすることができます。
これにより、Unused Reservation は 0 USD になっています。
そしてこの「合計 0 USD」という料金がオンデマンドキャパシティー予約の無駄な出費をより分かりにくくしてしまいます。
何故なら、「パッと見は0円」だからです。費用が安い or 見えないコストほどチェックから漏れやすいため「Unused OD Capacity Reservation」はコスト最適化のチェック漏れを誘発させてしまう可能性があります。
このため、ディスカウント前の「Unused Reservation」を正しく把握し、コスト最適化をしていく必要があることも合わせて認識しておいてください。
アップデートで監視が可能となった3つのオプション
「オンデマンドキャパシティー予約」の監視が可能となったというアップデートについて公開された AWS 公式ドキュメント「Monitoring Capacity Reservations」には以下の3つが記載されています。
- CloudWatch metrics
- EventBridge events
- Utilization notifications
今回は、この順番を使い勝手の観点から逆とし、下から順に機能を説明していきます。
※記載してから知ったのですが、CloudWatch metrics は数年前から確認ができたようです
AWS Health Dashboard と E メールで行われる通知
AWS ドキュメントでは「Utilization notifications」となっている本項目が最も利用しやすいと思われますので、まずはこれから記載します。
Utilization notifications は、AWS 側からのプッシュ通知です。
具体的には、該当 AWS アカウントで作成中のキャパシティー予約の使用率が 20% を下回ると、AWS Health は次の E メールと AWS Health Dashboard 通知を送信するようになりました。
- 過去 24 時間の使用率が 20% を下回った、新しく作成された各キャパシティー予約に関する個別の通知
- 過去 7 日間の使用率が 20% を下回ったすべてのキャパシティー予約の概要通知
つまり、作ったばっかりで正しく使われていないものはすぐに通知し、ずっと使っていたが取り消し忘れなどで使用率が下がったものも7日間の分析結果から通知をしてくれる、という機能です。
実際に送信されたメール
作成して2日間ほど放置していると [Action Recommended] EC2 ODCR Underutilization Notification
という件名でメールが送信されました。以下が実際のメールの内容です。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230407/20230407213133.png)
以下で抜粋した箇所が非常に良い内容だと感じます。
Capacity Reservation ID: cr-077c893863085fe93 Availability Zone: ap-northeast-1a Instance type: t4g.nano Platform: Linux/UNIX Utilization Rate: 0.0%
これと同時に、AWS Health Dashboard には以下がイベントログとして登録されていました。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406215902.png)
Status が空のため、少々見落とし安いかもしれませんが、合わせて確認してみてください。Push 通知としては E メールでの通知がかなり優秀だと感じました。
EC2 ODCR Underutilization Notification Summary
2つ目の「過去 7 日間の使用率が 20% を下回ったすべてのキャパシティー予約の概要通知」を示すメールである [Action Recommended] EC2 ODCR Underutilization Notification Summary
を受け取りましたので参考まで画面キャプチャーを張ります。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230411/20230411110004.png)
こちらは複数の ODCR が記載される想定のため、パイプで疑似的なテーブル作成しているようです。
EventBridge events を利用した通知
Amazon EventBridge では EC2 インスタンスや Direct Connect のメンテナンス通知を「AWS Health Event」として検出し、Slack 等に通知が可能です。具体例として、以前 EC2 インスタンスの通知についてはブログに記載しました。
今回、本通知設定にも対応しています。AWS ドキュメントでは「Monitor Capacity Reservations using EventBridge」となっています。
具体的には以下の2つのイベントが追加されています。
- AWS_EC2_ODCR_UNDERUTILIZATION_NOTIFICATION
- AWS_EC2_ODCR_UNDERUTILIZATION_NOTIFICATION_SUMMARY
実際に、前者の個別の通知を EventBridge から Slack へと通知してみました。
Event pattern
Amazon EventBridge に設定する「Event pattern」は以下がそのままご利用いただけます。
{ "source": ["aws.health"], "detail-type": ["AWS Health Event"], "detail": { "service": ["EC2"], "eventTypeCategory": ["accountNotification"], "eventTypeCode": ["AWS_EC2_ODCR_UNDERUTILIZATION_NOTIFICATION"] } }
もし、既に "eventTypeCategory": ["accountNotification"]
を eventTypeCode
に関係なく検出する設定をされている方は、それに自動的に含まれますので追加の設定は不要かと存じます。
実際に検出されたイベント
以下が AWS Chatbot から Slack に連携された通知です。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406221156.png)
Email と異なり、直接 Slack に通知させることが可能ですので、運用上はこちらのほうが気付きやすいと思われます。
ただ、改行コードが文字扱いとなっており、コードのままになってますので可読性が低い状況でした。正直メールのほうが見やすいと感じます。
CloudWatch メトリクスで ODCR を監視する
さて、ここまではある程度時間がかかってから検出される、という設定をそれぞれご紹介しましたが、Amazon CloudWatch を利用することでほぼリアルタイムのオンデマンドキャパシティー予約の監視も可能になっています。
これは AWS 公式ドキュメントで「Monitor Capacity Reservations using CloudWatch metrics」として記載があります。
ここから先は、CloudWatch メトリクスで実際に監視設定を行い、アラームを発生させて Slack へ連携するところまで動作確認していきます。
利用するメトリクス
以下の4つのメトリクスを利用して監視していきます。
- UsedInstanceCount
- AvailableInstanceCount
- TotalInstanceCount
- InstanceUtilization
CloudWatch メトリクスの動作検証
今回は、実際にそのうちの2つ「UsedInstanceCount」と「AvailableInstanceCount」がどのようなメトリクスなのか実例を紹介します。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406223745.png)
まずは検証用に capacity reservation を作成します。その後少しの時間を放置して待っておきます。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406223821.png)
その後、インスタンスを構築してオンデマンドキャパシティー予約を紐づけていきます。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406223928.png)
Capacity Reservation ID に、作成した capacity reservation の ID が含まれていることを確認します。
では、この作業結果としてどのように CloudWatch にメトリクスが登録されたでしょうか。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406224015.png)
今回の作業例では「AvailableInstanceCount」は作成した ODCR の台数である「1」から始まり、それが割り当てられたタイミングで「0」に下がりました。「UsedInstanceCount」はその反対の動きになっています。
この状態で、さらにキャパシティーを追加してみます。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406224244.png)
追加で、2台分の確保を行う capacity reservation を追加しました。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406224333.png)
キャパシティーの ID ごとにメトリクスは分割されるので、それぞれの「AvailableInstanceCount」を選択します。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406224431.png)
先の1台の「AvailableInstanceCount」は0のまま、新たな「AvailableInstanceCount」が2として表示されました。
さて、ここまでの動作確認を行った結果として、今回やりたい監視用途に適していると感じました「利用可能なオンデマンドキャパシティー予約の残数」を表す「AvailableInstanceCount」を使ってこの先アラームの設定を試みていきます。
CloudWatch アラームの作成
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406224856.png)
「Create alarm」を押下して、「Select metric」からはじめていきます。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406224931.png)
先の実例の通り、「AvailableInstanceCount」は各 CR-ID ごとに別になってしまうため、全体を監視するにはこれらを全て足し合わせていく必要があります。そして「AvailableInstanceCount」の合計値が「0ではない場合にはアラーム」=無駄が発生しているとする監視想定です。
Metrics Insights - query builder から、以下の通り選択します。
- Namespace: AWS/EC2CapacityReservations (No Scheme)
- Metric name: MAX(AvailableInstanceCount)
ここで「MAX(最大値)」を利用するのは、可能な限り即通知をすることをターゲットにしているためです。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406225437.png)
「Run」を押下すると SELECT MAX(AvailableInstanceCount) FROM "AWS/EC2CapacityReservations"
という Details が Graphed metrics に表示されます。表示内容に問題が無ければ「Select metric」を押下して続けます。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406225719.png)
今回、「Conditions」では「0 より大きな値は全てアラーム」としたいため、「Greater」のまま数値は「0」を入力します。これで「値>0」になるため、「AvailableInstanceCount」が1つでもあればすべて検出されます。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406225832.png)
Datapoints to alarm はシビアに設定するため「1 out of 1」としています。また、特にメトリクスに値がない場合は「Treat missing data as good」とします。オンデマンドキャパシティー予約が1つも作成されていない場合は「何も無駄はない」と言えるためです。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406230044.png)
通知先は SNS Topic を選択し、AWS Chatbot から Slack へと連携します。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406230128.png)
Alarm name は分かり易い名前であれば問題ないでしょう。今回は「AvailableCapacity」としておきました。
最後に確認し問題がなければ「Create alarm」で作成を完了してください。
アラームの動作確認
未使用オンデマンドキャパシティー予約がある場合
作成されたばかりの「AvailableCapacity」は、0 より大きな値を閾値としているため、アラームの線はコンソール上で 0 を示します。
現在、無駄になっているオンデマンドキャパシティー予約は2台あるため、すぐにアラームが発砲される想定です。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406230452.png)
数分の時間が経過すると Slack にアラームが連携されました。Slack に連携されたグラフからも、監視アラームの閾値が0台に設定されていることと、現在2台の無駄があることがわかります。
未使用オンデマンドキャパシティー予約をキャンセルした場合
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406230604.png)
無駄になっている2台分のオンデマンドキャパシティー予約を取り消してみます。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406230644.png)
「Cancel reservation」でキャンセルします。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406230741.png)
問題がなければ、すぐにキャンセルされます。
さて、この状態で CloudWatch アラームはどうなったでしょうか。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406230842.png)
15分程度待つと無事にアラームは解消され、OK ステータスになりました。問題なさそうです。
キャパシティー予約を利用中のインスタンスを停止した場合
では次に、1台分のオンデマンドキャパシティー予約を利用している EC2 インスタンスを停止してみます。
インスタンスの停止中は、オンデマンドキャパシティー予約を使ってない状態になるため再度アラームが発生する想定です。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406231003.png)
キャパシティーが割り当たっているインスタンス「i-09cf51c9518cb3a9d」を停止します。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406231105.png)
停止して、CR-ID が消えたことを確認します。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406231211.png)
これと同時に、Capacity Reservation の項目 Qty Available(利用可能な台数)が 0 から 1 に増えました。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406231312.png)
想定通り、再度アラーム状態になりました。
キャパシティー予約を全て削除した場合
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406231526.png)
最後に、残りの1台分のオンデマンドキャパシティー予約も取り消してしまいましょう。これでオンデマンドキャパシティー予約は「0」になります。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406231754.png)
オンデマンドキャパシティー予約を全て削除すると、「AvailableCapacity」の値は消失します。
この場合、事前設定の「Treat missing data as good」の通り CloudWatch アラームは「OK」となり回復しました。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406231945.png)
なお、OK ステータスも Slack に連携しておくことでアラームが OK へと回復したことが認識しやすくなるので、合わせて設定することを推奨します。
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406232227.png)
設定方法は「Configure actions」の「Alarm state trigger」で、「In alarm」だけではなく「OK」を選択したトリガーも追加しておくだけです。
以上で動作検証は完了です。
CloudWatch アラーム設定のセンシティブさの調整
![](https://cdn-ak.f.st-hatena.com/images/fotolife/s/swx-satake/20230406/20230406234612.png)
今回はほぼ即時の通知を実現したいためにかなりセンシティブな設定を行っていますが、上図のようにオンデマンドキャパシティー予約を持っているインスタンスを、何かの理由により毎日停止するような場合、今回のようなアラーム設定では毎日インスタンスが停止する度にアラームが発生してしまいます。
本設定はあくまで一例ですため、実際の運用に沿ったアラーム設定を行ってください。
まとめ
2023年3月末頃から、EC2 のオンデマンドキャパシティー予約が監視可能となりました。
これにより、今まで監視が難しかったコストの無駄を簡単に通知したり、監視したりできるようになりました。コスト最適化の視点で非常に有用なアップデートだと感じます。
実際、弊社ではこのようなコストの無駄を可視化するために、カスタムの社内レポートを Salesforce で作成しており、各エンドユーザ様に解消を試みて頂くように連絡する運用を始めたばかりでした。
ですが、今回のアップデートによりこの運用も無くて済みそうです。
何も設定せずとも送られてくる E メールによる Utilization notifications がまず非常に有用です。合わせて AWS Health Dashboard にもこれは掲載されます。
任意で通知がしたい場合は Amazon EventBridge にて検出可能であり、さらにメトリクスを監視してアラームとしたい場合は Amazon CloudWatch が有効活用できることもわかりました。
今回のブログでは全ての機能を動作検証するために少々時間を要してしまいましたが、その分詳細なブログになったかと存じます。本記事によって皆様の AWS アカウントのコスト最適化がさらに一歩進むことになれば嬉しく思います。
では、またお会いしましょう。
佐竹 陽一 (Yoichi Satake) エンジニアブログの記事一覧はコチラ
マネージドサービス部所属。AWS資格全冠。2010年1月からAWSを利用してきています。2021-2022 AWS Ambassadors/2023-2024 Japan AWS Top Engineers/2020-2024 All Certifications Engineers。AWSのコスト削減、最適化を得意としています。