はじめに
AWSサービスから以下のようなメッセージが来たので、Lambda のランタイムをGO 1.x
から provided.al2
に変更しました。
Web検索で調べたところ、SAMの記事に対してServerlessFramerwork(SLS)
の記事が少ないように感じたので、
その時の苦戦したところやわかりにくかったポイントをまとめておこうと思います。
お客様の AWS アカウントに現在 Go 1.x ランタイムを使用する 1 つ以上の Lambda 関数があることを確認しましたので、ご連絡いたします。
Amazon Linux AMI のメンテナンスサポートが 2023 年 12 月 31 日に終了するのに合わせて、AWS Lambda での Go 1.x ランタイムのサポートを終了します [1]。Lambda は、provided.al2 ランタイムを使用して Go プログラミング言語を引き続きサポートします。provided.al2 ランタイムを使用すると、AWS Graviton2 プロセッサのサポートや、より小さなデプロイパッケージとより高速な関数呼び出しパスによる効率的な実装など、go1.x ランタイムに比べていくつかの利点があります。詳細については、ブログ記事 [2] を参照してください。
Lambda ランタイムサポートポリシー [3] で説明されているように、Lambda での言語ランタイムのサポートの終了は 2 段階で行われます。2023 年 12 月 31 日以降、Lambda は Lambda 関数で使用される Go 1.x ランタイムにセキュリティパッチやその他アップグレードを適用しなくなり、Go 1.x を使用する関数は、テクニカルサポートの対象外となります。さらに、Go 1.x ランタイムを使用する新しい Lambda 関数を作成できなくなります。2024 年 1 月 30 日以降、Go 1.x ランタイムを使用して既存の関数を更新することができなくなります。
2023 年 12 月 31 日までに、既存の Go 1.x 関数を provided.al2 ランタイムにアップグレードすることをお勧めします。
サポートの終了は機能の実行には影響しません。関数は引き続き実行されます。しかしながら、AWS Lambda チームによるメンテナンスやパッチ適用がされない、サポートされていないランタイムで実行されることとなります。
アップグレードしなくても動くが、更新はできなくなるよ〜とのこと
現状のデプロイ
現在リリースしているLambda関数(ランタイム Go1.x)は以下のコードを使用してデプロイを行なっている。
ビルドコマンド
GOOS=linux GOARCH=amd64 go build -o bin/healthcheck/main cmd/healthcheck/main.go
serverless.yml
service: engimeerLambda
provider:
name: aws
runtime: go1.x
region: ap-northeast-1
functions:
Healthcheck:
name: ${self:service}-Healthcheck
handler: bin/healthcheck/main
description: Healthcheck
package:
individually: true
patterns:
- ./bin/healthcheck/main
events:
- http:
path: /healthcheck
method: get
変更後のデプロイ
上記のビルドコマンドとserverless.ymlを以下のコードに書き換え、provided.al2のランタイムを使用してLambda関数のデプロイを実行しました。
※AmazonLinux2の提供cpuはamd64とarm64のどちらもありますが、serverless.yml
のアーキテクチャを指定しない場合は、x86_64となるので、build時のコマンドをGOARCH=amd64
とした場合は記載不要です。
また、ランタイムの変更に合わせてビルドコマンドに-tags lambda.norpc
のオプションを付与しました。
• オプションの
lambda.norpc
タグを使用して、Lambda ライブラリの Remote Procedure Call (RPC) コンポーネントを除外することができます。RPC コンポーネントは Go 1.x ランタイムを使用する場合にのみ必要です。RPC を除外すると、デプロイパッケージのサイズが小さくなります。(引用:https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-package.html)
ビルドコマンド
- コンパイル後のバイナリファイル名を
bootstrap
に変更 - バイナリファイルをフォルダ構造を持たないzipにアーカイブ化
GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o bin/healthcheck/bootstrap cmd/healthcheck/main.go
zip -j bin/healthcheck.zip bin/healthcheck/bootstrap
serverless.yml
-
provider:runtime
をgo1.x
からprovided.al2
に変更 -
functions:Healthcheck:handler
をbin/healthcheck/main
からbootstrap
に変更 -
functions:Healthcheck:package:patterns
をfunctions:Healthcheck:package:artfact
に変更 - artifactには先ほど作成したアーカイブファイルを指定(
bin/
はローカルのデプロイ時の保存ディレクトリなので任意でOK)
service: engimeerLambda
provider:
name: aws
runtime: provided.al2
region: ap-northeast-1
functions:
Healthcheck:
name: ${self:service}-Healthcheck
handler: bootstrap
description: Healthcheck
package:
individually: true
artifact: bin/healthcheck.zip
events:
- http:
path: /healthcheck
method: get
上記にファイルを変更してsls deployを実行することでランタイムの変更ができ、問題なく動作するようになりました。
時間を要したポイント
以下の点がうまくいかないポイントでした。
-
provided.al2
ではバイナリファイルをzipにアーカイブ化する必要があるが、階層構造に注意する必要があった点-
zip bin/healthcheck.zip bin/bootstrap
ではうまくいかず、-j
オプション(ディレクトリ名無しで格納)が必要です。 - オプションなしでデプロイすると
entrypoint
が見つけられないため、以下のエラーが出力されます。
{ “errorType”: “Runtime.InvalidEntrypoint”, “errorMessage”: “RequestId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Error: Couldn’t find valid bootstrap(s): [/var/task/bootstrap /opt/bootstrap]” }
-
- yamlファイルで
package: artifact:
を指定する必要がある- デプロイファイルとして
.zip
ファイルを指定する- 指定しないとこちらも
entrypoint
が見つけられないため「bootstrap
いないよ」と以下のエラーが出ます。
- 指定しないとこちらも
{ “errorType”: “Runtime.InvalidEntrypoint”, “errorMessage”: “RequestId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Error: Couldn’t find valid bootstrap(s): [/var/task/bootstrap /opt/bootstrap]” }
- デプロイファイルとして
- バイナリファイル以外のファイルを一緒にLambda環境にdeployしたい場合、go1.xの時はserverless.ymlの
package:patterns
に指定すればよかったが、package:artifact
と同時に使用するとうまくデプロイできませんでした。- zip化する際にzipに一緒にdeployしたいファイルを格納することで改善できました。