API Gateway の HTTP API と Lambda を開発用・本番用のバージョン違いで接続する

めずらしく AWS ネタ。
けっこうどうやるんだ?ってなったので自分用のメモ。
要は API Gateway のステージとステージ変数を使って Lambda ファンクションのエイリアスを呼び分ける話。
「動的統合」というやつらしく IAM ロールは自分で用意・指定する必要があったところが(自分には)肝でした。

Lambda 側の準備

本番用と開発用とは Lambda の「バージョン」と「エイリアス」で表現する。なにも設定を変更してない状態だとバージョンは $LATEST だけ存在している。これを本番用の prod と開発用の dev に分ける。
現在の $LATEST バージョンをひとまず仮に本番用とするためバージョンを発行(作成)する。
f:id:nishikawasasaki:20200326195247p:plain
まだ一度もバージョンを作成していないと、バージョン 1 が作られる。

次にエイリアスを作成する。
本番用は固定されたバージョンの 1 を利用して、開発用は常に最新の $LATEST を使うとした場合。
f:id:nishikawasasaki:20200326195509p:plain
開発用なので dev としたエイリアスを、バージョンは $LATEST を見るように作成する。
f:id:nishikawasasaki:20200326195610p:plain 同様に本番用として prod エイリアスをバージョン 1 を見るように作成する。

これで Lambda 側の準備は完了。

API Gateway 側の準備

用意した Lambda のエイリアスに対応する形で API Gatewaydev ステージを用意する。

f:id:nishikawasasaki:20200326195915p:plain

ステージの名前は自由に。
ステージ変数の名前として「キー」に好きなものをつける。ここでは LambdaAlias
ステージ変数の値には Lambda で作った開発用のエイリアスを同じ dev をつける。
(この「値」が API Gateway の呼び出す Lambda ファンクションのエイリアスとして使われることとなる。)

同じことをデフォルトのステージ $default でもおこない、「値」は prod にしておく。
(本番用にちゃんと区別したい場合はデフォルトのステージを使わず prod ステージを用意すると良いはず。)

あとは統合する Lambda ファンクションを arn で指定するときに、エイリアス:エイリアス名 までつけて指定すれば OK。
arn + :エイリアス名 とするとそのエイリアスで Lambda ファンクションを指定できるそう。
arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxxxx:function:hogehoge:${stageVariables.LambdaAlias} こんな雰囲気。
f:id:nishikawasasaki:20200326200440p:plain
「一致する Lambda 関数がありません」と出てくるけどちゃんと保存できます。

これで動くかなと思ったらそうではなくて、いまやっている「動的統合」の場合は「アクセス許可を呼び出す」のところを自動ではなく明示的に指定しないといけないそう。
自分はここから IAM 力の低さにつまづいてしまった……。
以下のページにもあるのだけれど、

動的統合を構築する場合、それに応じて権限を更新することも重要です。統合が単一のLambda関数を指す場合、HTTP APIは呼び出し権限を自動的に追加します。ただし、複数の関数を使用する場合は、ロールを手動で作成および管理する必要があります。これを行うには、Lambda関数オプションを呼び出すための[Grant API Gateway permission to invoke your Lambda function]をオフにし、適切な権限を持つカスタムロールを入力します。

高速、低コストで、より良いAPIの構築 – HTTP APIが利用可能(GA)になりました | Amazon Web Services ブログ

とのこと。
具体的にどんなロールを用意したらいいの?ってなったけど チュートリアル: 2 つの AWS のサービス統合と 1 つの Lambda 非プロキシ統合を使用して Calc REST API を作成する - Amazon API Gateway の内容に沿ってロール作成したものを使えばうまくいきました。

最終的にこういう状態に。

f:id:nishikawasasaki:20200326200903p:plain

試す

ここまできたら API Gateway に本番用と開発用の 2 つのステージで URL が得られているはず。

上が本番用で下が開発用。
あとは API Gateway のルートに作成したパスをつなげれば本番用・開発用の使い分けができる。

もし API 実行して Internal Server error が帰ってきており、Lambda の実行ログが Cloud Watch にも無いようなら、API Gateway から Lambda を呼び出せていないので IAM まわりを確認する。 そうでなく Lambda の中でこけているなら通常どおり Cloud Watch でログを見て修正する。