初めに
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」をクリック。
Select blueprintと表示されますが無視して、左のメニューから「Configure function」を選択。
この画面で起動用の関数と停止用の関数を作成していきます。
まずは起動用の関数から。
項目 | 値 |
---|---|
Name | 適当に |
Description | 適当に |
Runtime | Node.js 4.3 |
Code entry type | Edit code inline |
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
は空のままで、Handler
はindex.handler
を指定。
Role
はセレクトボックスからCreate a custom role
を選択。
選択すると、別タブでロール作成画面が開きます。
別タブで開いた画面では下記のとおりに記述します。
項目 | 値 |
---|---|
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の画面に戻ります。
自動でRole
がChoose an existing role
になり、Exisiting role
が先程作成したロールになっていると思います。
もしなっていなかったら手動で設定してください。
その他設定はいじらず、右下の「Next」をクリック。
確認画面に遷移するので、問題なければ右下の「Create function」をクリック。
作成した関数のテストをして実際にEC2が起動するか確認したいと思います。
「Test」をクリックします。
とくに値をいじらず、右下の「Save and test」をクリックします。
画面にログが表示され、EC2が起動していたら成功です。
起動用の関数が確認できたら停止用の関数も作成します。
基本的に起動用の関数と同じ設定です。
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」をクリック
Event selector
はSchedule
を選択し、Cron expression
のラジオボタンにチェックを入れます。
Cron expression
の値は、0 0 ? * MON-FRI *
を入力してください。
cronの詳細な説明は省きますが、AWSの時間と日本の時間は9時間ずれていて
平日の朝9時に実行したい場合は0 0 ? * MON-FRI *
になります。
Targets
にはLambda function
を選択し
Function
には先程作成した開始用の関数を選択してください。
入力が終わったら「Configure details」をクリック。
最後にスケジュールの名前や説明文を入力します。
項目 | 値 |
---|---|
Name | 適当に |
Description | 適当に |
State | チェックを入れる |
入力したら、「Create rule」をクリックして完了です。
停止用は平日の18時に停止するようにCron expression
に
0 9 ? * MON-FRI *
を入力して、Function
に停止用の関数を設定してください。
これで、平日朝9時にEC2が起動し、平日夜18時にEC2が停止するようになりました。
最後に
夜間停止は思ったより簡単で、AWSのサービスを組み合わせるだけで実現ができました!
あとは、ALBの夜間停止がしたいのですが、どうやらALBは停止という概念はなく
起動しているか、壊すかの2択っぽいです・・・
terraformとかで実現すれば良いのでしょうか・・・調査中です(´・ω・`)