yyp٩( 'ω' )و

色々触って遊んでます

EC2インスタンスを夜になったら自動で停止する 前編

背景

個人のAWS環境のインスタンスを止め忘れてしまうことが度々あるので、この仕組みを作ることにしました。

方法を考える

1. Lambdaを使う方法

インスタンスを停止する関数を作り、CloudWatch Eventのcronで毎晩起動してあげればできそうです。
"Lambda EC2"でググったら公式のQ&Aもありました。

aws.amazon.com

2. Systems Managerを使う方法

Systems ManagerのAutomationドキュメントに"AWS-StopEC2Instance"というのがあります。
これをMaintenance Windowで毎晩実行するように指定してあげればできそうです。

実装

今回はLambdaの勉強も兼ねて、1. の方法で実装したいと思います。
上で載せたQ&Aを参考に進めていきます。

Lambda関数の作成

Lambda関数を作ります。
「一から作成」を選択して、関数名とランタイムを下記のように設定します。

関数名: StopEc2Instances
ランタイム: Python3.7

アクセス権限については今回はカスタムロールを作るので、
「関数のアクセス権限を定義するロールを選択します。カスタムロールを作成するには、IAM コンソールに移動します。」
からIAMコンソールに移動してロールを作ります。

IAMロールの作成

IAMロールを作ります。
「信頼されたエンティティ」は「AWSサービス」、「このロールを使用するサービス」は"AWS Lambda"を選択し、「次のステップ: アクセス権限」をクリック。
f:id:mizukichi3:20190423210041p:plain 今回はカスタムポリシーを使うので、「ポリシーの作成」をクリックしてポリシーの作成ページに飛びます。
f:id:mizukichi3:20190423210505p:plain "JSON"タブをクリックし、下記のポリシーを貼り付けます。

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

「ポリシーの確認」をクリックし、名前をつけます。今回は"stop-instances-lambda-policy"にしました。
説明は入力しなくても良いので今回は省略します。
「ポリシーの作成」をクリックするとポリシーが作成されるので、作りかけになっていたロールの作成画面に戻ります。
更新ボタン(ぐるぐるしてる矢印マーク)を押して、先ほど作成したポリシーを探し、チェックボックスにチェックを入れます。
「アクセス権限の境界の設定」については今回は必要ないのでそのままで。
次のステップの「タグ」も現時点では必要ないのでスキップします。
ロールの名前をつけて、「ロールの作成」をクリックして終わりです。

Lambda関数の作成 続き

作りかけになっているLambda作成画面に戻ります。
「アクセス権限」 > 「実行ロールの選択または作成」> 「実行ロール」プルダウンから「既存のロールを使用する」を選びます。
更新ボタンを押して、プルダウンを開くと先ほど作成したロールが出てくるので、選択します。
これで関数の箱ができました。

トリガーの設定

Lambda関数を動かすためのトリガーを設定します。
今回は毎日夜0時にインスタンスを停止するように設定します。
Lambdaコンソールで、「トリガーの追加」から"CloudWatch Events"を選択します。
「トリガーの設定」 > 「ルール」で「新規ルールの作成」を選択します。
名前をつけ、ルールタイプの設定をします。
今回は定刻にLambdaを起動したいので、「スケジュール式」を選択します。
「スケジュール式」に下記のcron式を入力します。

cron(0 15 * * ? *)

※ここではタイムゾーンUTCなので、-9した値を使います。
こんな感じです↓
f:id:mizukichi3:20190423213317p:plain

次回: 関数の中身の作成

だいぶ長くなってしまったので、本題とも言えるLambda関数のコードを書くのは後編に分けようと思います。
東京リージョンのインスタンスをすべて停止するように、*とかで指定できるかなと思ったのですが、InstansIdsって必須なんですね…
IDのハードコードはなるべくしたくないので、一旦起動中のインスタンスのIDを持ってきて変数に入れるということが必要そうです。