AWS Lambda で EC2 インスタンスを自動起動・停止してみる (セットアップ編)
こんにちは、まちいろの工藤です。
先日の AWS Summit レポートでも
今回の AWS Summit では「サーバーレス」という単語がよく聞こえてきました。
Lambda をうまく利用することで、開発・運用コストの最小化でき、 かつアプリケーションからビジネスロジック以外のコードを切り出すことができる、というのはかなりキャッチーですね。
事例で紹介されていた、EC2 インスタンスを日中だけ起動しておくよう Lambda で制御する、というのは面白いなと思いました。
と触れましたが、今回は事例として紹介されていた「EC2 インスタンスの自動起動・停止」に挑戦してみたいと思います。
まずはコンソール画面から触ってみる
Lambda がどんなものか、まずはコンソールから Lambda Function を登録してみたいと思います。
ヘッダメニューのサービスから、[コンピューティング]-[Lambda] にアクセスします。
Lambda Function を追加する
「Step 1: Select blueprint」は【Skip】ボタンを押してスキップします。
次に、「Step 2: Configure function」にて以下の設定を行います。
項目 | 設定 |
---|---|
Name | lambda-test |
Runtime | Node.js 4.3 |
Code entry type | Edit code inline |
Handler | index.handler |
Role | Create new role - * Basic execution role |
ソースコードには、サンプルとして以下のコードを貼り付けます。
他にも ZIP ファイルをアップロードしたり、S3 に配置した ZIP ファイルを読ませる方法があるようです。
exports.handler = (event, context) => { console.log('lambda test'); };
Role のプルダウンを変更すると、IAM ロールの登録画面が別ウィンドウで表示され、Lambda を実行するために必要なポリシーが予め設定された状態となります。
このロールは後ほど使用したいので、名称に EC2_OPERATING_SCHEDULE_MANAGER
と付けて保存しておきます。
登録が完了すると、Lambda Function の設定画面側で追加した IAM ロールが選択された状態となります。
以上の設定で Lambda Function を追加します。
動作確認
Lamda Function の詳細画面の【Test】ボタンからテストを実行します。
ここで Function に渡すパラメータを定義可能ですが、今回はサンプル Hello World
そのままで実行します。
実行すると、画面下部に実行結果が表示されます。
先ほど貼り付けたコードに記述した console.log
の実行結果がログに出力されていれば成功です。
ローカル開発環境の構築
コンソールを触ってみた印象としては、コードの修正・デプロイの流れが面倒そうに感じました。
そこで、ローカルのソースコードを ZIP 化 -> デプロイまでの流れを作ってみたいと思います。
今回はこの要件にぴったりな npm モジュール node-aws-lambda
を使用したいと思います。
gulp セットアップ
まずは node-aws-lambda
を使ったデプロイに必要な各種モジュールをインストールします。
$ npm install gulp gulp-install gulp-zip del node-aws-lambda require-dir run-sequence --save-dev
次に gulpfile.js
を作成します。
require-dir
モジュールを使って、タスクファイルの分割を行っています。
var dir = require('require-dir'); dir('./gulp/tasks', {recurse: true});
node-aws-lambda
の README を参考に、デプロイ用のタスクファイル gulp/tasks/deploy.js
を作成します。
const gulp = require('gulp'); const zip = require('gulp-zip'); const del = require('del'); const install = require('gulp-install'); const runSequence = require('run-sequence'); const awsLambda = require("node-aws-lambda"); gulp.task('clean', function() { return del(['./dist', './dist.zip']); }); gulp.task('js', function() { return gulp.src(['index.js']) .pipe(gulp.dest('dist/')); }); gulp.task('node-mods', function() { return gulp.src('./package.json') .pipe(gulp.dest('dist/')) .pipe(install({production: true})); }); gulp.task('zip', function() { return gulp.src(['dist/**/*', '!dist/package.json']) .pipe(zip('dist.zip')) .pipe(gulp.dest('./')); }); gulp.task('upload', function(callback) { awsLambda.deploy('./dist.zip', require("./lambda-config.js"), callback); }); gulp.task('deploy', function(callback) { return runSequence( ['clean'], ['js', 'node-mods'], ['zip'], ['upload'], callback ); });
node-aws-lambda
用の設定ファイル gulp/tasks/lambda-config.js
を作成します。
role
には先ほど作成した IAM ロール EC2_OPERATING_SCHEDULE_MANAGER
の arn を指定します。
注意点として、指定した profile
に Lambda Function の登録・更新権限を付与しておく必要があります。
module.exports = { profile: 'machiiro', region: 'ap-northeast-1', handler: 'index.handler', role: 'arn:aws:iam::xxxxxxxx:role/EC2_OPERATING_SCHEDULE_MANAGER', functionName: 'lambda-test', timeout: 5, memorySize: 128, publish: false, runtime: 'nodejs4.3' }
最後に、package.json
の script
に gulp 実行用の設定を追加しておきます。
"scripts": { "gulp": "gulp" },
デプロイ
コンソール画面で貼り付けたソースコードを index.js
として作成します。
正常にデプロイされたことがわかるよう、ログに出力するメッセージをちょっといじっておきます。
exports.handler = (event, context) => { console.log('lambda test2'); };
最終的なファイル構成は以下のようになります。
gulp/ tasks/ deploy.js lambda-config.js node_modules/ gulpfile.js index.js package.json
デプロイを実行してみます。
$ npm run gulp deploy > gulp "deploy" [12:47:12] Using gulpfile path-to-path/gulpfile.js [12:47:12] Starting 'deploy'... [12:47:12] Starting 'clean'... [12:47:12] Finished 'clean' after 8.02 ms [12:47:12] Starting 'js'... [12:47:12] Starting 'node-mods'... [12:47:12] Finished 'js' after 19 ms npm WARN package.json lambda-test@1.0.0 No description npm WARN package.json lambda-test@1.0.0 No README data [12:47:13] Finished 'node-mods' after 716 ms [12:47:13] Starting 'zip'... [12:47:13] Finished 'zip' after 28 ms [12:47:13] Starting 'upload'... [12:47:14] Finished 'upload' after 597 ms [12:47:14] Finished 'deploy' after 1.36 s
Lambda の画面から再度テストを実行してみましょう。
ログに出力されるメッセージが変更したものになっていれば、デプロイは正常に動作しています。
まとめ
今回は Lambda を一から触りつつ、gulp をつかってソースコードをデプロイする流れを構築してみました。
次回は、実際に EC2 インスタンスの起動・停止させる部分を実装していきたいと思います。