RDSを定期的に起動/停止する機能をCloudFormationで作ってみる
こんにちは、データアナリティクス事業本部@那覇オフィスの下地です。
RDSインスタンスは停止することができますが、停止した7日後には自動で起動します(一時的に Amazon RDS DB インスタンスを停止する)。そこで、6日間隔でRDSを自動起動/停止する機能を作成してみようと思います。
1. 全体像
作成する全体像は以下図のようになります。
必要なリソースを下記表にまとめます。こちらをCloudFormation(cfn)を使用して作成していきます。
作成するリソース | リソース名 |
---|---|
起動用のロール | LambdaRoleStartRDS |
起動lambda | StartRDSLambda |
起動EventBridge | StartRDSScheduleEvent |
停止用のロール | LambdaRoleStopRDS |
停止lambda | StopRDSLambda |
停止EventBridge | StopRDSScheduleEvent |
2. 作ってみる
RDSを自動起動/停止する機能を作成します。cfnで作成するリソースは以下の3種類です。
- AWS::IAM::Role
- AWS::Lambda::Function
- AWS::Events::Rule
2.1 cronの設定
AWS::Events::Ruleではcronを使用します。設定時には以下の6つの項目を設定する必要があります(Schedule Expressions for Rules)。
# 設定項目(分 時 特定の日 月 曜日 年) cron(Minutes Hours Day-of-month Month Day-of-week Year)
今回、起動イベントの30分後に停止イベントを実施すること、6日間隔で起動するため以下の様に設定します。
# 起動 cron(0 10 */6 * ? *) # 停止 cron(30 10 */6 * ? *)
2.2 最小権限の設定
LambdaからRDSの起動(もしくは停止)する際のpolicyには最小権限の設定のためRDSのARNを指定します。
こちらは、AWS::IAM::Role
のPolicies項目にて!Join
を使用し該当するRDSのARNを作成します。作成する内容は以下のようになります。
# policyに記載する内容 Resource: !Join ["", [ "arn:aws:rds:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":db:", !Ref RdsInstanceName] ] # 作成されるRDSのARN "Resource": "arn:aws:rds:リージョン名:アカウントID:db:RDSインスタンス名"
2.3 cfnのコード全体
では最終的に作成したファイルを記載します。
AWSTemplateFormatVersion: "2010-09-09" Description: Ability to automatically start and stop RDS Parameters: RdsInstanceName: Description: "rds instance name" Type: String Default: RDSインスタンス名 Resources: LambdaRoleStartRDS: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: PolicyStartRDS PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - "rds:StartDBInstance" Resource: !Join ["", [ "arn:aws:rds:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":db:", !Ref RdsInstanceName] ] - Effect: Allow Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" Resource: "*" StartRDSLambda: Type: "AWS::Lambda::Function" Properties: Handler: "index.handler" Role: Fn::GetAtt: - "LambdaRoleStartRDS" - "Arn" Environment: Variables: rds_instance: !Ref RdsInstanceName Runtime: "python3.7" Code: ZipFile: | import boto3 import os instance = os.environ["rds_instance"] def handler(event, context): rds = boto3.client('rds') rds.start_db_instance(DBInstanceIdentifier=instance) StartRDSScheduleEvent: Type: AWS::Events::Rule Properties: Description: ’StartRDS schedule event for lambda’ ScheduleExpression: 'cron(0 10 */6 * ? *)' State: ENABLED Targets: - Arn: !GetAtt StartRDSLambda.Arn Id: ScheduleEvent1Target DependsOn: - StartRDSLambda LambdaRoleStopRDS: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: PolicyStopRDS PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - "rds:StopDBInstance" Resource: !Join ["", [ "arn:aws:rds:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":db:", !Ref RdsInstanceName] ] - Effect: Allow Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" Resource: "*" StopRDSLambda: Type: "AWS::Lambda::Function" Properties: Handler: "index.handler" Role: Fn::GetAtt: - "LambdaRoleStopRDS" - "Arn" Environment: Variables: rds_instance: !Ref RdsInstanceName Runtime: "python3.7" Code: ZipFile: | import boto3 import os instance = os.environ["rds_instance"] def handler(event, context): rds = boto3.client('rds') rds.stop_db_instance(DBInstanceIdentifier=instance) StopRDSScheduleEvent: Type: AWS::Events::Rule Properties: Description: ’StopRDS schedule event for lambda’ ScheduleExpression: 'cron(30 10 */6 * ? *)' State: ENABLED Targets: - Arn: !GetAtt StopRDSLambda.Arn Id: ScheduleEvent1Target DependsOn: - StopRDSLambda
2.4 実行確認
コンソール画面からtemplate.yml
ファイルをアップロードし、該当のRDSインスタンス名を記載して実行します。実行後、以下図のようにリソースが作成されていることが確認できました。
3. まとめ
6日ごとにRDSを起動/停止する仕組みを作成してみました。cfnに慣れておらず作成する際にいろいろ調べましたが、作れてしまうと管理がとても容易になると実感しました。 この記事がどなたかの助けになれば幸いです。
参考リンク
- [AWS]Lambda で RDS の自動起動・自動停止を実装する
- 一時的に Amazon RDS DB インスタンスを停止する
- cron を10分おき 2時間おきに実行する方法
- cronの日時指定を、基礎から学ぶ(分,時,日,月,曜日の指定、◯分ごと、月末起動、など)
- AWS Lambda テンプレート
- CloudFormationでCloudWatch EventsとLambdaを構築
- CloudFormationを使ってCloudWatch Eventsでスケジュール起動されるlambdaをデプロイする
- AWS::Events::Rule
- AWS::Lambda::Function Environment
- [速報] RDSインスタンスの起動/停止
- 擬似パラメータ参照
- Fn::Join