JavaScriptを有効にしてください

AWS Lambda Go1.xからカスタムランタイム(provided.al2023, provided.al2)へ更新時の注意点

 ·  ☕ 5 分で読めます

もうすぐGo1.xランタイムがサポート終了するため、provided.al2に変更しました。
更新はできたものの釈然としない部分があったのでもう少し調べてみました。

注意点まとめ

  • ファイルはbootstrapという名前で「直下に」置く必要がある
  • Handlerの値は使用されないので何でもいい

Handlerもbootstrapじゃなきゃいけないとか、従来通り設定できると勘違いしがちだと思います。

Template更新例

Templateをどう直せば良いのか先に記載します。
なお、以降の記述も含めて.zipデプロイ前提で記載します。
また、provided.al2023 がリリースされたので基本的にそちらで記載しますが、provided.al2でも同じです。

Serverless Framework

aws-goテンプレートを元に記載します。

Makefile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
build:
	# env GOARCH=amd64 GOOS=linux go build -ldflags="-s -w" -o bin/hello hello/main.go
	# env GOARCH=amd64 GOOS=linux go build -ldflags="-s -w" -o bin/world world/main.go
	env GOARCH=amd64 GOOS=linux go build -ldflags="-s -w" -tags lambda.norpc -o bin/hello/bootstrap hello/main.go
	env GOARCH=amd64 GOOS=linux go build -ldflags="-s -w" -tags lambda.norpc -o bin/world/bootstrap world/main.go

# 追加
zip:
	zip -j bin/hello.zip bin/hello/bootstrap
	zip -j bin/world.zip bin/world/bootstrap

clean:
	rm -rf ./bin

deploy: clean build zip # zipを追加
	sls deploy --verbose

serverless.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
provider:
  name: aws
  runtime: provided.al2023 # go1.xから変更

package:
  # patterns:
  #   - '!./**'
  #   - ./bin/**
  individually: true

functions:
  hello:
    # handler: bin/test/hello
    handler: '-'
    package:
      artifact: bin/hello.zip # 追加
    events:
      - httpApi:
          path: /hello
          method: get
  world:
    # handler: bin/test/world
    handler: '-'
    package:
      artifact: bin/world.zip # 追加
    events:
      - httpApi:
          path: /world
          method: get

AWS SAM

Hello World Exampleを元に記載します。

template.yaml

1
2
3
4
5
6
7
8
9
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Metadata: # 追加
      BuildMethod: go1.x 
    Properties:
      CodeUri: hello-world/
      Handler: '-'  # 変更
      Runtime: provided.al2  # 変更

※本記事作成時点では、Runtime: provided.al2023とすると以下のエラーになりました。
RequestId: xxx Error: Couldn't find valid bootstrap(s): [/var/task/bootstrap /opt/bootstrap] Runtime.InvalidEntrypoint

これ以降は検証した結果を記載します。

Go1.xランタイムの終了について

そもそも発端となった件について軽くまとめておきます。

Go1.xランタイムは2023年12月31日にサポートが終了します。
https://aws.amazon.com/jp/blogs/compute/migrating-aws-lambda-functions-from-the-go1-x-runtime-to-the-custom-runtime-on-amazon-linux-2/?nc1=h_ls

厳密に言うと上記は「非推奨化フェーズ1」の日程です。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtimes.html

フェーズ1の制約

  • 新規で作成はできないが、更新は引き続き可能
  • セキュリティアップデートが受けられない
    フェーズ2は上記に加えて更新も不可。

サポート終了しても関数が実行できなくなるわけではありません(勘違いしている人はあまりいないとは思いますが)。

Go1.x ランタイムが終了するにあたり、後継は出さないようでカスタムランタイムに移行する必要があります。

ファイル名とHandlerについて

Go1.xは実行ファイルとハンドラーが対応していて、両方任意でした。
カスタムランタイムでは実行ファイルはbootstrap固定で、Handlerは任意となっています。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-handler.html#golang-handler-naming

