この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、データアナリティクス事業本部@那覇オフィスの下地です。
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のコード全体
では最終的に作成したファイルを記載します。
template.yml
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