安い?それとも高い?Provisioned Concurrencyを有効化したLambdaのコストに関する考察 #reinvent

2019.12.12

CX事業本部@大阪の岩田です。先日のアップデートでLambdaにProvisioned Concurrencyの設定が追加されました。実行準備のできたLambda実行環境を指定した数だけプーリングすることで、コールドスタートを回避できるナイスな機能です。

が、ちょっと待って下さい。本来サーバーレスアーキテクチャは必要な時だけ必要なリソースを確保して、アイドル時間には課金されないというのが特徴ではなかったでしょうか?詳しくは後述しますがProvisioned Concurrencyの設定でLambda実行環境を予約すると、Lambdaが起動しなくてもアイドル時間に課金が発生します。元々アイドル時間に課金されないことをモチベーションにLambdaを選定していたようなケースでは、本当にProvisioned Concurrencyを使うべきなのかは良く考えた方が良さそうです。以後Provisioned Concurrencyのコストについて考えてみます。

前提条件

以後のコスト試算は全て以下の前提で計算していきます。

  • リージョンは東京
  • データ転送料金は無視
  • 無料利用枠も無視
  • 課金対象となる時間の切り捨て、切上げは無視
  • 料金は2019年12月時点の料金
  • 他サービスの料金は無視 現実的には考え辛いですが、LambdaやFargate単体で完結するシステムを想定

Lambdaの料金体系比較

まずLambdaの料金体系についておさらいです。Lambdaの料金体系はProvisioned Concurrencyの利用有無によって異なります。

参考:AWS Lambda Pricing

通常のLambda(Provisioned Concurrencyの利用なし)

課金体系は以下のようになります。

課金対象 料金
リクエスト回数 100万リクエストあたり$0.20
実行時間 GB秒あたり$0.000016667

Provisioned Concurrencyを利用する場合

課金体系は以下のようになります。

課金対象 料金
リクエスト回数 100万リクエストあたり$0.20
実行時間 GB秒あたり$0.000012562
Provisioned Concurrency GB秒あたり$0.000005384

実行時間に対する課金が少し安くなっている反面、Provisioned Concurrencyに対する課金が追加されています。この課金はProvisioned Concurrencyを有効化してから無効化するまでの時間を5分単位で切り上げて計算し、Lambanoの実行有無に関わらず発生します。

実行時間に対する課金とProvisioned Concurrencyを合計すると、0.000012562 + 0.000005384 = $0.000017946となり、通常のLambdaの実行時間に対する課金$0.000016667を上回ります。Provisioned Concurrencyを利用すると通常のLambdaよりも料金は上がると考えて良さそうです。まあ当たり前っちゃ当たり前ですね。

また、今回は考慮外としていますが、Provisioned Concurrency を利用する場合は無料利用枠が適用されませんので、その点も注意が必要です。

Fargateとの料金比較

サーバー管理が不要なアーキテクチャとして、良くLambdaの比較対象に上がるのがFargateです。Provisioned Concurrencyを利用するLambdaとFargateの料金はどのような関係性になるのか比較してみました。

Lambdaはメモリ割り当てのみ調整可能なのに対してFargateはメモリ,CPU共に調整可能です。極力近しいリソース使用量になるように

  • Lambda...メモリ2G
  • Fargate...メモリ2G, 1vCPU

という条件で、リソースを1ヶ月間起動し続けた場合のコストを比較してみます。なお、FargateのSpotやSaving Plansは利用しないこととします。

Fargateの料金

Fargateの料金体系は以下の通りです。

課金対象 料金
1 時間あたりのvCPU 0.05056USD
1 時間あたりのメモリ(GB) 0.00553USD

メモリ2G,1vCPUの設定で、1つのタスクを30日間起動し続けた場合は

  • vCPU ... 30 × 24 × 0.05056 = 36.4032
  • メモリ ... 2 × 30 × 24 × 0.00553 = 7.9632

合計すると約$44/月の課金となります。

Provisioned Concurrencyを設定したLambdaの料金

メモリを2G割り当てたLambda実行環境を1つ30日間予約し続けた場合は

  • Provisioned Concurrency... 2 × 30 × 24 × 60 ×60 × 0.000005384 = 27.910656

1度も処理が実行されなかった場合に約$28/月の課金となります。処理が実行されればさらに課金が発生することになりますが、意外なことに?Fargateよりも安いという結果になりました。リソースの常時起動が必要、かつコールドスタートの遅延が許容し辛いユースケースではFargateの代替としてProvisioned Concurrencyを設定したLambdaが選択肢に入りそうです。

EC2との料金比較

非サーバーレスアーキテクチャの代表格であるEC2ともコストを比較してみましょう。極力近しいリソース使用量になるように

  • Lambda...メモリ3008Mの環境を2つ予約(メモリ6016M,2vCPU)
  • EC2...m5.large(メモリ8G,2vCPU)

