Lambdaでインスタンスの自動起動停止を行う
<初めに>
今回社内ブログを書くにあたって、AWS関連の勉強を始めて行うこととなりました。インスタンスの自動起動・停止について勉強し、実践した内容を記載します。
※ついでにhtmlに触れるのも初めてだったので手書きで書いてみることにしました。どこか間違ってたり改善点があれば指摘してもらえると嬉しいです。
<参考にしたサイト>
・EC2インスタンス起動/停止をLambdaで自動化してみた #AWS – Qiita
・cronの日時指定を、基礎から学ぶ(分,時,日,月,曜日の指定、◯分ごと、月末起動、など) – YoheiM .NET
<初期段階>
前に作成したEC2インスタンスが残っていたためこれを使って起動・停止を行ってみようと思います。
<作成開始>
①IAMロールの作成
まずはポリシーを作成します。
IAM>ポリシー>ポリシーを作成>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": "*"
}
]
}
知識がないなりに調べた感じ「arn:aws:logs:*:*:*」の中から「logs:CreateLogGroup」「logs:CreateLogStream」「logs:PutLogEvents」を許可して、全体の中から「ec2:Describe*」「ec2:Start*」「ec2:Stop*」を許可しているみたいなので、ここでは実行できるコマンドや使用できるディレクトリ・ファイルを指定しているのかなという認識でした。
※社内の先輩に聞いたところ大体の認識は間違っていなかったみたいです。
コード記述後名前を、参考にしたサイトと同じ、「lambda_for_start_stop_instance」としポリシーを作成しました。
ポリシーが作成出来たらIAM>ロール>ロール作成と進み、下記のように設定しました。
信頼されたエンティティ:AWSサービス
ユースケース:Lambda
「次へ」をクリックし、作成したポリシーを選択します。(startと打つと出てきました。)
選択したまま「次へ」を押すとした画像が出てくるのでロール名を参考サイト通り
「start_stop_instance_lambda」としました。
下にスクロールすると、タグの設定などありましたが特に設定必要なさそうだったのでこれで作成しました。
②Lambda関数の作成
ロールが作成できたのでいよいよ関数を作成していきます。
Lambda>関数>関数の作成 で下のような画面に映ります。
関数名:start_stop_ec2_instance(参考サイトと同じ)
ランタイム:Python 3.8(参考サイトではPythonで作成した模様)
関数のロール:作成したロールを選択する。
関数の作成を押してLambda関数を作成します。
③起動・停止の実装
先ほど作成した関数のコードを変更し、起動・停止を行うための関数にします。
「コード」タブに移動すると、コードの中身が表示されます。ここに以下のコードを書き込みます。
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.')
参考にしたサイトにコードが書いてあってコピペできて楽でしたけど、
意味わからないままは気持ち悪かったので自力で写しながら最低限調べました。
とりあえず、すごくアバウトな理解で最初4行はモジュールを取り込んだり
環境変数・変数の指定を行ったりしていて、def以降で関数の定義、関数内で使う変数、
処理を記述しているとしておきます。(処理内容は何となくわかるのでよしとします笑)
さてコードはかけたので「Deploy」ボタンを押して保存しておきます。(重要)
ここでは汎用性を高くするために「INSTANCE_ID」をLambda関数全体の環境変数とすることでほかのインスタンスにも流用できるようにしているとのことでした。頭いいなぁと普通に感心してしまったので、ほかインスタンス作る予定もないのに真似しておきました。
設定タブ>環境変数>編集>環境変数の追加から上記画面に移動するのでここで設定すると
Lambda関数内で変数として認識されるそうです。入力出来たら保存を押して環境変数を追加します。
④テスト
完成したLambda関数が動くかどうかテストを行います。
準備:起動・停止を行うインスタンスをあらかじめ起動しておくこと。
Lambda関数の詳細ページを下にスクロールするとタブ選択ができるところがあるので「テスト」タブを選択してリクエストを作成します。
①「テスト」タブを選択
②「新しいイベントを作成」を選択
③イベント名は任意(ここでは参考サイトと同様に「stop_request」とした)
④テンプレートオプションは「hello-world」を選択
⑤ イベントJSONに{”Action”:”Stop”}を入力、元のテキストは削除し
⑥保存をクリック
⑦⑥まで終わると保存されたイベントに作成したイベントがあるので選択して「テスト」ボタンをクリックする。
⑧ 成功すると上記のようになります。(インスタンスも停止していることが確認できます)
※Lambda関数のコードをどこか間違えていたみたいで一度目はエラーが出たのは内緒の話。やはりコピペか補完機能に頼るのが一番ですね。
⑤トリガーの設定
Lambda関数はできましたが、定期的に自動起動・停止を行うのはどうやらほかのサービスを利用するみたいですね。
Amazon EventBridgeというサービスを使うみたいで、Lambda関数の実行ルールだけでなく、「イベント」を通じてさまざまなアプリケーション同士を接続することができるみたいなのですが、これはおいおい勉強できればなと…
今は、イベントをスケジュールする機能があることだけ覚えておこうかなと思います。
参考サイトに書かれていたイベントというタブが見つからなかったので焦りましたが、
バス>ルール>ルールを作成
とたどると同じ用に作成できました。
参考サイトはイベントパターンをスケジュールにすると書かれていましたがおそらく下記選択で良いはず。(ここで参考サイトが更新された日を確認すると2021年でした。そのためいろいろ変わっている様子)
名前:start_ec2_instance_at_0900
説明:毎日9:00に{“Action”: “Start”}リクエストを投げるルール
イベントパス:デフォルト
ルールタイプ:スケジュール
記入後下にスクロールし、「EventBridge Schedulerで続行」をクリック
次の画面に映ったら少し下にスクロールして上記画像のように設定をします。
頻度:定期的なスケジュール
スケジュールの種類:cronベースのスケジュール
cron式:任意のものを入れる。(メタキャラクタを使えるとのこと。調べたところ?と*があるのは日付と曜日に同じものを入れられないためらしい。)
上画像では毎日00:00に設定されていると思ったのですが、参考サイトでは09:00に起動と書いました。2021年段階では日本のタイムゾーンが選択できなかったのかも?これも動かしてみて結果が楽しみです。
あとは、フレックスタイムウインドウをオフ(特に実行時間に幅を持たせる必要はないかなと思ったのでオフにしました。)にして、開始日時と終了日時を入力したら下にスクロールして作成します。
これでインスタンスの起動は自動化できたはずなので同様の手順で停止のイベントを作成します。
起動から変更する必要のある項目は下記です。
説明:毎日21:00に{“Action”: “Stop”}リクエストを投げるルール(任意)
cron式:0 12 ? * * * (これもおそらく12時に停止すると考えている。)
ここまでで設定は終了。さて、あとは結果待ち。翌日以降に持ち越し~(2024/02/29)
⑥結果
まず出社後確認したインスタンスの稼働状況が下画像です。
インスタンスの実行状態:実行中
日時:2024/3/1 09:53
出社後すぐの8時ごろにも確認したのにスクショを取り忘れるアホは僕です。
その時も実行中だったのでやっぱり0:00に起動したのではないかと。
この後12:00以降に確認して止まっていれば、ここ数年で日本のタイムゾーンが選択できるようになった認識でよさそうですね。
~~~~~~~~~~
12時超えてウキウキで確認したインスタンスの状態が下画像です。
インスタンスの実行状態:実行中
日時:2024/3/1 12:07
どうやら起動も停止も正常に動作したみたいですね。
また、予想通り起動0:00、停止12:00で動作しているみたいです。
CloudWatchでログを確認しました。どうやら毎日動いているみたいですね。(2024/3/2)
何はともあれ、これにて起動停止の自動化は成功ということでちょっとした達成感を感じています。
<まとめ>
今回はインスタンスの自動起動・停止について勉強実践した内容をまとめさせてもらいました。ほぼ初めて触るAWSでしたが、できることの幅が広そうで面白そうな分野だなと感じました。特に初心者でも、情報が多く検索に引っかかるのでとっつきやすいのはうれしいです。次回はもう少し難易度の高いものに挑戦してみようと思います。
コメント