LoginSignup
10
3

More than 1 year has passed since last update.

EC2インスタンス起動/停止をLambdaで自動化してみた

Last updated at Posted at 2021-08-23

はじめに

Lambdaを使ったEC2インスタンスの自動起動/自動停止の環境を構築したので紹介します
きっかけは業務でcrontabファイルを使用しておりLambdaに移行できるのでは?と思い実装しました
一回構築してしまえばめんどくさい手作業が自動化できますしヒューマンエラーも防げるのでおすすめです

対象読者

  • 個人アプリのサーバー費用節約したい人
  • EC2は触ったことあるけどLambdaは触ったことがない人
  • 自動化に興味のある人

前提

  • AWSアカウント作成済み
  • EC2インスタンス作成済み

実装の概要

実装時間: 30~60分
1. IAMロールの作成
2. LambdaでEC2インスタンスの起動・停止処理を実装
3. Amazon EventBridgeで Lambdaを実行する時間を指定する

IAMロールの作成

AWSにログインして IAM > ポリシー > ポリシーを作成 > JSONタブに進むとポリシー作成画面が表示されます
スクリーンショット 2021-08-23 9.16.25.png

そこに今回の実装に必要な権限が書かれた以下JSONテキストを貼り付けてください

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

記述したらポリシーの名前をlambda_for_start_stop_instanceにしてポリシーを作成しましょう。

ポリシーが作成できたらIAM > ロール > ロールを作成と進み以下の項目を選択し次のステップ:アクセス権限ボタンを押します

信頼されたエンティティの種類を選択: AWSサービス
ユースケースの選択: Lambda
スクリーンショット 2021-08-23 9.24.37.png

次にポリシーのフィルタに先ほど作成したlambda_for_start_stop_instanceを入力して検索したらそれを選択し次のステップ:タグボタンを押します
スクリーンショット 2021-08-23 9.27.19.png

タグは入力せず次のステップ:確認ボタンを押します
次にロール名にstart_stop_instance_lambdaを入力しロールを作成ボタンを押してロールを作成します

ロールが作成できたら作成したロール詳細画面でポリシーをアタッチする > 作成したポリシーを選択 > ポリシーのアタッチの順に進めてロールにポリシーをアタッチします

これでLambda用のロールが完成しました

Lambda関数の作成

ロールが作成できたらLambda関数を作成していきましょう
Lambda > 関数 > 関数の作成の順番で進むとLamba関数の作成画面が表示されます
スクリーンショット 2021-08-21 0.16.58.png

ここで以下の通り入力/選択しましょう
オプション: 一から作成
関数名: start_stop_ec2_instance
ランタイム: python3.8
ロール: 作成したロールを選択

入力できたら関数の作成ボタンを押してLambda関数を作成します
スクリーンショット 2021-08-21 0.22.26.png

起動・停止処理の実装

それではEC2の起動・停止処理を書いていきます
先ほど作成したLambda関数の「コード」タブ > lambda_function.pyファイルを選択するとコードの中身が表示されます
スクリーンショット 2021-08-21 0.41.39.png
ここに以下のコードを貼り付けてください

import boto3
import os
region = 'ap-northeast-1'
instances = [os.environ['INSTANCE_ID']]

def lambda_handler(event, context):
    ec2 = boto3.client('ec2', region_name=region)
    action = event["Action"]
    response = ec2.describe_instances(InstanceIds=instances)
    ec2_status = response['Reservations'][0]['Instances'][0]['State']['Name']
    print(instances[0] + ' instance is ' + ec2_status + ' now.')

    if action == "Start":
        ec2.start_instances(InstanceIds=instances)
        print('started your instance: ' + str(instances[0]))
    elif action == "Stop":
        ec2.stop_instances(InstanceIds=instances)
        print('stopped your instance: ' + str(instances[0]))
    else:
        print('Lamdba function could not be executed.')

コードを貼り付けたら3行目のregion = 'ap-northeast-1'の部分を起動/停止したいインスタンスがあるリージョンの名前に変更してください
筆者は東京リージョンEC2インスタンスがあるのでap-northeast-1にしています
変更できたらタブの横にあるDeployボタンを押して変更を保存します
※「Deploy」ボタンを押さないとコードの変更が反映されないので注意

コード概要

特徴は2つです
1つ目はLambda関数に送られてくるリクエストによって起動と停止の処理を条件分岐させています
理由はCloudWatchでLambdaを監視する場合、Lambda関数の数は少ない方が費用を削減できます(CloudWatchでの監視は別途紹介します)

2つ目はEC2インスタンスのidを記述する箇所は環境変数にして汎用性の高いコードにしてあります
そうしておくと他のインスタンス自動化したい!となった場合Lambda関数を複製して環境変数の部分だけ書き換えれば簡単に実装できます
ちなみに私はこのLambda関数を10個ぐらい複製しました

環境変数の設定

「設定」タブ > 環境変数 > 編集 > 環境変数の追加と進み環境変数の編集画面に進みます
スクリーンショット 2021-08-21 1.14.41.png

キーと値には次の値を入力しましょう
キー: INSTANCE_ID
値: i-xxxxxxxx (起動・停止したいEC2インスタンスのid)

入力できたら保存ボタンを押して環境変数を追加しましょう

これでLambda関数の設定は完了です

Lambdaのテスト方法

完成したLambda関数でインスタンスが起動・停止できるかテストしてみましょう

まずはあらかじめEC2インスタンスを起動させておきます

そのあとLambda関数画面で「テスト」タブ を押すとLambda関数に投げるリクエストを作成できます
停止のリクエストを投げたいので以下の項目を選択/入力します

テンプレート: hello_world
名前: stop_request
JSON: {"Action": "Stop"}

入力したら変更を保存 > テストボタンを押しましょう
すると実行結果:成功の表示がされるはずです
スクリーンショット 2021-08-23 18.04.26.png

インスタンスの状態を確認すると起動中から停止済みに変更されているはずです

トリガーの設定

それでは完成したLambda関数をいつ起動・停止するのか設定していきましょう
Amazon EventBridge > イベント > ルール > ルールを作成を押します
スクリーンショット 2021-08-21 1.36.09.png

今回はEC2インスタンスを毎日9:00に起動毎日21:00に停止 したいとして実装していきます

次の値を入力します
名前: start__ec2_instance_at_0900
説明: 毎日9:00に{"Action": "Start"}リクエストを投げるルール
イベントパターン: スケジュール
cron式: cron(0 0 ? * * *)

ターゲット: Lambda関数
機能: start_stop_ec2_instance(作成したLambda関数を選択)
入力の設定: 定数 (JSON テキスト) を選択
JSON テキスト:

入力が終わったら作成ボタンを押します
作成できたら今度は次の値を入力して作成ボタンを押します。
名前: stop__ec2_instance_at_0900
説明: 毎日21:00に{"Action": "Stop"}リクエストを投げるルール
イベントパターン: スケジュール
cron式: cron(0 12 ? * * *)

ターゲット: Lambda関数
機能: start_stop_ec2_instance(作成したLambda関数を選択)
入力の設定: 定数 (JSON テキスト) を選択
JSON テキスト:

これで決まった時間にEC2インスタンスが自動起動/停止するようになりました

最後に

最後まで本記事を読んでくださりありがとうございました
後日、本記事の内容をTerraformで構築する方法やCloundWatchで監視してSlackに通知する方法も投稿します
ご興味ありましたらお読みください

10
3
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
10
3