【AWS】LambdaとEventBridge SchedulerでRDSを7日以上自動停止する方法

EventBridgeアイキャッチ

Amazon RDS は、停止後7日が経過すると自動的に起動される仕様となっています。
開発環境や検証環境など、長期間利用しないRDSを停止したままにしたい場合、意図せずコストが発生してしまうケースがあります。

本記事では、Amazon Web Services Lambda と EventBridge Scheduler を利用して、RDSを7日以上自動停止し続ける方法を解説します。

なお、AWS公式では EventBridge Rule(旧 CloudWatch Events)を利用した方法が紹介されていますが、本記事ではより新しい EventBridge Scheduler を利用して構築します。

前提条件

  • Amazon RDS(RDS for PostgreSQL)作成済み
  • Lambda 関数を作成可能なIAM権限を保有していること
  • EventBridge Scheduler を利用可能であること

参考資料

下記AWS公式ナレッジセンターを参考にしています。

AWS re:Post「Lambda 関数を使用して Amazon RDS インスタンスを 7 日以上停止する方法を教えてください。」

IAM権限の設定(IAMポリシーを作成)

AWSマネジメントコンソールへログインし、IAMダッシュボードへ移動します。
左側メニューより「ポリシー」を選択し、「ポリシーを作成」をクリックします。

JSONタブを選択し、以下のポリシーを入力します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "rds:StartDBCluster",
        "rds:StopDBCluster",
        "rds:ListTagsForResource",
        "rds:DescribeDBInstances",
        "rds:StopDBInstance",
        "rds:DescribeDBClusters",
        "rds:StartDBInstance"
      ],
      "Resource": "*"
    }
  ]
}

ポリシー名を適宜入力し「ポリシーの作成」をクリック
(今回の場合「rds-stop-start-pol」という名前にしました)

「ポリシーxxxxxxxx が作成されました。」と緑のポップアップが表示されるのを確認

IAMロールを作成し、必要なポリシーをアタッチします。

IAMダッシュボードに移動し、左部メニューの「ロール」を選択 「ロールを作成」をクリック

信頼されたエンティティを選択で「AWSサービス」を選択し「ユースケース」よりLambdaを選び
「次へ」をクリック

先ほど作成したポリシーを選択します。今回は「rds-stop-start-pol」を選択し「次へ」をクリック

ロール名を任意で入力し、その他は何も入力せず「ロールを作成」をクリック
今回は「lambda-stop-start-Lambda」という名前にしました。

「ロール xxxxxxxx が作成されました。」と緑のポップアップが表示されるのを確認

DBインスタンスにタグを追加

RDSダッシュボードに移動し、左部メニューより「データベース」を選択
今回7日以上停止したいRDSのリンクをクリック

「タグ」タブを選択し「タグを管理」をクリック

下記の内容でタグを設定し「変更を保存」をクリック

キー
autostartyes
autostopyes

これらのタグを利用して、Lambda関数から対象RDSを判定します。

Lambda関数を作成して、タグづけされたDBインスタンスを起動する(RDS起動用Lambda作成)

Lambdaダッシュボードに移動し「関数を作成」をクリック

以下の内容でLambda関数を作成します。

  • ランタイム:Python 3.14
  • 実行ロール:先ほど作成したIAMロール

その他の設定のプルダウンをクリックし「カスタムロール」より先ほど作成したロールを選択する

最終的には下記のようになったのを確認し「関数を作成」をクリック

下記のような緑のポップアップが表示されるのを確認

次に作成したLambda関数ページに遷移するので
コードソースエディタで、下記のコードを入力します。

import boto3
rds = boto3.client('rds')

def lambda_handler(event, context):

    #Start DB Instances
    dbs = rds.describe_db_instances()
    for db in dbs['DBInstances']:
        #Check if DB instance stopped. Start it if eligible.
        if (db['DBInstanceStatus'] == 'stopped'):
            try:
                GetTags=rds.list_tags_for_resource(ResourceName=db['DBInstanceArn'])['TagList']
                for tags in GetTags:
                #if tag "autostart=yes" is set for instance, start it
                    if(tags['Key'] == 'autostart' and tags['Value'] == 'yes'):
                        result = rds.start_db_instance(DBInstanceIdentifier=db['DBInstanceIdentifier'])
                        print ("Starting instance: {0}.".format(db['DBInstanceIdentifier']))
            except Exception as e:
                print ("Cannot start instance {0}.".format(db['DBInstanceIdentifier']))
                print(e)


