Lambda go1.xランタイムからprovided.al2に変更時の備忘

## 変更に至った経緯
>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、検証、本番環境と４つあり、DEV環境以外はすべてCIでビルドして
CloudFormationを用いてLambdaの更新を行なっている。goのbuildコマンドで実行ファイルを作り、
その実行ファイルをzip圧縮してCloudFormationでLambdaのイメージを更新している状態となります。
DEV環境については、zip圧縮したファイルをaws cliを使い、Lambdaの更新を行なっています。

## やったこと
AWSのドキュメントを見ると、go1.xランタイムからprovided.al2（カスタムランタイム）に変更する作業は、
Lambdaのランタイムを変更するだけの簡単なお仕事と思っており、実際に当方の環境の話になるが、
CloudFormationのテンプレートに以下を追加した
```diff_yaml
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圧縮
```shell
$ 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 を除外すると、デプロイパッケージのサイズが小さくなります。

引用元　https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-package.html#:~:text=%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%C2%A0,%E3%81%95%E3%81%8F%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82

## トラブル発生
### トラブルその1「Runtime.InvalidEntrypoint」
- CloudWatchLogs
```json
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解決方法
```diff_yaml
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圧縮
```shell
$ GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o bootstrap /hoge_lambda/main.go
$ zip bootstrap.zip bootstrap
```
### トラブルその2「Runtime.Unknown」
- CloudWatchLogs
```json
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](https://github.com/aws/aws-lambda-go)のバージョンに問題がありそうだった。
このエラーが発生した時、go.modのバージョンを確認すると、
```go
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`以降でないと対応していなかった。
![go2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987493/af70b3f6-6ca7-09f8-6235-1de9154975e2.png)
引用元：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解決方法
```shell
go get github.com/aws/aws-lambda-go@v1.22.0
```

- go.mod
```diff_go
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
```json
INIT_START Runtime Version: provided:al2.v27	Runtime Version ARN: arn:aws:lambda:ap-northeast-1::runtime:*****
START RequestId: ***** Version: $LATEST
END RequestId: *****
```
エラーでなくなった。
解決。