AWS を利用する際に、EC2 インスタンスや RDS データベース インスタンスなどのリソースを一定のスケジュールで自動的に停止したり、再開したいことがあります。
このようなニーズは、開発環境やステージング環境として AWS を使っている場合に特に顕著です。一定の時間帯にはリソースを利用しないと確実に分かっている場合、その期間の課金を止めることで、経費を圧縮することができるためです。
このような場合に、EC2 や RDS の起動・停止をスケジュールする(現在のところ)一番簡単と思われる方法について、まとめました。
AWS の課金体系
現在では、AWS の課金単位はかなり細かなものになっています。
例えば EC2 仮想マシンの料金は、かなり以前には 1 時間単位に切り上げて計算されていたのですが、現在は Windows 仮想マシンも含めて 1 秒単位で計算され、最小の課金時間は 60 秒です。RDS でも、課金は 1 秒単位で計算され、最小の課金時間は 10 分です。
つまり、数時間にわたって EC2 インスタンスや RDS インスタンスを利用しないことが事前に分かっているケースでは、これをずっと起動しておくことはもったいない話なのです。
費用抑制の観点では、開発環境やステージング環境では EC2 のスポット インスタンスを利用することも普通に行われています。以前はスポット インスタンスを停止することが AWS の仕様上できなかったため、スポット インスタンスを終了(破棄)してもう一度 AMI から起動し直す手間との間で比較衡量し、あえて起動したままにする判断もありうる選択でした。
しかし、今では永続的なスポット インスタンス リクエストを作成できるため、スポット インスタンスであってもオンデマンド インスタンスと同様、いつでも自由に停止・再開することができるようになっています。
突き詰めれば、節約したいならそもそも EC2 のようなリソース確保型の手法ではなく、AWS Lambda のようなサーバーレス コンピューティングを利用してシステムを構築すべき、という考え方になるかもしれません。とはいえ、仮にさまざまな事情から EC2 インスタンスを利用してシステムを構築し続けなければならない状況でも、支払わなくていい料金を支払い続けるのは怠惰だといえます。
以前から利用できる方法
料金を節約するために EC2 や RDS のインスタンスを自動的に止めたいというニーズはありふれているため、これを実現するための手法はさまざまにあります。そして、より簡単に設定できるよう AWS それ自体の機能も進化してきました。
プリミティブな方法を含めて、以前から利用可能だった手法には、例えば次のものがあります。
- AWS 外のシステム上の cron から AWS CLI コマンドを実行する
- 常時起動している EC2 インスタンス上の cron から AWS CLI コマンドを実行する
- CloudWatch イベントから Lambda 関数を実行する
- EventBridge ルールから Lambda 関数を実行する
- EventBridge ルールから Systems Manager オートメーションを実行する
cron と AWS CLI を使う方法はもちろん現在でも利用可能ですし、それが適しているケースもあることは確かです。また、CloudWatch や EventBridge ルールからインスタンスを停止・再開するためのカスタム Lambda 関数を呼んだり、Systems Manager オートメーションを実行する方法も、AWS の機能追加の中でだんだんと簡易に設定できるようになってきた成果だといえます。
色褪せない cron は別として、これらの AWS 機能を利用したスケジュール設定手法はいまだにウェブ検索などでは多く見つかるのですが、今となってはどれも少し古い手法です。
一番簡単な方法
現在では、AWS コンソールの設定だけで EC2 や RDS の停止と再開をスケジュールでき、もはや Lambda 関数を書く必要もなくなっています。
具体的には、Amazon EventBridge Scheduler を使用してスケジュールを作成します。
- 準備: 停止したり再開したい対象リソースの ID を確認する
- 準備: 必要な IAM ロールを作成する
- Amazon EventBridge Scheduler でスケジュールを作成する
対象リソースの ID の確認
EventBridge スケジュールを作成する前に、操作対象リソースの ID を確認しておきます。ここでは例として、選択した RDS インスタンスを定期的に停止する EventBridge スケジュールを作成することにします。
RDS のインスタンス ID を確認するには、AWS コンソールから Amazon RDS 画面を開き、データベースのリストを確認します。
リストに表示される「DB 識別子」列の値が、RDS のインスタンス ID です。上の画面では "database-1" になっています。
IAM ロールの作成
次に、スケジュールの実行に使用される IAM ロールを作成します。EventBridge Scheduler でスケジュールを作成する際、多少なりとも面倒な部分はこの手順だけです。(毎回必要な手順ではなく、同様のタスクをいくつもスケジュールするケースでは作成済みの IAM ロールを再利用できます)
AWS コンソールから Identity and Access Management (IAM) 画面を開き、ロールの一覧で [ロールを作成] をクリックして、IAM ロールの作成を開始します。
[信頼されたエンティティタイプ] を [カスタム信頼ポリシー] に変更します。
画面下にカスタム信頼ポリシー エディタが以下の入力状態で表示されます。7 行目の Principal オブジェクトに電球アイコンで "Empty Object Principal" 提案が表示されています。
エディタを使用して、この部分を次のように編集します。この記述により、このポリシーで信頼される主体が EventBridge Scheduler であることを宣言しています。
"Principal": {
"Service": "scheduler.amazonaws.com"
},
全体が以下のようになっていることを確認して、画面下の [次へ] ボタンをクリックします。
続いて、スケジュールで実行したい操作に応じた許可ポリシーを選びます。
ここでは RDS インスタンスの操作を行うので、[AmazonRDSFullAccess] を検索して選択します。(EC2 インスタンスの操作を行いたいケースであれば [AmazonEC2FullAccess] を選びます。その他、複数の許可ポリシーを組み合わせて選択することもできます)
次に進み、ロール名を自由に入力します。ここでは "eventbridge-scheduler-rds-full-access-role" としました。
ページをスクロールして設定内容を確認した後、一番下の [ロールを作成] をクリックすると、設定した内容で IAM ロールが作成され、ロールの一覧に表示されます。
これで IAM ロールの作成は完了です。
Amazon EventBridge Scheduler スケジュールの登録
続いて、Amazon EventBridge Scheduler 画面からスケジュールを作成します。
AWS コンソールでサービスを検索すると、Amazon EventBridge とは別立てで Amazon EventBridge Scheduler が見つかります。これを選択しても実際には EventBridge 内の Scheduler メニューが開くだけなのですが、機能として前面に出そうという AWS の意図を感じます。関係ないかもしれませんが。
Amazon EventBridge の [スケジューラ] - [スケジュール] 画面で、スケジュール一覧の右上にある [スケジュールを作成] をクリックします。
最初に、スケジュールの名前を入力します。ここでは、"database-1-stop" としました。
画面を下にスクロールし、[頻度] - [定期的なスケジュール] を選択します。
今回の例のように、指定した日時に繰り返し実行するタイプのスケジュールでは、[スケジュールの種類] は [cron ベースのスケジュール] のままにします。[cron 式] のテキストボックス群に、crontab の書式でスケジュールを入力していきます。
上のスクリーンショットでは、スケジュールを毎週平日(月曜日から金曜日まで)の 23:30 に実行するように指定しています。
一般的な Linux の crontab 書式とは少し異なり、曜日を指定して日付は問わないことを表すため、[日付] テキストボックスには "?" と入力する必要があることに注意が必要です。ここに "*" を入力すると、"cron 式が無効です" エラーになります。
[フレックスタイムウィンドウ] は、開始時刻に幅を持たせる場合に指定しますが、ちょうど指定した時刻に実行したい場合は [オフ] を選択することもできます。(未選択にするとエラーになります)
画面下の [次へ] ボタンをクリックすると、[ターゲットの選択] 画面が表示されます。[すべての API] に切り替え、画面下の検索ボックスで [Amazon RDS] サービスを検索して見つけ、選択します。
RDS の API 一覧が表示されるので、検索ボックスで [StopDBInstance] API を検索して見つけ、選択します。
選択した API に応じた入力状態でエディタが表示されます。ここで、事前に確認しておいた RDS インスタンスの ID を入力します。(StopDBInstance API では、指定可能なインスタンス ID は 1 つだけです。EC2 インスタンスを停止する StopInstances API の場合は、配列形式で複数のインスタンス ID を指定できるので、同時刻に複数の EC2 インスタンスをまとめて停止するスケジュールを作成できます)
画面下までスクロールし、[次へ] ボタンをクリックします。次の画面では、スケジュールについての細かな設定を調整し、実行ロールを選択します。
[スケジュール完了後のアクション] では、最後の実行後にスケジュール設定を削除するか、何もせず残すかを指定します。cron で繰り返し実行をスケジュールする場合、次回の呼び出しタイミングが常に存在するはずなので、[DELETE] を選択しておいても差し支えはないはずですが、一応 [NONE] を選んでおきます。
[再試行ポリシー] では、アクションが失敗した場合に再試行する期間を指定することができます。トグルスイッチで再試行を単に無効にすることもできますが、キャパシティ不足で強制停止していることもある EC2 スポットインスタンスを停止させるスケジュールなどでは、一定期間の再試行を指定しておいた方がよいかもしれません。
画面の一番下までスクロールし、このスケジュールの実行ロールを指定します。前の [ターゲットの選択] 画面で [テンプレート化されたターゲット] を選んだ場合は [このスケジュールの新しいロールを作成] オプションも選択できますが、今回の例のように [すべての API] から選択した場合は、[既存のロールを使用] しか選択できません。
ここでは、前のステップで作成しておいた "eventbridge-scheduler-rds-full-access-role" ロールを選択し、[次へ] ボタンをクリックします。
[スケジュールの確認と作成] 画面が表示されるので、内容を確認して画面の下までスクロールし、[スケジュールを作成] ボタンをクリックします。
以上で EventBridge スケジュールの作成は完了です。スケジュール一覧を再表示し、作成したスケジュールが表示されることを確認してください。
動作確認
スケジュールの作成後、指定した時刻になると、EventBridge Scheduler によってスケジュールが開始され、指定した RDS インスタンスが停止されます。
同じように StartDBInstance API を指定する EventBridge スケジュールを作成すれば、RDS インスタンスを平日の朝に毎日起動し、夜に停止し、週末は停止し続けるようなスケジュールを画面からの設定だけで簡単に構成することができます。
まとめ
自腹が痛まない会社のお財布で AWS の費用を支払っていると鈍感になってしまいがちですが、EC2 や RDS の起動・停止を細かく管理することにより、AWS に支払う費用は最適化することができます。
そのために利用できる手法はさまざまにありますが、現在のところ一番簡単な方法は、EventBridge Scheduler でスケジュールを組む方法です。
手順の中で、IAM ロールを作成するステップについては現状、どうしてもエディタでのわずかな手作業が発生します。決まった内容を書くだけのものなので、近い将来にエディタ操作が不要になり、GUI で簡単に設定できるようになることを期待したいところです。