はじめに
前々から作って見たかったのですが、Javaで作るとたいそうかなと思ったところ、
AWS LambdaがPythonで実行できるということで、書いたことないので、
チャレンジしようと思って、早3ヶ月。
いろんな人が書いてるなか、やってみました。
概要
DynamoDBにテーブルを作り、時間やインスタンスに設定したタグ情報、
開始か停止かを入れておく。
Lambda Function(Python)は、10分ごとに動かして、
DynamoDBに入れてるデータの時間と一致したら、
そのタグ情報が一致するインスタンス全てに対して、
開始か停止かを実行します。
準備
DynamoDBにテーブル「EC2」を作ります。
Itemは4つ。「Id」「Time」「Tag」「StartStop」。
1. Id : シーケンス番号、順繰りになるようにしてください
2. Time : 時間、"%H:%M"形式、例:"09:00"
3. Tag : インスタンスのタグ開始や停止したいタグを入れてください
4. StartStop : 開始(start)か停止(stop)かを入れてください。
Lambdaの設定
- Runtimeは「Python2.7」
- コードは後で・・・
- Handlerは適当に
- RoleはDynamoDBへの読み書きとEC2への開始/停止と参照があれば、OK
- メモリは128MBでいけるとおもいます
- タイムアウトは適当に(今回は10secにしてます)
Lambda Function(Python)
個人的に苦労した箇所がいくつかあります。
1. "Filters=[{'Name':'tag-key','Values':[tableInfo['Tag']]}]"のとこ
"tableInfo['Tag']"の前後に"[]"がいることがわからなかった
2. "table.scan()['Items']"の"['Items']"がないといけない
これがないとDynamoDBから取得したデータのItemが取れない
3. なんでかわかりませんが、"boto3.client('ec2')"でないといけない
"boto3.resource('ec2')"だと動かなかった
4. "from boto3.dynamodb.conditions import Key, Attr"が必要みたい
で、コードは以下の通りです。
import boto3
import datetime
from boto3.dynamodb.conditions import Key, Attr
def lambda_handler(event, context):
# create EC2 client
ec2 = boto3.client('ec2')
# get the time(%H:%M)
timeInfo = datetime.datetime.now().strftime("%H:%M")
tableInfoList = getTableInfoList(timeInfo)
instanceList = getInstanceStartStopList(ec2, tableInfoList)
executeInstanceStartStop(ec2, instanceList)
# get the list of data (Id, StartEnd, Tag, Time)
# Id : Sequence
# StartEnd : "start" or "stop"
# Tag : Tag-key
# Time : %H:%M ex) 09:00
# @param timeInfo
# @return list of data(Id, StartEnd, Tag, Time)
def getTableInfoList(timeInfo):
dynamodb = boto3.resource('dynamodb')
#Set TableName
table = dynamodb.Table('EC2')
#Send the Query
#Query Parameter
# @param TimeInfo : [hh:mm]
#TimeInfo = "09:00"
tableInfoList = table.scan(
FilterExpression=Attr('Time').eq(timeInfo)
)['Items']
return tableInfoList
# get the list of data (Start or Stop Instance Ids)
# @param ec2
# @param tableInfoList
# @return instanceList Dictionaly('start', 'stop')
def getInstanceStartStopList(ec2, tableInfoList):
startInstanceIdList = []
stopInstanceIdList = []
for tableInfo in tableInfoList:
for reservation in ec2.describe_instances(Filters=[{'Name':'tag-key','Values':[tableInfo['Tag']]}])["Reservations"]:
for instance in reservation["Instances"]:
if (tableInfo['StartStop'] == 'start'):
startInstanceIdList.append(instance["InstanceId"])
elif (tableInfo['StartStop'] == 'stop'):
stopInstanceIdList.append(instance["InstanceId"])
instanceList = {"start":startInstanceIdList, "stop":stopInstanceIdList}
return instanceList
# Start of Stop Instances
# @param ec2
# @param instanceList
def executeInstanceStartStop(ec2, instanceList):
startInstanceIdList = instanceList["start"]
stopInstanceIdList = instanceList["stop"]
if not len(startInstanceIdList) == 0:
ec2.start_instances(InstanceIds=startInstanceIdList)
if not len(stopInstanceIdList) == 0:
ec2.stop_instances(stopInstanceIdList)
トライアンドエラーでなんとかできました。
これから
これからは、これに付随したものを作っていこうと思ってます。
- DynamoDBのデータを登録/更新/削除/閲覧できるスクリプト
- S3で静的HTML + JSでDynamoDBのデータを登録/更新/削除/閲覧
- API Gateway + Lambda で リアルタイム実行
いつになるかはわかりませんが。。。