AWS CloudFormationの記事でも書いたのですが、AWS Lambda と API Gateway の管理は Serverless でやっています。
そこに至るまでの経緯のポエムおよび、Serverlessの使い方の簡単な説明です。
きっかけ
LambdaがどういったURLで呼び出されるかは、Lambdaではなく、API Gatewayで設定します。
API Gatewayの設定は下記のようなGUIで行えるのですが、設定箇所は結構多く、LambdaとAPI Gatewayを手動で管理するのにはすぐに限界が来て、何かしらの管理ツールを使う必要があるなと調べ始めました。
モチベーション低下
調べてみると、管理ツールとして「Serverless」「AWS SAM」「Swagger」などの候補が上がってきたのですが、その過程で、「GraphQL」なるキーワードを知ってしまいました。
「GraphQL」とは、Facebookが提唱する、REST APIに代わる新しいAPI手順で、今回は使うつもりは無かったのですが、そういった物が出てくるということは、REST APIも過渡期かなと、REST APIに取り組むモチベーションが一気に冷めてしまいました。
また、GCPやAzureも似たようなFunctionやAPIサービスを提供しているのですが、それぞれ仕組みはバラバラで、それらをまとめる万能ツールは難しいのかなとも感じていました。
なので、汎用性は無くてもいいので、できるだけ学習コストが低く、簡単に使えるものがいいなぁと思い始めました。
試してみる
そんな中、CloudFormationなら、その知識はAWS全般にも使えるのでいいかなぁと思い、やってみたのですが、記事に書いたとおり痛い目にあいました。
次に「Serverless」を試してみたのですが、使いやすくて結局そのまま使い続けることになりました。
Serverlessのメリット
- 必要最小限の記述でよしなに動いてくれます。
- Lambda・API Gatewayの機能はほぼ網羅しています。
- Serverlessでカバー仕切れない機能は、CloudFormationで補うことができます。
未設定部分はServerlessの方でデフォルトの設定を補ってくれるので、設定は少ない記述で済み分かりやすかったです。
利用手順
Serverlessのインストールはnpm install -g serverless
とnpmを使って行います。
次に、設定ファイル「serverless.yml」を記述し、プログラムが置かれているディレクトリに置きます。
そして、serverless deploy
とすると、プログラムがアップされてLambdaが作成され、API Gatewayでパスが作られ、パスとLambdaの紐づけを行ってくれます。
プログラムやパスを変更した際は、再度serverless deploy
とすると更新されます。
例
例えば、パス「/test/message」をGETでアクセスすると「{'result': 'Hello World!'}」と返す Lambda+API Gatewayは下記のようになります。 更にここでは、開発と本番でAPIを分けられるようにしてみます。
helloWorld.ts(JavaScriptに変換しています)
exports.handler = async (event: any, context: any) => { try { return { result: 'Hello World!' }; } catch (err) { console.error(err); throw err; } }
serverless.yml
service: serverless-test-api # プロジェクト名 provider: name: aws stage: ${opt:stage} # ステージ名(パラメータ化) endpointType: REGIONAL role: arn:aws:iam::xxxx # Lambdaのロール runtime: nodejs8.10 region: ap-northeast-1 deploymentBucket: name: serveless-test-bucket # Lambdaのアップ先のS3バケット名 functions: hello-world: # 関数名(論理名) name: hello-world-dev-${self:provider.stage} # 関数名(Lambda実名) handler: helloWorld.handler # ハンドラ(<JavaScriptファイル名>.<function名>) events: - http: path: test/message # パス method: get # メソッド integration: lambda
serverless deploy --stage 'dev'
と打つと、LambdaとAPI Gatewayがアップされます。
Serverlessには開発・本番等のステージを分ける仕組みが入っていて、YAMLの「stage」で設定します。そのステージ名で全体のAPIが作成されるので、ステージ名で開発・本番でAPIを分けることができるのです。
また、ステージ名はパラメータ化でき、serverless deploy
コマンド実行時に決めることができます。そして、ステージでLambda関数も変えたかったので、YAML内でステージ名を参照する変数「${self:provider.stage}」を使って名前の切り替えを行っています。
これで、パスの変更や、ステージの追加・切り替えがちょっと記述を変えるだけでできてしまいます。これをAWSのGUIでやることを考えるとゾッとします…。
補足説明
- Serverlessは内部的にはCloudFormationを使ってLambda・API Gatewayのデプロイを行っているので、
serverless remove
でごっそりLambda・API Gatewayごと削除することもできます。 - API Gatewayだけでなく、S3やCloudWatch等の、他のLambdaトリガーもServerlessで記述できます。
Lambdaを使っていると、関連するAWSリソースをまとめて管理したくなります。Serverlessを使えば、「resources」項目でCloudFormationの記述で、それらのリソースを作成・設定することができます。
例えば、LambdaのロールをServerlessで作成しておけば、本番にデプロイした時に権限付与を忘れていた、といったようなことが無くなります。また、Lambdaを削除した時に、合わせてロールも削除してくれるので、用途不明のゴミロールが残るといったことも無くなるのでとても便利です。
感想
最初ツールを探し始めた時は、覚えるのが大変だなぁと気が重かったのですが、シンプルなツールが見つかってよかったです。
GraphQLもServerlessで書けるみたいなので、GraphQLが流行ってくるようならいつか試してみたいですね。
LambdaのオーソラーザーまわりのServerlessの設定で、いくつかハマったので別記事に書きました。