変更に至った経緯
Lambda 用の Go 1.x マネージドランタイムは Amazon Linux AMI (AL1) に基づいています。Amazon Linux AMI のメンテナンスサポートが 2023 年 12 月 31 日に終了するまで、Lambda は引き続き Go 1.x マネージドランタイムをサポートします。Go 1.x ランタイムを使用している場合は、関数を provided.al2 に移行する必要があります。この移行ではコードの変更は必要ありません。必要な変更は、デプロイパッケージの構築方法と、関数の作成に使用するランタイムに関するもののみです。
Lambdaのgo1.xランタイムのサポートが2023/12/31で終了になるとの話を受け、急遽go1.xランタイムからprovided.al2に変更する必要が出たため、変更に至りました。
環境について
まず、当方の環境はDEV、STG、検証、本番環境と4つあり、DEV環境以外はすべてCIでビルドして
CloudFormationを用いてLambdaの更新を行なっている。goのbuildコマンドで実行ファイルを作り、
その実行ファイルをzip圧縮してCloudFormationでLambdaのイメージを更新している状態となります。
DEV環境については、zip圧縮したファイルをaws cliを使い、Lambdaの更新を行なっています。
やったこと
AWSのドキュメントを見ると、go1.xランタイムからprovided.al2(カスタムランタイム)に変更する作業は、
Lambdaのランタイムを変更するだけの簡単なお仕事と思っており、実際に当方の環境の話になるが、
CloudFormationのテンプレートに以下を追加した
Resources:
HogeLambda:
Type: AWS::Serverless::Function
Properties:
Handler: hoge
FunctionName: Hoge
- Runtime: go1.x
+ Runtime: provided.al2
+ Architectures:
+ - x86_64 # デフォルトでx86_64になるが、視認性を考え明示的に書いてる
Description: Hoge Lambda
CodeUri: ./hoge.zip
Timeout: 3
goビルド、zip圧縮
$ GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o hoge /hoge_lambda/main.go
$ zip hoge.zip hoge
-tags lambda.norpc
のオプションをつけることで、これまでgo1.xのランタイム間で発生していたRPCのライブラリがリンクから外れるため、その分バイナリデータが軽くなるとのこと。
オプションの lambda.norpc タグを使用して、Lambda ライブラリの Remote Procedure Call (RPC) コンポーネントを除外することができます。RPC コンポーネントは Go 1.x ランタイムを使用する場合にのみ必要です。RPC を除外すると、デプロイパッケージのサイズが小さくなります。
トラブル発生
トラブルその1「Runtime.InvalidEntrypoint」
- CloudWatchLogs
INIT_REPORT Init Duration: 0.25 ms Phase: init Status: error Error Type: Runtime.InvalidEntrypoint
エンドポイントに向けて、GETリクエストを投げるとBad Gateway(502)
が返ってきた。
トラブルその1原因
lambda handler 名がbootstrapとなっておらず、InvalidEntrypointエラーが発生しているっぽい。
実行ファイルには bootstrap という名前をつける必要があります。詳細については、「命名」を参照してください。
たしかに、bootstrapである必要がありそうだ。
トラブルその1解決方法
Resources:
HogeLambda:
Type: AWS::Serverless::Function
Properties:
- Handler: hoge
+ Handler: bootstrap
FunctionName: Hoge
Runtime: provided.al2
Architectures:
- x86_64 # デフォルトでx86_64になるが、視認性を考え明示的に書いてる
Description: Hoge Lambda
- CodeUri: ./hoge.zip
+ CodeUri: ./bootstrap.zip
Timeout: 3
goビルド、zip圧縮
$ GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o bootstrap /hoge_lambda/main.go
$ zip bootstrap.zip bootstrap
トラブルその2「Runtime.Unknown」
- CloudWatchLogs
INIT_REPORT Init Duration: 3003.24 ms Phase: invoke Status: error Error Type: Runtime.Unknown
トラブルその1とはまた異なるエラーerror Error Type: Runtime.Unknown
が発生した。
トラブルその2原因
どうやら、aws-lambda-goのバージョンに問題がありそうだった。
このエラーが発生した時、go.modのバージョンを確認すると、
require (
github.com/aws/aws-lambda-go v1.10.0
github.com/aws/aws-sdk-go v1.19.29
github.com/golang/mock v1.3.1
github.com/guregu/dynamo v1.2.1
github.com/pkg/errors v0.8.1 // indirect
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.10.0
)
v1.10.0
であったため、v1.18.0
以降でない事が原因っぽい。
go 1.xランタイムを使わない事で、Runtime APIとaws-lambda-goが直接通信するため、
aws-lambda-goがv1.18.0
以降でないと対応していなかった。
引用元:https://aws.amazon.com/jp/blogs/compute/migrating-aws-lambda-functions-from-the-go1-x-runtime-to-the-custom-runtime-on-amazon-linux-2/
トラブルその2解決方法
go get github.com/aws/aws-lambda-go@v1.22.0
- go.mod
require (
- github.com/aws/aws-lambda-go v1.10.0
+ github.com/aws/aws-lambda-go v1.22.0
github.com/aws/aws-sdk-go v1.19.29
github.com/golang/mock v1.3.1
github.com/guregu/dynamo v1.2.1
github.com/pkg/errors v0.8.1 // indirect
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.10.0
)
※ v1.22.0にしているのは、他のlambdaで動かしているバージョンがv1.22.0
であったため。
バージョンは環境に合わせましょう。
再実行後
- CloudWatchLogs
INIT_START Runtime Version: provided:al2.v27 Runtime Version ARN: arn:aws:lambda:ap-northeast-1::runtime:*****
START RequestId: ***** Version: $LATEST
END RequestId: *****
エラーでなくなった。
解決。