はじめに
Serverless Frameworkに触る機会ができたので入門した。
Serverless FrameworkとはAWS Lambdaなどを使ったサーバレスアプリケーションの開発・運用を支援するフレームワークである。デプロイなどのコアな機能を提供するCLIはOSSとして公開されていて、アプリケーションをGUIで管理したりCI/CDを利用したい場合は料金プランが設定されている。
余談だが、このツールを作っている会社はServerlessという名前でFramework, Cloud, Consoleという3つのプロダクトがある。Serverless FrameworkのServerlessは会社名ということに最初気づかなかった。AWS Lambdaのようなものだ。
ローカルでHello World!
serverless frameworkはローカルでLambdaをエミュレートする仕組みがあるので、これを利用してローカルで確認する。
CLIのインストール
以下のコマンドでCLIをインストールする。
$ npm install -g serverless
インストールしたらserverlessコマンドでプロジェクトを作る。プロジェクトのテンプレートにはAWS - Python - HTTP API
を選んだ。プロジェクト名にhello-world
を入力後は全部No
にする。
$ serverless Creating a new serverless project ? What do you want to make? AWS - Python - HTTP API ? What do you want to call this project? hello-world ✔ Project successfully created in hello-world folder ? Do you want to login/register to Serverless Dashboard? No ? Do you want to deploy now? No
ローカルでの実行
作成したプロジェクトには以下のようなファイルができている。
$ cd hello-world $ ls README.md handler.py serverless.yml
handler.py
import json def hello(event, context): body = { "message": "Go Serverless v3.0! Your function executed successfully!", "input": event, } response = {"statusCode": 200, "body": json.dumps(body)} return response
serverless.yml
service: hello-world frameworkVersion: '3' provider: name: aws runtime: python3.8 functions: hello: handler: handler.hello events: - httpApi: path: / method: get
ローカルで実行するには以下のようにする。ここではserverless.ymlのfunctionsのhello関数を指定している。
$ serverless invoke local -f hello { "statusCode": 200, "body": "{\"message\": \"Go Serverless v3.0! Your function executed successfully!\", \"input\": {}}" }
messageを"Hello World!"に変えて実行してみる。
$ serverless invoke local -f hello { "statusCode": 200, "body": "{\"message\": \"Hello World!\", \"input\": {}}" }
ローカルでHello World!を実行できた。
AWSでHello World!
事前準備
以下を準備しておく。
AWSへのデプロイ
先ほどのhello-worldプロジェクトを使う。まずはServerless Frameworkのアカウントにログインする。
$ serverless login ? Which would you like to log into? Serverless Framework Dashboard ✔ You are now logged into the Serverless Dashboard
次にserverlessコマンドを実行し、いくつかの質問に答えるとデプロイが始まる。
$ serverless Onboarding "hello-world" to the Serverless Dashboard ? What org do you want to add this service to? <org name> ✔ Your project is ready to be deployed to Serverless Dashboard (org: "<org name>", app: "hello-world") ? Do you want to deploy now? Yes Deploying hello-world to stage dev (us-east-1) ✔ Service deployed to stack hello-world-dev (128s) dashboard: https://app.serverless.com/<org name>/apps/hello-world/hello-world/dev/us-east-1 endpoint: GET - https://xxxxxx.execute-api.us-east-1.amazonaws.com/ functions: hello: hello-world-dev-hello (86 kB)
このときCLIはserverless.ymlを読み取りCloudFormationを作成することで、関数をデプロイする。デプロイされるとエンドポイントが表示されるので叩いてみる。
$ curl -s https://xxxxxx.execute-api.us-east-1.amazonaws.com/ | jq { "message": "Hello World!", "input": { "version": "2.0", "routeKey": "GET /", "rawPath": "/", "rawQueryString": "", (略)
ここでダッシュボードにログインするとは次のようにデプロイしたアプリケーションをWeb上で確認ができる。
ダッシュボードの階層構造はorganization->application->service->stageというようになっている。上図で言うと、hello-worldアプリケーション->hello-worldサービス->devステージである。organizationとapplicationはダッシュボードでのみ存在する概念で、AWSのリソースに対して何か対応するものはないようだ。関連ドキュメントはServerless Frameworkではなく、Serverless Cloudの方にあるので注意。*1
CLIによって作成されるCloudFormationは次のようにAWS LambdaやAPI Gatewayなどを作成している。
プロジェクト作成時のテンプレート
プロジェクト作成時にテンプレートを選ぶことで、必要なファイルや設定がされた状態でプロジェクトが作成される。作成時の選択肢の他に
Examplesにもたくさんあるので、ここから選んで、serverless --template-url=https://github.com/serverless/examples/tree/v3/...
というような感じで指定してプロジェクト作成が可能である。
クエリパラメータを渡す
API GatewayとLambdaを統合した時にLambdaに渡される入力と出力が書いてある。
- Input format of a Lambda function for proxy integration
- Output format of a Lambda function for proxy integration
queryStringParameters
にName
パラメータがあればその値を表示するようにした。
handler.py
import json def hello(event, context): name = event.get("queryStringParameters", {}).get("Name", "World!") body = { "message": f'Hello {name}', "input": event, } response = {"statusCode": 200, "body": json.dumps(body)} return response
ローカルで実行する。
$ serverless invoke local -f hello --data '{}' { "statusCode": 200, "body": "{\"message\": \"Hello World!\", \"input\": {}}" } $ serverless invoke local -f hello --data '{"queryStringParameters":{"Name":"foo"}}' { "statusCode": 200, "body": "{\"message\": \"Hello foo\", \"input\": {\"queryStringParameters\": {\"Name\": \"foo\"}}}" }
serverless deploy
でデプロイしてcurlで確認してみる。
$ serverless deploy Deploying hello-world to stage dev (us-east-1) ✔ Service deployed to stack hello-world-dev (54s) dashboard: https://app.serverless.com/<account-name>/apps/hello-world/hello-world/dev/us-east-1 endpoint: GET - https://xxxxx.execute-api.us-east-1.amazonaws.com/ functions: hello: hello-world-dev-hello (86 kB) $ curl -s "https://xxxxx.execute-api.us-east-1.amazonaws.com?Name=foo" | jq .message "Hello foo"
デプロイ
更新した関数だけデプロイする時は以下でデプロイができるようだ。
$ serverless deploy function -f hello Deploying function hello to stage dev (us-east-1) ✔ Function code deployed (2s) Configuration did not change. Configuration update skipped. (2s)
おわりに
やはりこういうツールは便利だなと思った。スタートアップなどで、少ない人数でクラウドインフラも構築しないといけないと言う時に役に立ちそうだ。OSSなので何かバグなどあればIssueにするなりFixするなりで貢献したい。
AWS SAMを使ったことがあるが、うろ覚えの記憶で言うとSAMはCloudFormationまんまだった気がするので、Serverless Frameworkの方が好きな気がする。AWS SAMを使うならTerraform管理で良い気がしてくるのだが、どうだろうか。そのうちSAMも改めて触って比較したい。