効率UP!LambdaでEC2インスタンスを自動起動・停止させる

AWS

おつかれさまです。あきおです。

AWSのEC2インスタンスを自動で起動・停止できたら便利ですよね。一々手動で行うとコンソールにログインし、インスタンスを選択して、起動 or 停止するので手間がかかります。

あきお
以前、停止を忘れて余分な料金が発生しました。

今回はその手間を省くため、Lambdaを使ってEC2インスタンスを自動停止させる設定を追加しました。備忘録としてまとめていきます。

設定の概要

LambdaにEC2インスタンスを起動・停止する関数を作成し、CloudWatch Eventで関数を実行するルールを定義します。

あきお
関数はPythonで作成し、実行サイクルはcron式で定義します。

Lambda実行用ロールを作成

EC2インスタンスを起動、停止、表示するため下記ポリシーを作成しました。実行ログをCloudWatchに出力したかったので、logsのポリシーも付与しています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:Start*",
                "ec2:Stop*",
                "ec2:DescribeInstances"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:CreateLogGroup",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        }
    ]
}

このポリシーをアタッチしたロール@EC2_Controlを作成しました。

Lambda関数を作成

上記のロールを使用した、インスタンス自動起動と自動停止の関数を作成していきます。

インスタンス自動起動

インスタンス停止中で、AutoStartのタグが付与されているインスタンスを起動させます。

import boto3

#リージョン
REGION_NAME = 'ap-northeast-1'
#インスタンスの状態
STATE_LIST = ['stopped']
#タグ
TAG_LIST = ['AutoStart']

#メイン処理
def lambda_handler(event, context):
    ec2 = boto3.client('ec2', REGION_NAME)
    instances = get_instance_list(ec2)
    
    ec2.start_instances(InstanceIds=instances)
    print('started your instances: ' + str(instances))
    
#ステータスとタグを指定してインスタンスIDリストを返却
def get_instance_list(ec2):
    
    instanceIdlist = []
    
    instances = ec2.describe_instances(
        Filters = [
                {'Name':'instance-state-name','Values':STATE_LIST},
                {'Name':'tag-key','Values':TAG_LIST}
            ]
        ) ['Reservations']
    
    for i in instances:
        instanceIdlist.append(i['Instances'][0]['InstanceId'])
    
    return (instanceIdlist)

インスタンス自動停止

インスタンス起動中で、AutoStopのタグが付与されているインスタンスを停止させます。

あきお
ソースコードは自動起動とほぼ変わらないです。
import boto3

#リージョン
REGION_NAME = 'ap-northeast-1'
#インスタンスの状態
STATE_LIST = ['running']
#タグ
TAG_LIST = ['AutoStop']

#メイン処理
def lambda_handler(event, context):
    ec2 = boto3.client('ec2', REGION_NAME)
    instances = get_instance_list(ec2)
    
    ec2.stop_instances(InstanceIds=instances)
    print('stopped your instances: ' + str(instances))
    
#ステータスとタグを指定してインスタンスIDリストを返却
def get_instance_list(ec2):
    
    instanceIdlist = []
    
    instances = ec2.describe_instances(
        Filters = [
                {'Name':'instance-state-name','Values':STATE_LIST},
                {'Name':'tag-key','Values':TAG_LIST}
            ]
        ) ['Reservations']
    
    for i in instances:
        instanceIdlist.append(i['Instances'][0]['InstanceId'])
    
    return (instanceIdlist)

get_instance_listで対象インスタンスのインスタンスIDを取得しています。

EC2インスタンスにタグを付与

自動起動と自動停止を行うため、以下タグを付与します。

  • Key:AutoStart, Value:yes
  • Key:AutoStop, Value:yes

Valueは便宜上”yes”としましたが、何を指定しても問題ないです。

EventBridgeでルールを作成

自動で起動・停止をさせるためEventBridgeでトリガーとなるルールを作成し、それぞれの関数に紐付けます。

インスタンスを平日22時に停止させたいので、以下ルールを作成しました。

ルール作成後、関数を見るとトリガーとなるルールが追加されていることがわかります。

スケジュール式ではcron式で記述ができます。AWSの公式ドキュメントに詳細が書いてあったのでこちらも是非参考にしてください。

AWS公式ドキュメント
AWS公式ドキュメント
ルールのスケジュール式について

まとめ

インスタンスを自動で起動・停止させることで、無駄なコストと作業を減らすことができます。

1時間もあれば設定できるので、是非チャレンジしてみてください。

それでは、おつかれさまでした。

AWSナレッジセンター
AWSナレッジセンター
Lambdaを使ったEC2インスタンスの自動起動・停止について