EC2 SchedulerでEC2インスタンスをスケジュール操作してみた

アイキャッチ AWS EC2

西澤です。AWS利用費を少しでも節約する為に、EC2インスタンスの起動/停止をスケジューリングしたいケースは多々あると思います。以前にこんな記事を書いたことがありました。

この記事を書いた時点から今回執筆時点(2016年9月)までの関連するアップデートとしては、

  • Lambdaがスケジュールベースで起動できるようになった
  • スケジュールベースのAuto ScalingをAWS Management Consoleから操作できるようになった

あたりが関連するものになるかと思いますが、特に、スケジュールベースでLambdaを実行できるようになったことは非常に影響が大きいですね。参考までにData Pipelineを使った詳しいドキュメントも公開されていたようなので、リンクだけ貼っておきます。

で、前置きが長くなりましたが、今回ご紹介したいのは、AWS Answersというカテゴリから用意されているEC2 Schedulerです。

なんとご丁寧に"Implementation Guide"までついています。これは親切ですね。

AWS Answersとは?

EC2 Schedulerの紹介ページを見るとわかるように、こちらはAWS Anaswersという枠組みの中で紹介されているものです。非常にわかりやすく丁寧なドキュメントが用意されてはいるものの、AWSが提供するサービスそのものではなく、AWSサービスを組み合わせて利用するサンプルの1つという位置付けになると思います。ユーザが自己責任の下で利用するものとなりますので、ご理解いただいた上でご利用ください。

AWS Answers は、AWS アーキテクトが作成した説明資料の保管場所です。ここでは、アカウント管理、設定管理、ロギング、モバイルアプリケーション、ネットワーキング、セキュリティ、ウェブアプリケーションに関するガイダンスを参照できます。これらの資料を利用すると、クラウドコンピューティングの使用規模が広がるにつれて拡張する AWS クラウドにおけるアーキテクチャと操作に精通できます。 AWS Answers(クラウドでのアプリ設計、開発、運用に関するよくあるご質問) | AWS

EC2 Schedulerの概要

公式ページの説明を確認して、まずは概要を把握しておきます。尚、ここから先は、ほぼ英語ページを翻訳しつつ、実際にやってみるところまでをご紹介していくだけの内容となりますのでご了承ください。

以下の流れで処理が行われるようです。

  1. CloudFormationスタック作成時に指定したパラメータを、Dynamo DB内にデフォルト値として格納
  2. EC2インスタンスにスケジュール起動/停止したい日時に合わせてカスタムリソースタグを設定
  3. CloudWatch EventsのスケジュールイベントからLambdaファンクションを起動
  4. LambdaファンクションからEC2インスタンスのタグ情報を判定して指定の時刻に起動/停止
  5. EC2インスタンス起動/停止の記録をCloudWatchカスタムメトリクスに送信

EC2 Schedulerの設定手順

CloudFormationスタックの作成

それでは早速やってみましょう。用意されたCloudFormationテンプレートからスタックを作成するだけですので非常に簡単です。

今回、パラメータはすべてデフォルトのままで起動しました。

ec2-scheduler-1

ec2-scheduler-2

ec2-scheduler-3

ec2-scheduler-4

ec2-scheduler-5

無事に作成に成功したようです。

ec2-scheduler-6

指定できるパラメータは下記に詳しく記載されていますが、デフォルト設定で概ね問題ないのではないかと思います。デフォルトの スケジュール設定では、CloudWatch Eventsから5分おきにLambdaファンクションが実行されるようになりますが、やや冗長な気もするので、もう少し実行頻度は抑えても良いのではないかと思います。

作成されたリソースの確認

CloudWatch Eventsのスケジュールとそこから起動されるLambdaファンクションが確認できました。デフォルトでは、先に記載した通り、5分おきにLambdaファンクションが実行されます。

ec2-scheduler-7

デフォルト値を格納するDynamo DBテーブルも確認できました。こちらに設定されたデフォルト値を手動で変更しても問題ないようです。

ec2-scheduler-8

EC2へのタグ設定

CustomTagNameに指定したscheduler:ec2-startstopというタグから始まるKeyに設定したValueによって、起動/停止対象かどうか、や、その実行時刻が判定されますので、タグを付与していないインスタンスには特に影響はありません。複数のスケジュールを組み合わせて利用するパターンやデフォルト値を利用するパターン等、様々な方法で設定をすることができますので、公式ドキュメントの設定例を参考に試してみてください。

ec2-scheduler-9

参考までに公式ドキュメントに記載の設定例をいくつか転記しておきます。複数のスケジュールを1台のEC2インスタンスに指定する場合には、CustomTagNameで指定した文字列に続けて任意の文字列を追加可能です。(下記例では、"alt/long/late/short")

Tag Key Tag Value 説明
scheduler:ec2-startstop default (or true) デフォルト指定(DynamoDBに格納)時刻にStart,Stop
scheduler:ec2-startstop:alt 0800;none;utc;tue 火08:00UTCにStart
scheduler:ec2-startstop:long 0800;2200;utc;mon,wed 月水08:00UTCにStart,月水22:00にStop
scheduler:ec2-startstop:late 1500;2400;utc;tue,thu,fri 火木金15:00UTCにStart,火木金24:00UTCにStop
scheduler:ec2-startstop:short 1400;1800;utc;sat,sun 土日14:00UTCにStart,土日18:00UTCにStop

※今のところ"utc"以外の指定はできないようです

動作確認

Lambdaファンクションの実行ログ

5分おきに実行されるLambdaファンクションの実行ログを確認してみます。特に対象が存在しない場合は、下記のようになりました。全リージョン対応のスクリプトになっていることが確認できますね。

ec2-scheduler-10

指定時刻のEC2起動/停止

想定通りの時刻に、Start/Stopさせることができました。指定する時刻がUTCである点にご注意ください。

ec2-scheduler-11

検証ではここで問題が発生した為、スクリプトを確認したところ、タグに指定したstartTime、stopTimeが、Lambdaファンクションが実行された時点から遡って45分前までの範囲に収まっていれば、対象のEC2が起動/停止が実行される仕様であることがわかりました。この仕様により、今回は検証の為に非常に短い時間で起動/停止を試した為に、EC2が起動/停止を繰り返す事象が発生してしまいました。ただ、実際にはEC2の1時間単位での課金を抑えることが目的で設定するものなので、今回のような近い時刻をstartTime、stopTimeに指定することは無いと思いますから、特に問題とはならないのではないかと思います。念の為、この「45分前から現在までの間」というロジックがハードコードされている点には、少し注意しておくと良いと思いました。

また、DynamoDBに格納されたデフォルト値を利用(default/true)した起動/停止、それ以外のタグ指定による起動/停止もそれぞれ試してみましたが、ひと通り動作を確認することができました。

カスタムメトリクスの確認

前述の問題があった為に綺麗なグラフになりませんでしたが、インスタンスの状態をrunning=1,stopped=0で示すカスタムメトリクスもputしてくれています。これはとても親切な実装ですね。

ec2-scheduler-12

まとめ

ほぼ用意されたドキュメントをなぞっただけの内容となりましたが、用意されたスタックをデプロイしながら動作確認まですることができました。実装もひと通り確認することができたので、個人的にはとても勉強になりました。このようなテンプレートを参考にしつつ、さらに運用要件に合わせてカスタマイズして利用して行けると良いのではないかと思います。また、AWS Answersの今後にも注目して行きたいところですね。

ちなみに、ソースは全てこちらに公開されていますので、AWS活用に役立てていただければと思います。

どこかの誰かのお役に立てば嬉しいです。