ファイル名とHandlerの罠

設定を変えながら検証してみます。
フレームワークに左右されないようにあえてCLIで作成する事にします。

まずGo1.xのデプロイをCLIで書くと以下になります。

1
2
3
4
5
6
7
env GOARCH=amd64 GOOS=linux go build -ldflags="-s -w" -o bin/test/hello hello/main.go
zip bin/hello.zip bin/hello
aws lambda create-function --function-name go-go1x-test-hello \
  --runtime go1.x \
  --handler bin/hello \
  --role <role> \
  --zip-file fileb://bin/hello.zip

前述の案内Blogに沿ってカスタムランタイムに変更すると以下になります。

1
2
3
4
5
6
7
env GOARCH=amd64 GOOS=linux go build -ldflags="-s -w" -tags lambda.norpc -o bootstrap hello/main.go
zip hello.zip bootstrap
aws lambda create-function --function-name go-cr-test-hello \
  --runtime provided.al2023 \
  --handler bootstrap \
  --role <role arn> \
  --zip-file fileb://bin/hello.zip

これで成功はするのですが、
ファイル名がbootstrap、Handlerが任意ということなので、以前となるべく変えずに修正しようとすると以下のようにしたくなります。

1
2
3
4
5
6
7
env GOARCH=amd64 GOOS=linux go build -ldflags="-s -w" -tags lambda.norpc -o bin/hello/bootstrap hello/main.go
zip bin/hello.zip bin/hello/bootstrap
aws lambda create-function --function-name go-cr-test-hello2 \
  --runtime provided.al2023 \
  --handler bin/hello/bootstrap \
  --role <role arn>  \
  --zip-file fileb://bin/hello.zip

これは実行すると以下のエラーになってしまいます。

1
2
3
4
{
  "errorType": "Runtime.InvalidEntrypoint",
  "errorMessage": "RequestId: xxx Error: Couldn't find valid bootstrap(s): [/var/task/bootstrap /opt/bootstrap]"
}

ファイル名がbootstrapと書かれているので、ファイル名さえbootstrapであればいいと普通は考えると思うのですが、直下に配置しないといけません。

そしてHandler名は任意となっていますが、任意だとしてどこに合わせればいいんでしょうか?
これはHandler名は何にしても意味がないので、以下のようにしても問題ありません。

1
2
3
4
5
aws lambda create-function --function-name go-cr-test-hello3 \
  --runtime provided.al2023 \ 
  --handler hoge/huga \
  --role <role arn> \
  --zip-file fileb://bin/hello.zip

ちなみに、書く意味がないならとハンドラーの指定を削ってみるとエラーになります。
An error occurred (InvalidParameterValueException) when calling the CreateFunction operation: Runtime and Handler are mandatory parameters for functions created with deployment packages.

まとめると、先にも書いた通り以下です。

  • ファイルはbootstrapという名前で「直下に」置く必要がある
  • Handlerの値は使用されないので何でもいい

うーん、分かりづらい。。
現にServerless Frameworkの、Issueでもbootstrapについて私と同様の同様の勘違いをしている人がいましたし
後述のドキュメントのせいかもしれませんが、Handlerもbootstrapにしなければならないと書かれた記事をちらほら見かけます。
検証したりサポートに問合せしたりしてようやく理解できました。

なお、以下のドキュメントには「ハンドラー名は何でもかまいません。」と書かれています。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-package.html#golang-package-mac-linux

※私の記憶ではこちらのドキュメントには以前はハンドラーもbootstrapにしなければならないと書かれてたと思うのですが、矛盾してるやんとフィードバックしたので、更新されたのかもしれません。

参考にした記事

移行にあたり以下の記事がとても参考になりました。
https://blog.matthiasbruns.com/running-multiple-golang-aws-lambda-functions-on-arm64-with-serverlesscom
まぁこの方も"the handler name must be bootstrap"って書いてます。仕方ないね

共有