はじめに
Lambdaを使ったEC2インスタンスの自動起動/自動停止の環境を構築したので紹介します
きっかけは業務でcrontabファイルを使用しておりLambdaに移行できるのでは?
と思い実装しました
一回構築してしまえばめんどくさい手作業が自動化できますしヒューマンエラーも防げるのでおすすめです
対象読者
- 個人アプリのサーバー費用節約したい人
- EC2は触ったことあるけどLambdaは触ったことがない人
- 自動化に興味のある人
前提
- AWSアカウント作成済み
- EC2インスタンス作成済み
実装の概要
実装時間: 30~60分
- IAMロールの作成
- LambdaでEC2インスタンスの起動・停止処理を実装
- Amazon EventBridgeで Lambdaを実行する時間を指定する
IAMロールの作成
AWSにログインして IAM > ポリシー > ポリシーを作成 > JSONタブ
に進むとポリシー作成画面が表示されます
そこに今回の実装に必要な権限が書かれた以下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
次にポリシーのフィルタ
に先ほど作成したlambda_for_start_stop_instance
を入力して検索したらそれを選択し次のステップ:タグ
ボタンを押します
タグは入力せず次のステップ:確認
ボタンを押します
次にロール名にstart_stop_instance_lambda
を入力しロールを作成
ボタンを押してロールを作成します
ロールが作成できたら作成したロール詳細画面でポリシーをアタッチする > 作成したポリシーを選択 > ポリシーのアタッチ
の順に進めてロールにポリシーをアタッチします
これでLambda用のロールが完成しました
Lambda関数の作成
ロールが作成できたらLambda関数を作成していきましょう
Lambda > 関数 > 関数の作成
の順番で進むとLamba関数の作成画面が表示されます
ここで以下の通り入力/選択しましょう
オプション: 一から作成
関数名: start_stop_ec2_instance
ランタイム: python3.8
ロール: 作成したロールを選択
入力できたら関数の作成
ボタンを押してLambda関数を作成します
起動・停止処理の実装
それではEC2の起動・停止処理を書いていきます
先ほど作成したLambda関数の「コード」タブ
> lambda_function.pyファイル
を選択するとコードの中身が表示されます
ここに以下のコードを貼り付けてください
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個ぐらい複製しました
環境変数の設定
「設定」タブ
> 環境変数
> 編集
> 環境変数の追加
と進み環境変数の編集画面に進みます
キーと値には次の値を入力しましょう
キー: INSTANCE_ID
値: i-xxxxxxxx (起動・停止したいEC2インスタンスのid)
入力できたら保存ボタンを押して環境変数を追加しましょう
これでLambda関数の設定は完了です
Lambdaのテスト方法
完成したLambda関数でインスタンスが起動・停止できるかテストしてみましょう
まずはあらかじめEC2インスタンスを起動させておきます
そのあとLambda関数画面で「テスト」タブ
を押すとLambda関数に投げるリクエストを作成できます
停止のリクエストを投げたいので以下の項目を選択/入力します
テンプレート: hello_world
名前: stop_request
JSON: {"Action": "Stop"}
入力したら変更を保存 > テスト
ボタンを押しましょう
すると実行結果:成功
の表示がされるはずです
インスタンスの状態を確認すると起動中
から停止済み
に変更されているはずです
トリガーの設定
それでは完成したLambda関数をいつ起動・停止するのか
設定していきましょう
Amazon EventBridge
> イベント
> ルール
> ルールを作成
を押します
今回は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に通知する方法も投稿します
ご興味ありましたらお読みください