LoginSignup
8
6

More than 5 years have passed since last update.

AWS Lambda(Python)でインスタンス起動停止をSchedule実行してみる

Posted at

はじめに

前々から作って見たかったのですが、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の設定

  1. Runtimeは「Python2.7」
  2. コードは後で・・・
  3. Handlerは適当に
  4. RoleはDynamoDBへの読み書きとEC2への開始/停止と参照があれば、OK
  5. メモリは128MBでいけるとおもいます
  6. タイムアウトは適当に(今回は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)

トライアンドエラーでなんとかできました。

これから

これからは、これに付随したものを作っていこうと思ってます。

  1. DynamoDBのデータを登録/更新/削除/閲覧できるスクリプト
  2. S3で静的HTML + JSでDynamoDBのデータを登録/更新/削除/閲覧
  3. API Gateway + Lambda で リアルタイム実行

いつになるかはわかりませんが。。。

8
6
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
8
6