4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RDS(Aurora)を夜中と休日は止めて、利用料を節約する

Last updated at Posted at 2018-12-31

例えば、開発環境などは夜中や休日は使っていないことが多いと思います。
その時間DBを常に動かしているとお金の無駄になります。
Amazon Auroraでは、最大7日間DBインスタンスを停止することができます。

RDS(Aurora)を止めるとどのくらい節約できるのか

https://blog.manabusakai.com/2017/06/stopping-rds/

1 週間のうち、土日と平日深夜から早朝(0 〜 8 時)に停止させると仮定すると、
削減時間は (24 時間 * 2 日) + (8 時間 * 5 日) = 88 時間
削減率は 88 時間 / (24 時間 * 7 日) = 0.5238 (52 %)

この記事によれば、平日深夜と休日に止めるだけで料金の半分を節約することができると書いてあります。

どうやって止めるのか

今回はBoto3(Python)/CloudWatch/Lambdaを使ってRDSを止めていきます。
止める対象のDBは1リージョンにあるDBすべてとなります。
実装はCloudFormationを使って作ります。

実装

前準備

事前にlambda-function-stop-start-rds-<リージョン>-<アカウントID>という名前でS3バケットを作成します。
※ ここで指定したリージョンのRDSをすべて止めることになります。

aws s3 mb \
    s3://lambda-function-stop-start-rds-<リージョン>-<アカウントID> \
    --profile <プロファイル> --region <リージョン>

次に、以下のコードをZIPに圧縮してstop-start-rds.zipという名前で上記のS3へ置きます。

lambda_function.py
import boto3
import json

client = boto3.client('rds')

def lambda_handler(event, context):
    print(event)
    
    cloudWatchEventsArn = event['resources'][0]
    
    if 'start-rds-events' in cloudWatchEventsArn:
        start_db_cluster()
    elif 'stop-rds-events' in cloudWatchEventsArn:
        stop_db_cluster()

def stop_db_cluster():
    for DBClusterIdentifier in describe_db_clusters() :
        response = client.stop_db_cluster(
            DBClusterIdentifier = DBClusterIdentifier
        )

def start_db_cluster():
    for DBClusterIdentifier in describe_db_clusters() :
        response = client.start_db_cluster(
            DBClusterIdentifier = DBClusterIdentifier
        )

def describe_db_clusters():
    clusters = []
    response = client.describe_db_clusters()

    for DBCluster in response['DBClusters']:
        clusters.append(DBCluster['DBClusterIdentifier'])

    return clusters

CloudFormationの実行

以下のymlファイルを作成します。

stop-start-rds.yml
---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'CloudWatch Events -> Lambda -> RDS(Aurora)'
Parameters:
  FunctionName:
    Type: String
    Description: "Lambda Fuction Name"
    Default: "lambda-function-stop-start-rds"
  SourceFileName:
    Type: String
    Description: "Lambda Source FileName"
    Default: "stop-start-rds.zip"
Resources:
  IAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonRDSFullAccess
        - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Path: /
      RoleName:
        Fn::Join:
          - '-'
          - - !Ref FunctionName
            - !Ref 'AWS::Region'

  LambdaFunction:
    DependsOn:
      - IAMRole
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket:
          Fn::Join:
            - '-'
            - - !Ref FunctionName
              - !Ref 'AWS::Region'
              - !Ref 'AWS::AccountId'
        S3Key: !Ref SourceFileName
      FunctionName: !Ref FunctionName
      Handler: lambda_function.lambda_handler
      MemorySize: 1024
      Role: !GetAtt IAMRole.Arn
      Runtime: python3.7
      Timeout: 60

  StopRdsEventRule:
    DependsOn:
      - LambdaFunction
    Type: "AWS::Events::Rule"
    Properties: 
      Name: "stop-rds-events"
      Description: !Ref FunctionName
      ScheduleExpression: "cron(0 16 ? * MON-FRI *)"
      State: "ENABLED"
      Targets: 
        - Arn: !GetAtt LambdaFunction.Arn
          Id: LambdaFunction
  StartRdsEventRule:
    DependsOn:
      - LambdaFunction
    Type: "AWS::Events::Rule"
    Properties: 
      Name: "start-rds-events"
      Description: !Ref FunctionName
      ScheduleExpression: "cron(0 22 ? * SUN-THU *)"
      State: "ENABLED"
      Targets: 
        - Arn: !GetAtt LambdaFunction.Arn
          Id: LambdaFunction

CloudFormationでスタックを作成します。
※ 最初に作成したS3と同じリージョンに作成してください。
※ stop-start-rds.ymlがあるディレクトリで実行してください。

aws --profile "<プロファイル>" --region "<リージョン>" \
    cloudformation create-stack \
    --stack-name stop-start-rds \
    --template-body file://stop-start-rds.yml \
    --capabilities CAPABILITY_NAMED_IAM

CloudFormationのコンソールでスタックが作成されれば完了です。

所感

実際にいくら安くなっているのかは一ヶ月経たないとわかりませんが、
RDSのインスタンス自体はCloudWatchメトリクスを見ると止まっているのが確認できました。
意外と簡単に作れるのでおすすめです。

どうでもいいこと

最近のおすすめの曲:https://www.youtube.com/watch?v=BuP1R6MKyns

皆さん、良いお年を〜

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?