という条件で、リソースを1ヶ月間起動し続けた場合のコストを比較してみます。EC2はオンデマンド料金とします。

EC2の料金

東京リージョンにおけるm5.largeのオンデマンド料金は0.124$/hです。30日間起動し続けた場合は

  • 30 × 24 × 0.124 = 89.28

約$89/月の課金となります。

Provisioned Concurrencyを設定したLambdaの料金

メモリを3008M割り当てたLambda実行環境を合計2つ、30日間予約し続けた場合は

  • Provisioned Concurrency... 6 × 30 × 24 × 60 ×60 × 0.000005384 = 83.731968

1度も処理が実行されなかった場合に約$84/月の課金となります。m5.largeとの比較なのでLambdaの方がメモリ2G程度不足した基準での比較ですが、割とEC2と近しいレベルの金額感では無いでしょうか?

通常のLambdaとの比較

今度は通常のLambdaとの料金比較をシミュレーションしてみます。以下の前提条件で比較します。

  • Lambdaの処理は毎回1秒かかる
  • 100万回/月実行される
  • メモリ割り当ては2G
  • 全てのリクエストは直列実行され、同時に複数のLamdbaが起動することはない

通常のLambda

通常のLambdaは以下のような課金になります。

  • リクエスト... 1000000/1000000 × 0.2 = 0.2
  • 実行時間... 1000000 × 1 × 2 × 0.000016667 = 33.334

合計すると約$33/月の課金となります。

Provisioned Concurrencyあり(1ヶ月上げっぱなし)

続いてProvisioned Concurrencyを設定した場合です。Application Auto Scalingは特に使わずLambda実行環境を1ヶ月間予約しっぱなしにした場合の想定です。

  • リクエスト... 1000000/1000000 × 0.2 = 0.2
  • 実行時間... 1000000 × 1 × 2 × 0.000012562 = 25.124
  • Provisioned Concurrency... 30 × 24 × 60 ×60 × 2 × 0.000005384 = 27.910656

合計すると約$53/月の課金となります。通常のLambdaに比べると結構お高いですね。さらに今回は考慮外にしていますが、Provisioned Concurrencyを使うと無料利用枠が使えなくなるというデメリットもあります。

Provisioned Concurrencyあり(スケールを完璧に制御した場合)

現実的にはありえないですが、Application Auto Scalingを完璧に制御し、Lambdaにリクエストが流れてくる時間帯だけProvisioned ConcurrencyでLambda実行環境をプロジョニングし、使い終わったらProvisioned Concurrencyを0に戻すシナリオを考えてみます。考え方をシンプルにするため、Provisioned Concurrencyを有効化すると即座にLambda実行環境がReady状態となり、無効化すると即座に破棄される仕様とします。このシナリオではProvisioned Concurrencyで予約したLambda実行環境が100万秒だけ起動することになり、課金は以下のようになります。

  • リクエスト... 1000000/1000000 × 0.2 = 0.2
  • 実行時間... 1000000 × 1 × 2 × 0.000012562 = 25.124
  • Provisioned Concurrency... 1000000 × 2 × 0.000005384 = 10.768

合計すると約$36/月の課金となります。通常のLambdaに大分近付きました。コストメリットが出るようにProvisioned Concurrencyと付き合うためには、うまくApplication Auto Scalingを設定するのが重要になりそうです。

まとめ

Provisioned Concurrencyの利用有無によるコストの変化、Fargate/EC2との比較について考察してみました。Application Auto Scalingが適切に設定できればProvisioned Concurrencyを有効化してもなおFargateやEC2に対してコストメリットが出せそうです。ただし、Application Auto Scalingを自分で適切に設定するというのは、本来サーバーレスアーキテクチャのメリットである

  • 自動スケール
  • インフラ管理不要

という部分を一部放棄することになります。このあたりの管理コストも考慮した上でProvisioned Concurrencyの導入を検討頂ければと思います。

個人的な見解ですが、20本のLambdaから構成されるシステムで、全てのLambdaに対してProvisioned Concurrencyを設定するようなアーキテクチャは黄色信号かなー。と考えています。本当に全てのLambdaでコールドスタートを回避したいなら、LambdaではなくFargateやEC2を利用するのが適切なのではないでしょうか?逆に20本のLambdaのうち、1本だけはコールドスタートを回避したい といったユースケースにはProvisioned Concurrencyがうまくハマりそうです。ただし、

  • 適切にApplication Auto Scalingを設定しないとコストが大きくなること
  • Provisioned Concurrencyを設定しても、設定数以上にLambdaが起動すればコールドスタートは発生する

という点には留意する必要があります。うまく特性を抑えた上で、うまく付き合っていきたいですね。