LoginSignup
11
15

More than 5 years have passed since last update.

CloudWatchとLambdaによるEC2の夜間停止

Posted at

初めに

AWSのアドベントカレンダーもっと盛り上がれ!もう時代遅れか!?

と念じております。

さてさて、前回はWEBアプリケーションの環境を構築しましたが

今回はEC2の夜間停止をCloudWatchとLambdaを利用して実装していきたいと思います。

夜間停止の流れはLambdaで起動用の関数と停止用の関数を作成し

CloudWatchを利用して朝に起動用の関数を、夜に停止用の関数を実行することで実現させます。

第1部 「AWSを避けていたPGがALBとEC2を利用してWEBアプリケーション環境を構築してみた

第2部 「LambdaとCloud WatchによるEC2の夜間停止」←今ここ

第3部 「ALBによるパスルーティング」

前置き

LambdaのScheduleイベントでEC2を自動起動&自動停止してみた#reinventを基本的に参考にして構築をしております。

解釈や説明の誤りなど、コメント欄に記載していただけると幸いです。

Lambda

さて、まずLambdaです。

左のメニューから「Function」を選択肢、「Create a Lambda function」をクリック。

スクリーンショット 2016-12-21 22.17.31.png

Select blueprintと表示されますが無視して、左のメニューから「Configure function」を選択。

スクリーンショット 2016-12-21 22.20.27.png

この画面で起動用の関数と停止用の関数を作成していきます。

まずは起動用の関数から。

項目
Name 適当に
Description 適当に
Runtime Node.js 4.3
Code entry type Edit code inline

スクリーンショット 2016-12-21 22.27.50.png

Lambda function codeには下記、起動用の関数を、記述します。

INSTANCE_IDにはEC2のinstance idを、AWS.config.regionにはリージョンを入れてください。

リージョンに関しては東京なら ap-northeast-1です。

その他リージョンの場合は下記公式から確認してください。

リージョンとアベイラビリティーゾーン

const INSTANCE_ID = '*****';

var AWS = require('aws-sdk'); 
AWS.config.region = '*****';

function ec2Start(cb){
    var ec2 = new AWS.EC2();
    var params = {
        InstanceIds: [
            INSTANCE_ID
        ]
    };

    ec2.startInstances(params, function(err, data) {
        if (!!err) {
            console.log(err, err.stack);
        } else {
            console.log(data);
            cb();
        }
    });
}
exports.handler = function(event, context) {
    console.log('start');
    ec2Start(function() {
        context.done(null, 'Started Instance');
    });
};

Environment variablesは空のままで、Handlerindex.handlerを指定。

RoleはセレクトボックスからCreate a custom roleを選択。

選択すると、別タブでロール作成画面が開きます。

スクリーンショット 2016-12-21 22.58.13.png

別タブで開いた画面では下記のとおりに記述します。

項目
IAM Role Create a new IAM Role
Role Name 適当に

Policy Documentは下記jsonを記述します。

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

記述したら右下の「Allow」をクリックします。画面が閉じるので、Lambdaの画面に戻ります。

スクリーンショット 2016-12-21 23.07.46.png

自動でRoleChoose an existing roleになり、Exisiting roleが先程作成したロールになっていると思います。

もしなっていなかったら手動で設定してください。

スクリーンショット 2016-12-21 23.18.49.png

その他設定はいじらず、右下の「Next」をクリック。

スクリーンショット 2016-12-21 23.20.19.png

確認画面に遷移するので、問題なければ右下の「Create function」をクリック。

スクリーンショット 2016-12-21 23.21.10.png

作成した関数のテストをして実際にEC2が起動するか確認したいと思います。

「Test」をクリックします。

スクリーンショット 2016-12-21 23.28.24.png

とくに値をいじらず、右下の「Save and test」をクリックします。

画面にログが表示され、EC2が起動していたら成功です。

スクリーンショット 2016-12-21 23.29.36.png

起動用の関数が確認できたら停止用の関数も作成します。

基本的に起動用の関数と同じ設定です。

Lambda function codeは下記のコードを

const INSTANCE_ID = '*****';

var AWS = require('aws-sdk'); 
AWS.config.region = '*****';

function ec2Stop(cb){
    var ec2 = new AWS.EC2();
    var params = {
        InstanceIds: [
            INSTANCE_ID
        ]
    };

    ec2.stopInstances(params, function(err, data) {
        if (!!err) {
            console.log(err, err.stack);
        } else {
            console.log(data);
            cb();
        }
    });
}
exports.handler = function(event, context) {
    console.log('start');
    ec2Stop(function() {
        context.done(null, 'Stoped Instance');
    });
};

ロールのPolicy Documentは下記jsonを

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

これで、起動用の関数と停止用の関数が作成できました。

CloudWatch

さて、次に(最後ですが)CloudWatchを利用して朝と夜にLambdaの関数を実行したいと思います。

CloudWatchのページで、左のメニューから「Rules」を選び、「Create rule」をクリック

スクリーンショット 2016-12-22 20.35.52.png

Event selectorScheduleを選択し、Cron expressionのラジオボタンにチェックを入れます。

Cron expressionの値は、0 0 ? * MON-FRI *を入力してください。

cronの詳細な説明は省きますが、AWSの時間と日本の時間は9時間ずれていて

平日の朝9時に実行したい場合は0 0 ? * MON-FRI *になります。

TargetsにはLambda functionを選択し

Functionには先程作成した開始用の関数を選択してください。

入力が終わったら「Configure details」をクリック。

スクリーンショット 2016-12-22 20.38.27.png

最後にスケジュールの名前や説明文を入力します。

項目
Name 適当に
Description 適当に
State チェックを入れる

入力したら、「Create rule」をクリックして完了です。

スクリーンショット 2016-12-22 20.44.52.png

停止用は平日の18時に停止するようにCron expression

0 9 ? * MON-FRI *を入力して、Functionに停止用の関数を設定してください。

これで、平日朝9時にEC2が起動し、平日夜18時にEC2が停止するようになりました。

最後に

夜間停止は思ったより簡単で、AWSのサービスを組み合わせるだけで実現ができました!

あとは、ALBの夜間停止がしたいのですが、どうやらALBは停止という概念はなく

起動しているか、壊すかの2択っぽいです・・・

terraformとかで実現すれば良いのでしょうか・・・調査中です(´・ω・`)

11
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
15