Systems Manager で実現する祝日対応の計画的な EC2 停止起動処理をやってみる!

2020.03.29

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

園部です。

開発やステージング環境の EC2 を不要な時に、停止して利用料金を削減するという取り組みは多くのユーザーで実施されている施策ではないかと思います。私も以前所属していた会社では平日夜間・土日は停止し、平日朝に起動を行っていました。

そんな EC2 停止&起動処理ですが、いくつかの実現方法があります。(たぶんもっとある...

  • CloudWatch Event( EventBridge ) + Lambda
  • CloudWatch Event( EventBridge ) + SSM Automation
  • AWS Instance Scheduler
  • サードパーティ製品
  • EC2(Linux なら cron 、Windows ならタスク)上で CLI 等から実行

先に挙げた方法は、一長一短で例えば以下のような課題があげられます。

  • 実行用 EC2 を用意すると管理が必要となる
  • 対象リストを作成すると管理が煩雑になる
  • 自前のコードを書くとコード管理が必要となる
  • 日本の祝日や除外日への対応が難しい

個人的な見解としては、こういった何かを軽減する施策では、出来るだけマネージドサービスを利用して、関係者に違う負担が増えないことを意識することも重要だと考えます。前置きが長くなってしまいましたが AWS Systems Manager( 以降、SSM )で、前述の課題を軽減する仕組みをやってみたいと思います!

構成

実行環境問題

SSM Automation を利用することでユーザー側で実行環境に関する管理を行わないで済む様にします。

対象リスト問題

ここでは他の方法でも採用されている Tag ではなく リソースグループ を利用していきます。

  • Tag が env:dev となっているインスタンスを blog をいうリソースグループとします。

なぜ Tag だけの管理ではないのかというと、起動時の処理が意図した動作をしなかったからです。これは仕様なのか不具合なのか判断が出来なかった点と今回の目的にとってはどちらの方法でも問題ないと判断したためです。

コード管理問題

SSM Document をベースに少し手を加える程度にして、管理を最小限にします。

祝日や除外日問題

SSM Change Calendar + Maintenace Window を組み合わせることで実行日と実行禁止日を定義します。

やってみる

EC2 への Tag 付与

対象とする EC2 へ Tag を付与します。 今回は env:dev とします。

リソースグループ( blog )作成

リソースグループ >>> グループを作成します を選択

タグベース を選択し、先ほど付与した Tag を条件に指定して作成します。

SSM Change Calendar 作成

SSM >>> カレンダーの変更 >>> Create changes calendar を選択

カレンダーの名称等は好きな名称を記入しておきます。 ポイントとなるのは Open By default を選択することです。 こちらのタイプは、カレンダーにイベントを作成していない日以外は処理が実行されます。つまり、祝日や除外日をカレンダーにイベントとして登録することで処理をスキップすることが可能です。

反対に Closed By dafault を選択し、実行を許可する日をイベント日として登録することでも実現は可能です。個人的にはその日がなぜ実行されないかが把握出来るために実行しない日をイベント日とするのが良いかなと思います。これはイベントとして登録する日の数や考え方によると思います。

指定した日の起動処理が実施されないため、前日最後に停止した EC2 は起動しません。

作成したカレンダーを選択します。

SSM Change Calendar イベント(処理除外)日を作成

繰り返しになりますが、自動停止&起動処理が不要な日をイベントとして登録していきます。

毎週土日を登録

毎週土日は利用しないことを想定して停止しておきます。

Create event を選択

名称は土日用であることがわかる内容を記載します。

4月の土日から月末までを連続で登録します。

登録されました。 4月4日 土曜日に二つのイベントが登録されているのは、開始日として登録した分と繰り返しの分が重複して登録されているためです。。

祝日や作業日を登録

同じ要領で、祝日や停止したい日を登録していきます。(csv で登録出来たらなんと嬉しいだろうか...

カレンダーに対応する処理(ドキュメント)を作成

停止用ドキュメント

ドキュメントビルダーを利用して作成していきます。

SSM >>> 共有リソース >>> ドキュメント >>> Create automation を選択

ドキュメント名と説明を入力します。

ここでは ドキュメントで共通とするパラメータを定義します。

次に、作成した Change Calendar から実行可能な日かをチェックするステップを作成します。

新しいステップを追加 を選択

EC2 を停止するステップを作成します。

Create automation を選択します。

起動用ドキュメント

停止用ドキュメントを参考に、起動用ドキュメントを作成します。

実行のスケジューリング

SSM Maintenance Window を利用して毎日特定の時間に実行されるようにスケジュールします。

SSM >>> メンテナンスウィンドウ >>> メンテナンスウィンドウの作成 を選択

ここでは、毎日 23:00 に停止が実行されるように設定して作成します。

作成したメンテナンスウィンドウを選択 >>> アクション >>> ターゲットの登録 を選択

今回は リソースグループ を利用して対象を管理するため リソースグループ からターゲットを登録します。

作成したメンテナンスウィンドウを選択 >>> アクション >>> オートメーションタスクの登録 を選択

先ほど作成したターゲットおよびドキュメントを指定して登録します。

ここで実行権限(EC2 停止、SSM 実行、リソースグループ参照)を持つロールを指定します。入力パラメータでは 疑似パラメータ を指定します。

同じ要領で、起動用メンテナンスウィンドウを作成します。

検証 01

まずは、カレンダーを意識せずに メンテナンスウィンドウでの処理を検証します。(既にカレンダーを参照する処理となっているのでカレンダーでイベントが入っていない実行可能な日時で実施)

  • 23:05 停止
  • 23:10 起動

停止処理が実行され、ステータスが成功になりました。

EC2 コンソールでも停止になっています。

起動処理が実行され、ステータスが成功になりました。

EC2 コンソールでも起動になっています。

問題なくメンテナンスウィンドウを利用して、停止起動の処理が実行できました。

検証 02

続いては、カレンダーにイベント日を登録して、処理が行われないことを確認します。

まずは、Change Calendar で作成したカレンダーに以下の時間帯を登録します。

メンテナンスウィンドウを上記のイベント内に指定します。

流れとしては、前日処理で停止まで完了しているため、イベント日の起動が実行されずに起動しないことを確認します。あわせて、停止処理も不要なので実行されないことを確認します。

意図した通り処理が失敗になっています。

詳細を確認すると、Calendar の状況が 「OPEN」 ではなく 「CLOSED」 であることが原因と記載されています。

おまけ: なぜ対象指定を Tag にしなかったのか?

当初は Tag で管理し、対象としてメンテナンスウィンドウのターゲットとする想定していました。ところが、停止処理は意図した通り、停止まで正常に実行されたのですが、起動処理で意図した動作を得ることが出来ませんでした。

処理のステータスとしては 成功 となるのですが実際に EC2 は起動されません。こちらはブログを書いている中で、検証を行っている際の処理結果ですが、ステータスの詳細には "No Invocations to execute" と表示されています。

対象がなく、処理が空振りになった時と同じ状況です。 同一 ドキュメントを Automation 単体で Tag で指定すると正常に起動までおこわなれます。 メンテナンスウィンドウにした際の仕組みを把握することが出来ませんでしたが、おそらく停止している EC2 のタグ情報を取得できず、対象とならなかったのではないかと考えられます。

さいごに

出来るだけ再利用してもらえればと思い、画像を多く使用したこともあり長文となってしまいました。 この方法であれば冒頭で課題とした内容も解消・軽減することができます。処理自体は一度作成しておけば Tag による管理・付与を行うことで、対象の増減にも対応できます。また休日に停止を行いたくない場合は、メンテナンスウィンドウを無効にすることで対応が可能です。

これから同じような処理を検討される方にとって、一つの候補としてもらえれば幸いです。