AWS Lambdaを使ってEC2インスタンスを定時にcronで停止、起動させる。

イベントソースに「CloudWatchイベント」を指定することで、Lambda関数を一定時間ごとに実行させることができます。
イベントソースとは、Lambda関数を呼び出す引き金となるもののことです。
イベントソースにはS3やDynamoDB、API Gatewayなど色々なものを指定することができます。

EC2の利用料金を節約するために、使わない時間はインスタンスを停止しておきたいという人もいると思います。

使わない時間に停止して、使いたい時間に起動させるという使い方ができれば、EC2の利用料金を大きく削減できる可能性があります。
たとえば、開発用の環境は夜の20時には落として、朝の7時に上げるように設定するとかですね。

今回はLambda関数を使って、定時にEC2を停止、起動させてみます。

まずはLambdaで関数を作成します。スクラッチ(1から作成する)でOKです。
![Lambda Management Console - Google Chrome 2018-01-03 08.58.24.png](https://qiita-image-store.s3.amazonaws.com/0/226431/a8ac4ec9-5839-12c3-5c58-d4847e7a5433.png)

イベントにCloudWatchイベントを設定します。
![Lambda Management Console - Google Chrome 2018-01-03 08.59.10.png](https://qiita-image-store.s3.amazonaws.com/0/226431/eced2226-929f-6c18-26c8-2e7376cd2e21.png)

CloudWatchイベントの詳細を設定していきます。
![Lambda Management Console - Google Chrome 2018-01-03 08.46.20.png](https://qiita-image-store.s3.amazonaws.com/0/226431/4d03509e-411a-a9c8-82b6-6080de446328.png)

ルールタイプは「スケジュール式」とします。

> cron 式は、協定世界時 (UTC) です。

とあります。
つまり、このcron式で設定された時刻+9時間が日本時間となります。

ルールのスケジュール式については以下のページが参考になります。
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html

|フィールド|値|ワイルドカード|
|-----|-----|-----|
|分|0-59|, - * /|
|時間|0-23|, - * /|
|日|1-31|, - * ? / L W|
|月|1-12 または JAN-DEC|, - * /|
|曜日|1-7 または SUN-SAT|, - * ? / L #|
|年|1970-2199|, - * /|


```
cron(0 13 * * ? *)
```
と指定しているので、22時にLambda関数が起動する設定ですね。

では実際にLambda関数を作成していきます。

「StopEC2Instance」という自分が作成した関数名をクリックします。
![Lambda Management Console - Google Chrome 2018-01-03 09.01.12.png](https://qiita-image-store.s3.amazonaws.com/0/226431/ead36f34-c43f-7f5f-5d93-fe7aba87aaba.png)

画面の下の方でコードを書く部分があるので、そこに以下のような関数を書きます。

```python
import boto3

region = 'ap-xxxxxxxx-x'
instances = ['x-xxxxxxxx']
def lambda_handler(event, context):
    # TODO implement
    ec2 = boto3.client('ec2', region_name=region)
    ec2.stop_instances(InstanceIds=instances)
    
    return 'Stopped these instances: ' + str(instances)
```

`instance = ['x-xxxxx']`にはEC2のインスタンスIDを指定して下さい。

`region = 'ap-xxxxxxxx-x'`にはリージョンのIDを指定します。
https://docs.aws.amazon.com/ja_jp/general/latest/gr/rande.html
東京だったら`ap-northeast-1`ですね。

|リージョン名|サービス対象|エンドポイント|プロトコル|Amazon Route 53 ホストゾーン ID*|
|-----|-----|-----|-----|-----|
|米国東部 (オハイオ)|us-east-2|apigateway.us-east-2.amazonaws.com|HTTPS|ZOJJZC49E0EPZ|
|米国東部（バージニア北部）|us-east-1|apigateway.us-east-1.amazonaws.com|HTTPS|Z1UJRXOUMOOFQ8|
|米国西部 (北カリフォルニア)|us-west-1|apigateway.us-west-1.amazonaws.com|HTTPS|Z2MUQ32089INYE|
|米国西部 (オレゴン)|us-west-2|apigateway.us-west-2.amazonaws.com|HTTPS|Z2OJLYMUO9EFXC|
|アジアパシフィック (ムンバイ)|ap-south-1|apigateway.ap-south-1.amazonaws.com|HTTPS|Z3VO1THU9YC4UR|
|アジアパシフィック (ソウル)|ap-northeast-2|apigateway.ap-northeast-2.amazonaws.com|HTTPS|Z20JF4UZKIW1U8|
|アジアパシフィック (シンガポール)|ap-southeast-1|apigateway.ap-southeast-1.amazonaws.com|HTTPS|ZL327KTPIQFUL|
|アジアパシフィック (シドニー)|ap-southeast-2|apigateway.ap-southeast-2.amazonaws.com|HTTPS|Z2RPCDW04V8134|
|アジアパシフィック (東京)|ap-northeast-1|apigateway.ap-northeast-1.amazonaws.com|HTTPS|Z1YSHQZHG15GKL|
|カナダ (中部)|ca-central-1|apigateway.ca-central-1.amazonaws.com|HTTPS|Z19DQILCV0OWEC|
|欧州 (フランクフルト)|eu-central-1|apigateway.eu-central-1.amazonaws.com|HTTPS|Z1U9ULNL0V5AJ3|
|欧州 (アイルランド)|eu-west-1|apigateway.eu-west-1.amazonaws.com|HTTPS|ZLY8HYME6SFDD|
|欧州 (ロンドン)|eu-west-2|apigateway.eu-west-2.amazonaws.com|HTTPS|ZJ5UAJN8Y3Z2Q|
|南米 (サンパウロ)|sa-east-1|apigateway.sa-east-1.amazonaws.com|HTTPS|ZCMLWB8V5SYIT|

関数の作成が終わったら右上の「保存」を押します。

複数のインスタンスを指定したい場合は`instances = ['x-xxxxxxxx','x-xxxxxxxx','x-xxxxxxxx']`のように配列にIDを入れます。

ここまで作ったら関数をテストします。

右上のテストをクリックして、「テストイベントの設定」を選択してください。
![Lambda Management Console - Google Chrome 2018-01-03 11.14.00.png](https://qiita-image-store.s3.amazonaws.com/0/226431/8cff925c-9701-8c70-d697-b74309b599c2.png)

イベントテンプレートは「Scheduled Event」とします。
![Lambda Management Console - Google Chrome 2018-01-03 09.07.42.png](https://qiita-image-store.s3.amazonaws.com/0/226431/8714c56e-754b-21e8-af50-f06d384a9bb9.png)

作成できたら、上部には以下のように表示されているはずです。
![Lambda Management Console - Google Chrome 2018-01-03 10.44.32.png](https://qiita-image-store.s3.amazonaws.com/0/226431/00012197-61c0-10ef-b5b0-f2c2c61fc030.png)

「テスト」を実行してEC2インスタンスが停止することを確認します。

次に、起動用のLambda関数を作成します。
基本的には停止の関数を作ったときと同じことをやります。

スクリプトは以下の通りです。

```python
import boto3

region = 'ap-xxxxxxxx-x'
instances = ['x-xxxxxx','x-xxxxx','x-xxxxxxx','x-xxxxxx']
def lambda_handler(event, context):
    # TODO implement
    ec2 = boto3.client('ec2', region_name=region)
    ec2.start_instances(InstanceIds=instances)
    
    return 'Started these instances: ' + str(instances)
```

この関数を実行すると、EC2インスタンスが起動することが確認できました。