📈

AWS Step Functions x Go Runtime x Serverless Framework

タイトルの構成で Step Functions を動かすのに思ったより苦労したので知見をまとめます。

結論

次のサンプルリポジトリの構成にならいつつ、Step Functions 用に serverless.yml を編集しておく。

https://github.com/matthiasbruns/golang-sls-provided.al2-arm64

はまりポイント

AWS Lambda の Go Runtime は Amazon Linux 2 を使う

https://aws.amazon.com/jp/blogs/compute/migrating-aws-lambda-functions-from-the-go1-x-runtime-to-the-custom-runtime-on-amazon-linux-2/

we plan to deprecate the go1.x runtime in line with the end-of-life of Amazon Linux 1, currently scheduled for December 31, 2023.

なるほど、ということで go1.x Runtime は 廃止予定で、かわりに Amazon Linux 2 を使ってね、ということでした。

バイナリファイル名が bootstrap に固定されている

Amazon Linux 2 の利用については、serverless.yml で次のように指定するだけなのですが、

provider:
  name: aws
  # runtime: go1.x
  runtime: provided.al2
  architecture: arm64

provided.al2 と Go のコード実行の掛け合わせに罠があってはまりました。

Compiling for the provided.al2 runtime

の項にあるコマンドで次のように記載されているのですが、

GOARCH=amd64 GOOS=linux go build -o bootstrap main.go

AWS Lambda に最終的にデプロイされるバイナリファイル名が bootstrap である必要があります。どうやれこれは変えられません。

handler を bootstrap に固定しつつ artifact で zip ファイルを指定する

続きですが、バイナリファイルを bootstrap に指定するのは良いのですが、それを Serverless Framework 経由でデプロイするのにクセがありました。

次のように、handlerbootstrap に指定したうえで、デプロイ対象のバイナリを zip しておいて artifact で明示する必要があります。

functions:
  hello:
    handler: bootstrap
    package:
      artifact: build/hello.zip

この設定を成立させるために、次のコマンドでバイナリをビルドして zip を生成します。

env GOOS=linux GOARCH=arm64 go build -tags lambda.norpc -o build/hello/bootstrap hello/main.go
zip -j build/hello.zip build/hello/bootstrap

設定ファイル全体

設定ファイルの全体は次のようになります。

service: xxxService

frameworkVersion: "3"

provider:
  name: aws
  runtime: provided.al2
  architecture: arm64

plugins:
  - serverless-step-functions

package:
  individually: true

functions:
  hello:
    handler: bootstrap
    package:
      artifact: build/hello.zip

stepFunctions:
  stateMachines:
    StateMachine1:
      name: TestStateMachine1
      definition:
        StartAt: Hello
        States:
          Hello:
            Type: Task
            Resource:
              Fn::GetAtt: [hello, Arn]
            Parameters:
              Payload.$: "$"
            End: true

デプロイコマンドは次のとおりです。

npm i -g serverless

# -g ではなくプロジェクトのルートで実行する必要がある
npm install -D serverless-step-functions

# デプロイ
sls deploy

補足

Awarefy では AWS Lambda x Go の環境はすでに存在しているのですが、Docker Container を実行する環境となっていました(なんだコンテナでラップしてたんだっけ...?)。Amazon Linux 2 Runtime を利用するというのが始めてでしたので、検証していました。

参考文献

https://www.serverless.com/plugins/serverless-step-functions

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-package.html

https://qiita.com/sgash708/items/1f6cfca3e889af354236

Awarefy 技術ブログ

Discussion