Amazon RDS は一時停止した場合、最大7日間までしか停止できない
しかし停止させたままにしたい状況が発生したため調査を行なった
その際のまとめを備忘録として残しておく
解決案
- Lambda 関数を使用する
- 公式推奨
- EventBridge を使用する
- どちらかというと夜間休日止めるのに最適
実際の手順
Lambda 関数を使用する
-
IAM > ポリシー を選択
-
以下でポリシーを作成
{ "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": "*" } ] } -
IAM > ロール を選択
-
以下でロールを作成
- 信頼できるエンティティタイプを選択: AWS サービス
- またはサービスを選択してユースケースを表示: Lambda
- ポリシー: 手順 2 で作成したポリシー
-
RDS > データベース > «該当の DB インスタンス» を選択
-
以下の様にタグを設定
- autostart: yes
- autostop: yes
-
Lambda > 関数 を選択
-
以下の設定で関数を作成
- オプション: 一から作成
- 関数名: 任意
- ランタイム: Python 3.*
- アーキテクチャ: x86_64
- デフォルトの実行ロールの変更: 手順 4 で作成したロール
-
コード > [コードソース]エディタでサンプルコードを削除して次のコードを入力
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) -
デプロイする
-
関数の概要 > トリガーを追加 を選択
-
EventBridge (CloudWatch Events) を選択し、[新しいルールを作成] を作成
- ルール名: 任意
- スケジュール式: RDS メンテナンス時間の 30 分前等を指定(cron 式)
- 例. cron(30 21 ? * SUN *)
-
手順 7 〜 12 を行い RDS 自動停止用の関数を作成
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)
EventBridge を使用する
-
以下の CloudFormation テンプレートを使用して stack を作成
--- AWSTemplateFormatVersion: '2010-09-09' Description: EventBridge Scheduler to stop RDS instance Parameters: InstanceId: Type: String ScheduleStopTime: Type: String Default: "cron(0 20 * * ? *)" ScheduleTimezone: Type: String Default: Japan Resources: # EventBridgeScheduler??? ScheduleRDSStop: Type: AWS::Scheduler::Schedule Properties: Name: !Sub 'RDS-Stop-${InstanceId}' Description: Stop RDS Instance ScheduleExpression: !Ref ScheduleStopTime ScheduleExpressionTimezone: !Ref ScheduleTimezone FlexibleTimeWindow: Mode: "OFF" State: ENABLED Target: Arn: arn:aws:scheduler:::aws-sdk:rds:stopDBInstance Input: !Sub |- { "DbInstanceIdentifier": "${InstanceId}" } RoleArn: Fn::GetAtt: - SchedulerRDSStopRole - Arn # EventBridgeScheduler?????IAM?????? SchedulerRDSStopRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - scheduler.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: rdsstop PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - rds:StopDBInstance Resource: - "*" -
以下のパラメータを指定
- 対象のインスタンス(DB 識別子)
- 例. sample-db
- 停止のスケジュール(cron 式)
- 例. cron(0 20 * * ? *)
- タイムゾーン
- 例. japan
- 対象のインスタンス(DB 識別子)
-
作成されたリソースを確認
3-1. Amazon EventBridge > スケジュール > «対象のスケジュール»