LoginSignup
0
0

More than 1 year has passed since last update.

【EC2】Lambdaから時刻指定でEC2を自動起動・停止を時刻実現する

Posted at

EC2の自動起動・停止を実現したい!

上記記事の改良版です。上記記事では自動起動・停止をhour単位でしか指定できず、一日に一度しか指定できませんでした。
それに加えて今回は

  • 時刻まで指定できる(10分ごと)
  • 複数時刻を指定できる
  • 平日指定できる

の機能を追加しました。
今回はLambdaを何度も呼び出したくないので10分ごとにしましたが、Lambdaを毎分呼び出せば、分指定までできるようになります。

EC2のタグの設定

スクリーンショット 2023-01-30 16.56.03.png

タグはこの様に設定します。
これだと
平日16時30分に起動して16時40分に停止する。
平日16時50分に起動して17時00分に停止する。
という流れになります。
時刻はカンマ区切りで記入して、0埋めで記載します 05:10 のような形です。

Lambda

import json
import boto3
from datetime import datetime, timedelta, timezone

# 10分単位で時間を丸める
# 例 12時8分 → 12時10分   5時58分 → 6時00分
def hour_rounder(t):
    return (t.replace(second=0, microsecond=0, minute=0, hour=t.hour) + timedelta(minutes=round(t.minute, -1)//10) * 10)

# 平日ならTrueを返し、週末(土日)ならFalseを返す
# 祝日は現在考慮していない
def is_weekday(t):
    weekday = t.weekday()
    if weekday == 5 or weekday == 6:
        return False
    return True
    
def lambda_handler(event, context):
    ec2 = boto3.client('ec2', region_name='ap-northeast-1')
    JST = timezone(timedelta(hours=+9), 'JST')
    now = datetime.now(JST)
    rounded_time = hour_rounder(now)
    is_weekday_flag = is_weekday(rounded_time)
    time = rounded_time.strftime("%H:%M")
    # 停止するインスタンスの処理
    custom_filter = [{
        'Name':'tag:auto_stop_at', 
        'Values': ["*" + time + "*"]
    }]
    	
    response = ec2.describe_instances(Filters=custom_filter)
    stop_instance_ids = []
    for instance_dic in response['Reservations']:
        stop_instance_ids.append(instance_dic['Instances'][0]['InstanceId'])
    
    if stop_instance_ids:
        ec2.stop_instances(InstanceIds=stop_instance_ids)
    
    # 開始するインスタンスの処理
    custom_filter = [{
        'Name':'tag:auto_start_at', 
        'Values': ["*" + time + "*"]
    }]
    custom_filter.append({
        'Name':'tag:auto_start_only_weekly', 
        'Values': ['true']
    })
    response = ec2.describe_instances(Filters=custom_filter)
    start_instance_ids = []
    for instance_dic in response['Reservations']:
        for tag in instance_dic['Instances'][0]['Tags']:
            # 平日の場合、平日設定のインスタンスのみ起動する
            if is_weekday_flag and tag['Key'] == 'auto_start_only_weekly' and tag['Value'] == 'true':
                start_instance_ids.append(instance_dic['Instances'][0]['InstanceId'])        
                
    if start_instance_ids:
        ec2.start_instances(InstanceIds=start_instance_ids)
    return {
        'statusCode': 200,
        'start_instance_ids': start_instance_ids,
        'stop_instance_ids': stop_instance_ids
    }

かんたんにコードを説明すると
hour_rounder という関数で、時間の10分を丸めています。
12時8分 → 12時10分 5時58分 → 6時00分
という形です。
これは考慮いらない気もしますが、毎度ピッタリの時刻にLambdaが呼ばれない可能性を考慮しています。

for instance_dic in response['Reservations']:
        for tag in instance_dic['Instances'][0]['Tags']:
            # 平日の場合、平日設定のインスタンスのみ起動する
            if is_weekday_flag and tag['Key'] == 'auto_start_only_weekly' and tag['Value'] == 'true':
                start_instance_ids.append(instance_dic['Instances'][0]['InstanceId'])

次に上記部分です。自動起動を平日のみ設定のものの考慮です。
時間からインスタンスIDをフィルタリングしたあとに、平日のみ設定だったら曜日判定するという流れです。
このあたり、もう少し簡略化できるかもしれませんが、一旦これで問題ないのでこうしています。

問題点

現状のコードだと05:00のように0埋めで時間を入力しておく必要があります。カンマ区切りで入力できるようにした関係で、インスタンスIDを取る際に、*5:00*というワイルドカードを使っている関係で、0がないと5:00とすると15時にも動いてしまいます。
このあたりなんとかしたいのですが、一旦運用でカバーしています。

0
0
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
0
0