Serverless Frameworkに入門した

はじめに

Serverless Frameworkに触る機会ができたので入門した。

Serverless FrameworkとはAWS Lambdaなどを使ったサーバレスアプリケーションの開発・運用を支援するフレームワークである。デプロイなどのコアな機能を提供するCLIOSSとして公開されていて、アプリケーションをGUIで管理したりCI/CDを利用したい場合は料金プランが設定されている。

余談だが、このツールを作っている会社はServerlessという名前でFramework, Cloud, Consoleという3つのプロダクトがある。Serverless FrameworkのServerlessは会社名ということに最初気づかなかった。AWS Lambdaのようなものだ。

ローカルでHello World!

serverless frameworkはローカルでLambdaをエミュレートする仕組みがあるので、これを利用してローカルで確認する。

www.serverless.com

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!を実行できた。

AWSHello World!

事前準備

以下を準備しておく。

  • AWSアカウントの作成とAWS CLIの設定
  • Serverless Frameworkのアカウントの作成 (AWSで実行するだけならば必要なし)

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に渡される入力と出力が書いてある。

queryStringParametersNameパラメータがあればその値を表示するようにした。

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も改めて触って比較したい。

www.techmagic.co

*1:ダッシュボードはどちらの製品でも共通なのでドキュメントだけ別れていて少しわかりづらさを感じた。