こんばんは! AWSでWebアプリを運用していると毎月のRDSの費用も決して安くないことを思い知ります。 しかし、開発環境用に使っているRDSインスタンスなら、基本的に開発者が起きている時間帯だけ動けば良いので、夜間や休日に稼働させる必要はありませんよね。
というわけで不要な時間帯になったらRDSにはお休みして頂こうと思います。
何がしたいのか
RDSインスタンスを停止させるLambda
まずはRDSインスタンスを停止させるLambdaを作成します。 今回はサクサク書けるPython 3.8でLambdaを実装していきます。
- 関数名は任意の名前を付けてください。
- 実行ロールは特に問題が無ければ基本的なLambdaアクセス権限で新しいロールを作成を指定します。
Lambdaが作成できたら、実行ロールにrds:StopDBInstance
を許可するポリシーを追加します。これが無いとLambdaからRDSを停止できません。
下記は追加するポリシーのサンプルです。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "rds:StopDBInstance", "Resource": "*" } ] }
あとはザクザクとソースコードを書きます。
lambda_function.py
import json import boto3 def lambda_handler(event, context): rds = boto3.client('rds') # ***************にRDSインスタンスのDB識別子を指定 result = rds.stop_db_instance(DBInstanceIdentifier = '***************') print(result) return True
RDSインスタンスを起動させるLambda
先ほどと同様にLambdaを作成した後、今度は実行ロールにrds:StartDBInstance
を許可するポリシーを追加します。これが無いとLambdaからRDSを開始できません。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "rds:StartDBInstance", "Resource": "*" } ] }
ポリシーを追加したら、Lambdaのソースコードを書いていきます。 呼び出すメソッド以外は停止させるLambdaと同じですね。
lambda_function.py
import json import boto3 def lambda_handler(event, context): rds = boto3.client('rds') # ***************にRDSインスタンスのDB識別子を指定 result = rds.start_db_instance(DBInstanceIdentifier = '***************') print(result) return True
CloudWatchからLambdaを呼び出す
CloudWatchEventsは、Cron式を設定して特定の日付・曜日・時刻等の条件を満たした場合にAWSの各サービスを実行させることができます。 自分の場合、AWS環境でバッチ処理をさせたい場合なんかに使ったりしています。
では、CloudWatchの「ルール」画面から「ルールの作成」ボタンを押して、新しいルールを作成します。 下記は設定値の例です。 Cron式は開発者の皆さんの勤務実態に合わせて設定して下さい。
月~金曜日の21:00(JST)になったらRDSを停止させるルール
月~金曜日の8:00(JST)になったらRDSを開始させるルール
注意する点は、Cron式はGMT(グリニッジ標準時)で指定する必要があるということです。 本来設定したいJST(日本標準時)の時刻から9時間マイナスした時刻で設定する必要があります。 JSTからGMTに変換する過程で日付を跨いだ場合は、Cron式の曜日指定も1日分ズラす必要がありますので気を付けましょう。
設定に間違いがなければ、指定した時刻にRDSインスタンスが停止/開始するはずです。 開発用に使っているRDSインスタンスが多い程、コスト削減の効果は大きくなるでしょう。
余談
- テストでLambdaを連続実行したところ、RDSの開始に失敗する時があった。
- よくAWSコンソールを見てみるとRDSのステータスには停止中と停止の2種類がある。
- 停止中の時にRDSを開始するLambdaを実行してもエラーになる。停止処理を実行した後、開始処理が受付可能になるまでインターバルがある模様。