結論
- Provisioned Concurrency は関数のバージョンではなくエイリアスに対して設定しよう
- ドキュメントにもあるように関数のエイリアスをロードバランサーのターゲットグループに登録しよう
ロードバランサーが常に現行バージョンの Lambda 関数を呼び出せるようにするには、関数のエイリアスを作成し、ロードバランサーに Lambda 関数を登録するときに関数 ARN にエイリアスを含めます。
はじめに
こんにちは、ディベロップメントサービス課の保田(ほだ)です。
6月から短パンで過ごすことに慣れてしまい、(私服と言えど)長ズボンを穿いてオフィス出社していたころがもはや想像できなくなっています。
導入
要件によっては Lambda 関数を ALB のターゲットに登録して、 ALB 経由で実行したいときもあるかと思います。
また、要件によってはその Lambda 関数に Provisioned Concurrency を設定して指定数の実行環境をプロビジョニングしておきたいこともあるかと思います。
このような状況下で、設定を間違うと ALB 経由で呼び出している Lambda からのレスポンスが思ったように速くならず「どうやらコールドスタートが起きているみたいだぞ」、ですとか「Lambda をデプロイしたとき ALB の向き先を最新のものに切り替える手順が面倒だぞ」といった事態を招く可能性があります。
個々のドキュメントの記載をつなぎ合わせれば自然と望ましい設定にできていることもあるかと思いますが、改めてなぜそうすべきなのかを解説していきます。
Provisioned Concurrency
Provisioned Concurrency を利用すれば、 Lambda 関数の実行環境をウォームスタートできる状態で指定数確保しておくことができます。
さて、この Provisioned Concurrency ですが設定するには Lambda 関数のバージョンとエイリアスについて理解していないといけないので、ここから先しばらく説明します。
知ってるよ!という方は 7. 再び Provisioned Concurrency のセクションまで飛んでください。
Lambda 関数のバージョンとエイリアス
Lambda 関数にはバージョンとエイリアスが設定できます。順に見ていきましょう。
バージョン
バージョンはある時点の Lambda 関数のスナップショットであり、画面キャプチャからもわかるようにその時点での最新版( $LATEST
)を新しいバージョンとして作成することになります。
タイムアウトやメモリーなど、ソースコード以外の設定値も保存されます。
特定のバージョンの関数を表す Lambda は 修飾 ARN
により一意に特定されます。
関数名の後ろに :2
がついていますが、それです。バージョンを作成するごとにこの数字がインクリメントされていきます。
arn:aws:lambda:ap-northeast-1:123456789012:function:provisioned-concurrency-test:2
一度作成したバージョンのコードや設定内容は後から変更することはできません。
Lambda の更新時はこのバージョンごとにアクセスを振り分けたりすることで、カナリアデプロイメントなんかも実現できますというわけですね。
また、 非修飾 ARN
と呼ばれる Lambda 関数の ARN があります。
arn:aws:lambda:ap-northeast-1:123456789012:function:provisioned-concurrency-test
これは $LATEST
という特殊なバージョンを指すものになっており、要するにその時点での最新のコードに対応します。
「特殊」と書いたのは、この $LATEST
バージョンのコードはいくらでも変更でき、特定のバージョンの中身はあとから変更できないという仕様に当てはまらないからです。
エイリアス
エイリアスはこのバージョンに対して貼るものになっています。
エイリアス自体は $LATEST
バージョンに対しても設定できます。
また、エイリアスは向き先のバージョンを後から変更できます(同時に複数のバージョンを指すことはできません)。
ですので向き先のバージョンを Lambda 関数をデプロイするたびに切り替えるようにすれば、バージョンがどんどんインクリメントされても常に同じ修飾 ARN で呼び出すことが出来るわけですね。
修飾 ARN はバージョンの時と似たような形になります。 当然数字( 1 とか 2 とか)はバージョンの命名と被ってしまうのでエイリアス名として使えません。
arn:aws:lambda:ap-northeast-1:123456789012:function:provisioned-concurrency-test:dev
再び Provisioned Concurrency
ここで Provisioned Concurrency の話に戻ってきます。
Provisioned Concurrency はバージョンかエイリアスに対して指定できます。が、 $LATEST
に対しては設定できません。
非公開バージョン ($LATEST) を参照するエイリアスにプロビジョニングされた同時実行数を割り当てることもできません。
ですので、 $LATEST
以外のバージョンかもしくは向き先が $LATEST
ではないエイリアスをターゲットに指定しなくてはなりません。
ALB のターゲット
さて、 ALB のターゲットグループに Lambda 関数を指定する場合、バージョンかエイリアスを指定します。
このバージョンは $LATEST
を含みます。
ですので、何も考えずに $LATEST
バージョンを指定すれば、 ALB 経由で呼び出される Lambda は常に最新状態のものということになります。
現にマネジメントコンソールから設定すると、デフォルトでは $LATEST
が選択されています。
じゃあそれでいいじゃん、となりそうですがここにProvisioned Concurrency が絡むと話が変わってきます。
そうです。Provisioned Concurrency は $LATEST
バージョンに対して設定することはできません。
直前に述べたように $LATEST
以外のバージョンかもしくは向き先が $LATEST
ではないエイリアスをターゲットに指定しなくてはなりません。
ではバージョンとエイリアスのどちらが良いか、ですが、 ターゲットグループは一度指定した ARN を後から変更できない 仕様を考慮すると答えはおのずと見えてきます。
ちなみに変更したい場合はターゲットグループから登録解除し、新たに作成したターゲットをまたターゲットグループに登録する必要があります。(めんどくさい)
はい、という訳で冒頭のこのドキュメントに行きつきます。
ロードバランサーが常に現行バージョンの Lambda 関数を呼び出せるようにするには、関数のエイリアスを作成し、ロードバランサーに Lambda 関数を登録するときに関数 ARN にエイリアスを含めます。
まとめると、あるべき姿はこうなります。
- Lambda 関数を更新したら新しいバージョンを作成する
- Lambda 関数の 1 のバージョンが向き先となるエイリアスを作成する
- Provisioned Concurrency は 2 のエイリアスに対して設定する
- ターゲットグループのターゲットには Provisioned Concurrency を設定したエイリアスを指す Lambda 関数の修飾 ARN を指定する
こうすることで、公開する Lambda 関数が更新されても、バージョンの作成とエイリアスの向き先変更だけやれば常に同じ ALB で Provisioned Concurrency の効いた Lambda 関数を呼び出せる、という訳です。
また、 バージョンの作成とエイリアスの向き先変更
の手順もドキュメントの機械翻訳がヤバいことでおなじみの AWS SAM(Serverless Application Model) にて AutoPublishAlias を設定すれば自動でやってくれます。
- AutoPublishAlias: AWS SAM では、このプロパティを追加し、エイリアス名を指定することで、以下を実行します。
- Lambda 関数の Amazon S3 URI に対する変更に基づいて、新しいコードがいつデプロイされるかを検出します。
- 最新のコードでその関数の最新バージョンを作成して発行します。
- Lambda 関数の最新バージョンを参照するエイリアスを指定された名前で作成する (エイリアスがまだない場合)。関数の呼び出しでエイリアスを利用するには、エイリアス修飾子を使用する必要があります。Lambda 関数のバージョニングとエイリアスに慣れていない場合は、AWS Lambda 関数のバージョニングとエイリアス。
おわりに
完全に私事ですが Lambda 関数に $LATEST
以外のバージョンを作ったりエイリアスを作成したり、はたまた Provisoned Conccurency を使うような機会も今までありませんでした。
しかも ALB 経由で Lambda を呼び出すこと自体も初めてだったので、当初は色々混乱してしまいました。
せっかくなので、そのあたりの回り道した過程もまとめてみましたという訳です。
今後似たような事態に遭遇して「なんかよく分からんがレスポンス速度からして多分 Provisoned Conccurency 効いてないのでは?」となって困っている方の参考になれば幸いです。