この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、菊池です。
やりたいこと
DynamoDBのテーブルを月ごとに分けて利用している環境で、以下のオペレーションを定期的に自動で実行したいというケースを想定しています。
- 前月のテーブルのRCU/WCUを下げる
- 翌月のテーブルを作成する
DynamoDBではテーブルが存在するだけで、割り当てたRCU/WCU分の利用料が発生します。新しいテーブルは必要になるタイミングで作成し、古くなってアクセス頻度が減ったテーブルは割り当てるRCU/WCUを小さくすることでコストを抑えることができます。
上記のオペレーションを実行するLambda関数を作成し、CloudWatch Eventsで自動実行することで、この要件を実現します。
環境構築
テーブル自動作成
まずはテーブルを定期的に作成する環境です。
Lambda関数の作成
DynamoDBのテーブルを新規に作る関数を作成します。
トリガーは後から設定しますので、何もせず次に進みます。
関数名を入力し、ランタイムはPython 3.6にしました。
以下のコードをPython 3.6のランタイムで作成します。実行日時の10日後の年月でtable_yyyymm
という名称のテーブルを作成するコードです。同名のテーブルが存在する場合には何もしません。
import boto3
import datetime
def lambda_handler(event, context):
dynamodb = boto3.client('dynamodb')
WCU = event['wcu']
RCU = event['rcu']
now = datetime.datetime.now()
next_month = now + datetime.timedelta(days=10)
new_table_name = "table_" + next_month.strftime("%Y%m")
tables = dynamodb.list_tables()['TableNames']
if new_table_name not in tables:
newtable = dynamodb.create_table(
AttributeDefinitions=[
{
'AttributeName': 'id',
'AttributeType': 'S'
}
],
TableName = new_table_name,
KeySchema=[
{
'AttributeName': 'id',
'KeyType': 'HASH'
}
],
ProvisionedThroughput={
'ReadCapacityUnits': RCU,
'WriteCapacityUnits': WCU
}
)
print("New table is created.")
else:
print("New table is already exist.")
return 0
続いて、IAMロールの選択です。あらかじめ作成していなければ、新規に作成します。
利用するIAMロールには、AmazonDynamoDBFullAccessの管理ポリシーをアタッチしておきます。
関数ができたら、テストイベントを入力してテストしてみます。JSONで指定したwcu
、rcu
の値でテーブルが作成されます。
{
"wcu": 5,
"rcu": 5
}
実行して成功すれば、テーブルが作成されているはずです。テーブル名は、table_yyyymm
となります。今回のコードでは実行日+10日の月で作成されますので、実行タイミングに合わせて調整しましょう。
CloudWatch Eventsの設定
続いて、定期実行させるためのイベントを作成します。CloudWatchから、[イベント]-[ルールの作成]を選びます。
イベントソースに、[スケージュール]、[Cron式]を選択します。今回は毎月25日の日本時間9時に実行したいので、0 0 25 * ? *
と入力します。設定パターンはこちらを参照ください。イベントターゲットは、作成したLambda関数を選択し、入力にwcu、rcuの値を指定するJSONを設定します。
イベントルール名を指定し、作成します。
WCU/RCUの自動変更
続いて、古くなったテーブルのキャパシティを変更する関数を作成します。
Lambda関数
同様に、Python3.6の関数を作成します。table_yyyymm
という名称のテーブルのRCU/WCUを指定した値に変更するコードです。yyyymm
は実行日の10日前の年月になりますので、実行タイミングによって調整しましょう。対象のテーブルが存在しない場合には何もしません。
import boto3
import datetime
def lambda_handler(event, context):
dynamodb = boto3.client('dynamodb')
TARGET_WCU = event['decreace_target_wcu']
TARGET_RCU = event['decreace_target_rcu']
now = datetime.datetime.now()
last_month = now - datetime.timedelta(days=10)
old_table_name = "table_" + last_month.strftime("%Y%m")
tables = dynamodb.list_tables()['TableNames']
if old_table_name in tables:
old_table = dynamodb.describe_table(
TableName=old_table_name
)
wcu = old_table['Table']['ProvisionedThroughput']['WriteCapacityUnits']
rcu = old_table['Table']['ProvisionedThroughput']['ReadCapacityUnits']
if rcu == TARGET_RCU and wcu == TARGET_WCU:
print("Old table is not modified.")
else:
modify = dynamodb.update_table(
TableName= old_table_name,
ProvisionedThroughput={
'ReadCapacityUnits': TARGET_RCU,
'WriteCapacityUnits': TARGET_WCU
}
)
print("Old table CU is modified.")
else:
print("Old table is not exist.")
return 0
テストイベントで、設定するwcu/rcuを指定し、テストしてみましょう。
{
"decreace_target_wcu": 5,
"decreace_target_rcu": 5
}
CloudWatch Eventsの設定
続いて、定期実行させるためのイベントを作成します。先程と同様に、CloudWatchから、[イベント]-[ルールの作成]を選びます。
設定の方法は同じです。こちらは毎月5日の日本時間9時に実行しますので、0 0 5 * ? *
と入力します。ターゲットのLambda関数と入力のJSONを設定します。
以上で環境が準備できました。それぞれ、CloudWatch Eventsで指定した日時になれば実行されます。
最後に
以上です。
定期的に実行するオペレーションは、Lambda + CloudWatch Eventsを使うことで自動化することができます。
なお、今回紹介した構成はあくまでサンプルですので、運用環境に適用する際には、エラー発生時の検知や、対応方法も併せて検討しましょう。