if __name__ == "__main__":
    lambda_handler(None, None)

入力したら「Deploy」をクリックし「関数 xxxxxxx が正常に更新されました。」を表示されるのを確認

次にタイムラウト値を変更するため「設定」タブを選択し「編集」をクリック

「基本設定を編集」でタイムラウト値 を 10 に変更し「保存」をクリック

タイムアウトが10秒になっているのを確認して完了です。

タグ付けされたDBインスタンスを停止するLambda関数を作成する
(RDS停止用Lambda関数を作成)

Lambdaダッシュボードに移動し「関数を作成」をクリック

先ほどと同様にLambda関数を作成します。

最終的に下記のような画面になればOKです。
「関数を作成」をクリックします。

コードソースエディタで下記コードを入力します。

import boto3
rds = boto3.client('rds')

def lambda_handler(event, context):

    #Stop DB instances
    dbs = rds.describe_db_instances()
    for db in dbs['DBInstances']:
        #Check if DB instance is not already stopped
        if (db['DBInstanceStatus'] == 'available'):
            try:
                GetTags=rds.list_tags_for_resource(ResourceName=db['DBInstanceArn'])['TagList']
                for tags in GetTags:
                #if tag "autostop=yes" is set for instance, stop it
                    if(tags['Key'] == 'autostop' and tags['Value'] == 'yes'):
                        result = rds.stop_db_instance(DBInstanceIdentifier=db['DBInstanceIdentifier'])
                        print ("Stopping instance: {0}.".format(db['DBInstanceIdentifier']))
            except Exception as e:
                print ("Cannot stop instance {0}.".format(db['DBInstanceIdentifier']))
                print(e)

if __name__ == "__main__":
    lambda_handler(None, None)

入力したら「Deploy」をクリックし「関数 xxxxxxx が正常に更新されました。」を表示されるのを確認

次にタイムラウト値を変更するため「設定」タブを選択し「編集」をクリック

先ほどと同様に基本設定を編集でタイムラウト値 を 10 に変更し「保存」をクリック
最終的に下記のような画面になるのを確認してください。

設定確認画面

以上でLambdaの作成は終了です。Lambda関数の「テスト」よりLambda関数のテストができるので
必要に応じて実施してください。

Lambda関数テスト画面

RDSが停止になっているのを確認

EventBridge Schedulerを設定

AWS公式手順ではLambdaトリガーから EventBridge Rule を利用していますが、本記事では EventBridge Scheduler を利用します。

EventBridgeのダッシュボードへ移動し左部メニューの「スケジュール」を選択
「スケジュールを作成」をクリック

スケジュールのパターンより、Lambdaを動かしたい時間を入力し「次へ」をクリック
名前は任意で入れてください。

スケジュール設定例

ターゲットの選択よりAWS Lambda Invoke を選択

「Lambda 関数」より動かしたい対象のLambdaを選択します。

設定オプションでは特に何も入れずに「次へ」をクリック
(ロールは新しいロールを作成より選びました)

「スケジュールの確認と作成」で、確認を行い。
問題なければ「スケジュールを作成」をクリック

下記のように緑のポップアップが表示されたら完了です。スケジュール時間まで待ちましょう。

確認

設定した時間になると、RDSが自動停止されることを確認できました。

また、CloudWatch Logs や CloudTrail 上でも StopDBInstance イベントを確認でき、正常にLambda関数が実行されていることを確認できました。

まとめ

本記事では、Lambda と EventBridge Scheduler を利用して、RDSを7日以上自動停止する方法を紹介しました。

開発環境や検証環境のRDSを長期間停止したい場合、本構成を利用することで不要なコスト発生を抑えることができます。

特に EventBridge Scheduler を利用することで、従来の EventBridge Rule より柔軟なスケジュール管理が可能となるため、これから構築する場合はこちらの利用がおすすめです。