概要
タイトルにもある通り、AWSのRDSを自動停止・自動起動する仕組みをつくってみました。
背景
最近勉強用にAWSで一つサイトを公開し、請求額を見てみたところRDSのサービスで予想以上に料金が発生してたので、
これはどうにかしないと!と思い色々調べてみました。
どうやらRDSのDBインスタンスは、恒久的な「停止」が出来なく、7日間経つと自動的にインスタンスが起動してしまうらしい。
なのでしばらく使わないならインスタンスごと「削除」する必要があるっぽい。
でも削除してしまうと再度立ち上げるのに時間がかかるので、あくまでも「停止」の状態にしておきたい。
7日間ごとに手動で停止作業を行うのも面倒なので、自動で停止や起動を制御できないかを調べてみたところ、Lambdaを使えそうな事が分かりました。
LambdaによるRDSの自動起動/停止の手順
簡単に手順をまとめていきます。
① IAMロールの設定
IAM>ロールの画面から、「ロールの作成」をクリックします。
「信頼されたエンティティタイプ」では「AWSのサービス」を選択。
「ユースケース」では「Lambda」を選択して「次へ」をクリックします。
許可ポリシーには以下の二つを選択します。それぞれ検索欄で検索してチェックします。
- AmazonRDSFullAccess
- CloudWatchFullAccess
最後に、ロールの名前を任意に入力し、ロールの作成完了です。
② Lambda関数の作成
RDSインスタンス起動
起動に必要な設定を以下のようにし、Lambda関数を作成します。
項目 | 値 |
---|---|
関数名 | (任意の関数名) |
ランタイム | Python 3.9 |
アーキテクチャ | x86_64 |
実行ロール | 「既存のロールを使用する」>(①で作成したロールを選択) |
「コードソース」のエディタで次のコードを記載し保存(Ctrl+S)した後、「Deploy」を選択します。
import boto3
region = 'ap-northeast-1'
rds = boto3.client('rds', region_name=region)
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:
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)
続いて、このスクリプトでRDSインスタンスが起動されるかをテストします。
「イベント名」にそれっぽい名前を付けて「保存」し、「テスト」をクリックします。
すると、停止されているRDSのインスタンスが起動されるはずです。(少し時間がかかります)
以下は必須ではないですが、スクリプトの実行を失敗させないために「メモリ」を増幅し、「タイムアウト」の時間も延ばしておきます。
・「メモリ」:128MB → 256MB
・「タイムアウト」:3秒 → 10秒
RDSインスタンス停止
上記の起動の設定と同じように停止用のLambda関数を作成します。
コードは次のものを使用します。
import boto3
region = 'ap-northeast-1'
rds = boto3.client('rds', region_name=region)
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:
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)
③ スケジューリング
②で作成した二つのLambda関数にスケジューリングの設定をし、実行する時間を指定します。
私の場合、毎週日曜日の21:30に自動起動、23:00に自動停止するように設定しました。
Lambda>「トリガーを追加」から設定できます。
ルール名やスケジュール式は起動/停止用に調整して下さい。(cron式の細かい説明などは今回は省きます)
以上です。
参考文献