一つのLambdaで複数のEC2 インスタンスを起動・停止を行う


この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので十分ご注意ください。

はじめに

こんにちは、これからブログの形でAWS利用と知識に関する様々な情報を公開していきたいと思います。AWSを使用する時、コストを控えたり、手間を省いたり場合には自動でインスタンスを起動・停止したい時があります。今回は「一つのLambdaで定期的に複数のEC2インスタンスを起動・停止させる方法」を紹介していきます。ちなみに、対象が複数インスタンスでも可能です。


概要

必要なサービスは、以下の2つです。

サービス 機能
CloudWatch events Lambdaを呼び出すトリガー用
Lambda インスタンスを起動・停止させる関数を実行
IAM 権限を提供する

手順としては大まかな流れは下記の3つになります。

  • IAMポリシーとIAMロールの作成
  • Lambda関数の作成
  • CloudWatchのイベントの作成

IAMポリシーとロールの作成

IAMポリシーの作成

EC2 instancesの起動・停止を実行できるポリシーを作ります。実行ログをCloudWatchに出力したかったので、logsのポリシーも付与しています。ポリシー名はstartstop-ec2をつけます。

ポリシー内容は以下です。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:StartInstances",
        "ec2:StopInstances"
      ],
      "Resource": "*"
    }
  ]
}

IAMロールの作成

次に、Lambdaが実行できるようにIAM Roleを割り当てます。信頼されたエンティティはLambdaを選択し先ほど作成したstartstop-ec2というポリシーをアタッチして作成します。

設定は完了したら、以下の画面になります。
file
file

各項目の設定は以下に設定しました。

項目 設定内容
信頼されたエンティティ Lambda
アタッチするポリシー startstop-ec2 (先ほど作成したポリシー)
ロール名 startstop-ec2-role (入力任意)

Lambda Functionの作成

Lambdaの画面を開いて関数の作成をクリックします。

各項目の設定は以下に設定しました。

項目 設定内容
関数名 startstop-ec2-lambda (入力任意)
ランタイム pyhton 3.8
実行ロール startstop-ec2 (先ほど作成したロール)

file

ソースコードは以下に記述しました。

import boto3

def lambda_handler(event, context):
    region = event['Region']
    instances = event['Instances']
    ec2 = boto3.client('ec2', region_name=region)
    if event['Action'] == 'start':
        ec2.start_instances(InstanceIds=instances)
    elif event['Action'] == 'stop':
        ec2.stop_instances(InstanceIds=instances)
    else:
        return 1
    return 0
  • region = event[‘Region’]はイベントに渡されたリージョンを定義します。
  • instances = event[‘Instances’]はイベントに渡されたインスタンスを定義します。
  • ec2.start_instances(InstanceIds=instances)はインスタンスを起動することを定義します。
  • ec2.stop_instances(InstanceIds=instances)はインスタンスを停止することを定義します。

ここのコードでは、特定のリージョン、インスタンスを入力することは不要です。


CloudWatch Events で起動・停止のイベントスケジュールを作成

イベントの選択

各項目の設定は以下に設定しました。

項目 設定内容
イベントバターン スケジュール
Cron式の入力 0 5 ? * MON-FRI *

file

このCron式の設定の意味は、平日日本時間の14時という意味になります。注意する点はcron式で指定する時間はUTC timeですので、UTCとJTCの時間差を注意して設定してください。

ターゲットの入力

各項目の設定は以下に設定しました。

項目 設定内容
ターゲット Lambda関数
関数 startstop-ec2-lambda (先ほど作成した関数)

file

ターゲットへの入力(JSON文字列)は以下の通りです。

{"Action": "stop","Region":"ap-northeast-1","Instances": ["i-xxxxxxxxxxxxxxxxx","i-xxxxxxxxxxxxxxxxx""]}

このように設定すれば、東京リージョンでの選定されたインスタンスidのインスタンスが自動停止を実行できます。起動する場合は、JSON文字列は{"Action": "start","Region":"ap-northeast-1","Instances": ["i-xxxxxxxxxxxxxxxxx","i-xxxxxxxxxxxxxxxxx""]}とすれば実行できます。

操作したいリージョンとインスタンスのIDを環境に合わせて入れ替えられます。

テスト確認

上記の流れはすべて終わってから、一度テストしましょう。CloudWatch Eventsのロググループでテストの結果を確認できます。

file

上記をクリックすると、ストリームの内容が出てきました。

file

上記の画面だと「START RequestID」でこのイベントの開始を記録されています。「END RequestID」でイベントの終了を記録されています。何もエラーメッセージが出ないので、無事にLambdaが実行されたことが確認できます。


まとめ

このように設定すると、自動起動・停止の対象にしたいインスタンスが増えても管理しやすいです。

1時間もあれば設定できるので、是非やってみてください。

Last modified: 2024-02-06

Author