AWS SAM を使用した RDS 停止ステータスの効率的な管理
はじめに
デフォルトでは、Amazon RDS インスタンスは無期限に停止状態を維持することはできません。7 日後に自動的に再起動されます。
You can stop a DB instance for up to seven days. If you don’t manually start your DB instance after seven days, your DB instance is automatically started so that it doesn’t fall behind any required maintenance updates.
この挙動により、使用されていないインスタンスでも 不要なコスト が発生する可能性があります。本記事では、AWS SAM を使用して RDS インスタンスの停止を自動化し、その停止状態を維持する方法を解説します。
前提条件
以下のツールがシステムにインストールされていることを確認してください。
- AWS SAM
- Python 3.x
AWS SAM アプリケーションの作成
ディレクトリ構造
以下は SAM アプリケーションのディレクトリ構造です。
/
|-- rds_shutdown/
| |-- app.py
| `-- requirements.txt
|-- samconfig.toml
`-- template.yaml
AWS SAM テンプレート
このテンプレートでは、CloudWatch Events ルールを使用して cron (23 行目) でトリガーされる Lambda 関数を定義します。代わりに、より詳細な制御を行うため RDS イベントと EventBridge を検討することもできます。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Using a CloudWatch Events rule, RdsShutdown keeps an RDS instance shutdown after 1 week.
Parameters:
RdsDbInstance:
Type: String
Resources:
RdsShutdownFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: rds_shutdown/
Environment:
Variables:
DB_INSTANCE: !Ref RdsDbInstance
Events:
ScheduleEvent:
Type: Schedule
Properties:
Description: An event rule for RdsShutdownFunction
Enabled: True
Schedule: 'cron(* */1 * * ? *)' # Every hour
FunctionName: rds_shutdown
Handler: app.lambda_handler
MemorySize: 128
Role: !GetAtt IamRole.Arn
Runtime: python3.8
Timeout: 10
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/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: policy1
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- rds:DescribeDBInstances
- rds:StopDBInstance
Resource: !Sub arn:aws:rds:*:${AWS::AccountId}:db:${RdsDbInstance}
RoleName: rds-shutdown
LogsLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${RdsShutdownFunction}
RetentionInDays: 30
Python スクリプト
requirements.txt
追加の依存関係は不要です。boto3 は AWS Lambda ランタイムにすでに含まれています。
app.py
このスクリプトでは RDS インスタンスのステータスを確認し、available 状態の場合にのみ停止します。
import logging
import os
import boto3
# Environment Variables
DB_INSTANCE = os.environ.get('DB_INSTANCE')
logger = logging.getLogger()
logger.setLevel(logging.INFO)
client = boto3.client('rds')
def lambda_handler(event, context):
if not DB_INSTANCE:
# Exit when a DB Instance is not specified.
logger.error('DB_INSTANCE environment variable is not specified.')
return
# Get the DB Instance status.
status = get_db_instance_status(DB_INSTANCE)
if status == 'available':
# Stop when the status is available.
client.stop_db_instance(DBInstanceIdentifier=DB_INSTANCE)
logger.info(f'DB instance - {DB_INSTANCE} - has been stopped.')
def get_db_instance_status(db_instance: str) -> str:
# See https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Status.html
response = client.describe_db_instances(DBInstanceIdentifier=db_instance)
return response['DBInstances'][0]['DBInstanceStatus']
samconfig.toml
<YOUR_S3_BUCKET>
と <YOUR_RDS_INSTANCE_NAME>
をそれぞれの値に置き換えてください。
version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "rds-shutdown"
s3_bucket = "<YOUR_S3_BUCKET>"
s3_prefix = "rds-shutdown"
region = "ap-northeast-1"
capabilities = "CAPABILITY_IAM CAPABILITY_NAMED_IAM"
parameter_overrides = "RdsDbInstance=\"<YOUR_RDS_INSTANCE_NAME>\""
ビルドとデプロイ
以下のコマンドでアプリケーションをビルドおよびデプロイします。
sam build
sam deploy
テスト
RDS インスタンスを停止し、7 日間放置して、Lambda のログに以下のメッセージが表示されることを確認します。
DB instance - database-1 - has been stopped.
以下の AWS CLI コマンドでインスタンスのステータスを確認してください。
aws rds describe-db-instances --db-instance-identifier <YOUR_RDS_INSTANCE_NAME> | grep DBInstanceStatus
次のような出力が表示されます。
"DBInstanceStatus": "stopped",
まとめ
AWS SAM と Lambda 関数を使用して RDS インスタンスの停止を自動化することで、コスト削減とリソース管理を効率化できます。ただし、RDS インスタンスを無期限に停止状態に維持することはできない点に注意してください。
Happy Coding! 🚀