ちょっとしたLambda関数を作りたい時は、Node.jsやPythonエンジンのLambdaを作ることが多いのですが、実はいままで自前のシェルスクリプトでzip化した後にLambdaへアップロードしてデプロイしていました。 (今思うとなかなかに面倒な作業でした…)
しかし、設定周りはAWSコンソール上でぽちぽち操作する必要があるので、Roleやレイヤー、タイムアウト設定が大変苦痛になってきたのでServerless Frameworkを導入しました。
Serverless Frameworkのメリット
- Lambdaや付随するサービスの設定をコードベースで管理できるようになります。
- LambdaのRole、レイヤー、VPC、タイムアウト、メモリ等の各種設定値を予めコードに記述するだけで、デプロイ時にServeless Frameworkが更新してくれるので時短になります。
- API Gatewayの構成も記述できるので、Lambda + API Gatewayの各種設定をコードに書いておけばすぐに使えるAPIがデプロイできます。便利!
- APIの構成がコードになっているので第三者も相関関係が把握しやすい。
Node.jsの単純なAPIを作ってみる
開発環境
- OS: Windows 10 Home (20H2)
$ aws --version aws-cli/2.1.19 Python/3.7.9 Windows/10 exe/AMD64 prompt/off $ node -v v15.14.0 $ npm -v 7.7.6
- Node.js, AWS CLIを予めインストールしておきます。
- AWS CLIはアクセスキー、シークレットキー等の基本設定を完了しておきます。
下準備
- Serveless Frameworkはnpmパッケージなので、まずは開発用の端末にてグローバルインストールします。 ※もし、Node.js自体が入っていない場合はまずはNode.js 6.x以降をインストールしておいて下さい。
$ npm install -g serverless
インストールできたか確認しましょう。
$ serverless -v Framework Core: 2.34.0 Plugin: 4.5.3 SDK: 4.2.2 Components: 3.8.2
プロジェクトの新規作成
プロジェクトを作成したいパスで下記コマンドを実行します。
いくつか質問されますので回答していきます
$ serverless # 新規にプロジェクトを作りたいのでYを入力 Serverless: No project detected. Do you want to create a new one? (Y/n) # カーソルキー上下でLambdaのエンジンを選択しエンター Serverless: What do you want to make? (Use arrow keys) > AWS Node.js AWS Python Other # プロジェクト名を指定してエンター Serverless: What do you want to call this project? Project successfully created in 'EasyAPI' folder. # Serverlessアカウントを作ればモニタリング等ができるようですが、無くてもデプロイは可能なので今回はnを入力(お好みでどうぞ) You can monitor, troubleshoot, and test your new service with a free Serverless account. Serverless: Would you like to enable this? (Y/n)
回答が終わると指定したプロジェクト名のディレクトリとファイルが生成されているはずです。
APIの構成を記述する
今回はEasyAPI
という名前のNode.jsのプロジェクトを作成してみました。
プロジェクトディレクトリ内には下記のファイルが生成されています。
- handler.js
- serverless.yml
- .npmignore
serverless.yml
にLambdaの各種パラメータを記述しておけば、後はSererless Frameworkがうまい具合に設定してくれます。
今回はAPI GatewayでクライアントからのGETリクエストを受け、API Gateway経由でLambda関数を実行するような構成を作ってみます。
serverless.yml
# サービス名を指定(Lambda, APIGatewayの名称の一部に使われる) service: easyapi frameworkVersion: '2' provider: name: aws runtime: nodejs12.x lambdaHashingVersion: 20201221 # dev, prod等の任意のステージ名を指定できます。Lambda, APIGatewayの名前に連結されます。 stage: dev # Lambdaのリージョン region: ap-northeast-1 # Lambdaの環境変数 environment: TZ: Asia/Tokyo # Lambdaのメモリサイズ memorySize: 512 # Lambdaのタイムアウト設定 timeout: 10 functions: # ファンクション名を指定(Lambda, APIGatewayの名称の一部に使われる) hello: # Lambdaのハンドラ。handler.{****}の****にはhandler.jsの最初に呼ばれるメソッド名を指定。 handler: handler.hello # Lambdaの説明文 description: this is practice project. events: # API GatewayでHTTP APIを作成するよう指定 - httpApi: # APIで受け付けるメソッドとパスを指定 path: /hello-world method: get
↓他にもymlに指定できるパラメータはありますので、いろいろと触ってみると良いです。
APIのロジックを書く
デフォルトのhandler.js
にちょっとだけ手を加えました。
クライアントへ返したい値をお好みで書きましょう。
handler.js
'use strict'; module.exports.hello = async (event) => { const today = new Date(); return { statusCode: 200, body: JSON.stringify( { message: `Hello, world. It's ${today.toString()}`, }, null, 2 ), }; };
デプロイする
下記のコマンドを叩くことでserverless.yml
の設定に沿ったサービスが作成されます。
$ serverless deploy Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Uploading service easyapi.zip file to S3 (602 B)... Serverless: Validating template... Serverless: Updating Stack... Serverless: Checking Stack update progress... ......... Serverless: Stack update finished... Service Information service: easyapi stage: dev region: ap-northeast-1 stack: easyapi-dev resources: 11 api keys: None endpoints: GET - https://************.execute-api.ap-northeast-1.amazonaws.com/hello-world functions: hello: easyapi-dev-hello layers: None
初回実行時は完了までに数分程度かかります。
完了後、AWSコンソールでLambda, APIGatewayのページを覗くと下記が作成されていると思います。
- Lambda: easyapi-dev-hello
- API Gateway(HTTP API): dev-easyapi
名称はserverless.yml
のサービス名、ファンクション名、ステージ名を参照したものになっています。
Lambdaのタイムアウトやメモリサイズといったパラメータは、serverless.yml
で指定したものが反映されています。
裏ではCloudFormationが動いている
実はServerless Frameworkの裏側ではCloudFormationのスタックが作成されています。
AWSコンソールで確認すると実際の処理が確認できますね。
APIを実行してみる
APIGatewayに$default
ステージが用意されていますので、URLをブラウザやPostman等でGETリクエストしてみましょう。
今回の例だと↓のようなURLにGETリクエストをすればレスポンスが返ってきます。
https://*************.execute-api.ap-northeast-1.amazonaws.com/hello-world
レスポンス
{ "message": "Hello, world. It's Fri Apr 09 2021 20:10:59 GMT+0900 (Japan Standard Time)" }
これだけでAPIが完成してしまいました! AWSコンソールでポチポチ設定する手間が無くなるのは嬉しいですね😎
ソースコード変更時のデプロイ方法は?
新規作成時と同様にserverless deploy
を叩くと更新されます。
API Gatewayはいらない時
APIGateway無しでLambdaだけを純粋に作りたい場合は、serverless.yml
のevents.httpApi
を記述しなければOK。
あとがき
今回はNode.js向けの記事でしたが、Pythonの場合も初回作成時のエンジンをPythonに指定するだけですので以降の手順はほぼ同じです。
便利なツールは積極的に使っていきたいですね!