AWS LambdaからのEC2インスタンスの起動を再現してみた

# 経緯
弊社SIGNIFIの自社事業として「[りふり](https://rifuri.jp/)」という介護事業があります。
2018年のオープン時に請求関連の業務システムを
我々システムソリューション本部のメンバーでAWS環境に構築して運用していました。

りふりシステムのインフラとしては、DBのバックアップをS3に日次で取得したり、
AWS Lambdaを利用して業務時間外のサーバ停止・起動を自動化していました。

Qiitaの寄稿にあたり、2023年10月時点での最新のAWS環境（Lambda）を利用したサーバ（EC2）の
起動を再度トライしてみようと思います。
（時間指定の停止などは次回以降で）

それでは行ってみましょう！

# 流れ
① AWSアカウントの作成【今回省略】
② EC2インスタンスの作成【今回省略】
③ IAMポリシーとロールの作成
④ LambdaでEC2インスタンスの起動の設定

# ③IAMロールの作成
### ポリシー作成
AWSコンソールにログインし、まずはロールに紐づけるポリシーから作成します。
IAMサービスの アクセス管理 → ポリシー を選択して”ポリシー”画面から
［ポリシーの作成］ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/8a559364-66f7-b514-8ba3-571d5d2200ed.png)


”アクセス許可を指定”画面で JSON を選択して
ポリシーエディタに下記のように記述したら［次へ］ボタンを押下。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/fc390c7c-c760-6624-2cef-69226ee6c3ce.png)

```
{
    "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": "*"
        }
    ]
}
```
”確認して作成”の画面にて、任意のポリシー名を入力。
［ポリシーの作成］ボタンを押下してポリシーを作成を完了させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/ec27da9c-1ded-d9ba-5e80-08b6bda94f50.png)

### ロール作成
次に、IAMサービスの”ロール”から「ロールを作成」を押下して進めます。

”信頼されたエンティティタイプ：AWSのサービス”、
”ユースケース：Lambda”
をそれぞれ選択して、次に進みます。

「許可ポリシー」にて、”絞り込みタイプ：カスタマー管理” を選択して、
先程作成したポリシーにチェックを入れて次に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/d04c17d7-3010-e239-36a3-cb07a358a946.png)

”ロール名”に任意の名前を入力して、［ロールを作成］ボタンを押してロールを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/77dec2be-71aa-812b-9d77-d265bdebab35.png)

「ロール Start_EC2_ByLambda が作成されました。」と表示されたら完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/7942628d-d503-6c18-ce5e-13a168f1eb85.png)


### ロールにポリシーをアタッチ
作成したロール名をクリックして、ロールの情報を表示します。
”許可ポリシー”の中の作成したポリシーを選択した状態で、
［許可を追加］内の”ポリシーをアタッチ”をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/01f07345-1bd1-ca31-2438-900162b875a8.png)

作成したポリシーを選択して、ポリシーのアタッチの順に進めて
”絞り込みタイプ：カスタマイズ管理”を選択して、
先程作成したポリシーにチェックを入れてアタッチします。
　
# ④LambdaでEC2インスタンスの起動の設定
### Lambda関数の作成
Lambda関数を作成していきます。

Lambdaにて”関数”を選択し、
［関数の作成］ボタンを押下します。

”オプション：一から作成"
関数名：（任意の関数名）
”ランタイム：python3.8"
を選択・入力し、
「デフォルトの実行ロールの変更」を開きます。
”既存のロールを使用する”を選択し、
流れ①で作成した作成したロールをドロップダウンから選択して、
ページ下にある［関数の作成］ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/7043b55e-b9c1-01a7-7e07-fc6c256809b8.png)

### 起動処理コードの設定
EC2の起動処理コードを設定していきます。

上記の流れで関数が正常に作成されると、
作成したLambda関数の詳細画面が表示されるので、
この後にコードで使用する環境変数を設定します。

「設定」内にある”環境変数”で［編集］ボタンを押下すると、
「環境変数の編集」ページになるので、
”キー：INSTANCE_ID”
”値：（EC2インスタンスページの”インスタンス ID”）”
を入力して、［保存］ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/495f934e-6e24-6658-04ac-880a2be1a667.png)

いよいよコードを書いていくので、
「コード」内の「コードソース」内の”lambda_function.py”ファイルを選択して、
”lambda_function.py”タブ内のエディタに起動処理を設定していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/e0d7d207-0882-c0b3-b091-ef82c877bdfa.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(' My SIG instance: ' + instances[0] + ' is ' + ec2_status + ' now.')

    if action == "Start":
        ec2.start_instances(InstanceIds=instances)
        print('My SIG instance: ' + str(instances[0]) + 'is Started!!!')

    else:
        print('Input Error!!!')
```

コードを作成したら［Deploy］ボタンを押して変更を保存します。
※［Deploy］ボタンを押さないとコードの変更が反映されません

### テスト実行
［Test］ボタンを押下すると、テスト実行するためのイベント設定が出来ます。

イベント名に任意の名前を入力し、
”イベント共有の設定”、”テンプレート”はデフォルトのままで、
”イベントJSON”のエディタに実行時の引数として
```
{
　　"Action": "Start"
}
```
と記述して、［保存］ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/a4859e0e-022d-2a4a-9bad-b0bb55e8c90d.png)

「コード」内の［Test］をクリックして実行します。
”Functional Logs”にコードで出力設定した内容が表示されます。

正常終了すると、「Status:Succeeded」と表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3427723/db8287c6-df05-e50a-e990-32bde1cafc9f.png)

『EC2サービス』の「インスタンス」にて、
”インスタンスの状態” が ”実行中” となったら、一通りの設定が完了です。


# 振り返り
遠い記憶やエビデンスを引っ張り出しながら、
5年前からGUIもかなり変わっていることも相まってアタフタしながら構築・設定してみました。
下記の参考ページにかなり助けられながら(ほぼトレース状態でしたが)、
なんとか再現が出来た、というところでしょうか。
これをきっかけに、もう少しAWSを触っていこうと思います。

## 参考
「【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム＆スケジュール化手順【2018年最新版】」
https://go-journey.club/archives/7400

「EC2インスタンス起動/停止をLambdaで自動化してみた」
https://qiita.com/YK0214/items/59bc0e5ae89f68af74b3