Fargate VS Lambda 両者の違いをスタートアップCTOが本気で考えてみた!

Fargate VS Lambda 両者の違いをスタートアップCTOが本気で考えてみた!

こんにちは!

Docker による開発がデファクトな近年では、Fagate による Docker 管理が非常に多くなってきました。わたしたちの開発でも Fargate は多くの例で採用しており、最近では EC2 を SSH で操作するのには抵抗を感じます。すっかり Fargate の魅力に取り憑かれていますね。

しかし最近、お客様から下記のようなご質問を多くいただくケースが多くなってきました。

「 Lambda と Fargate はどう使い分けるの?」

「 Lambda の方が簡単!Lambda で済ませたいけどどうかな?」

これを理解するには、まず両者の違いをしっかり理解する必要があります。

Aws Fargateは何者?

AWS Fargate は、コンテナオーケストレーション用のサーバー( 例えば EC2 を自前で構築し Docker デーモンを管理するサーバー )を自身で管理することなく、Docker コンテナ実行を実現できる AWS サービスです。

Docker コンテナーの起動、停止、Latest への差し替えなどをマネージすることが可能です。

また Code Piepline と接続することも可能なので、私たちはよく Code Build で Dockerfile をビルド→ ECR へ Latest タグのイメージをプッシュ→ ECS でタスクを実行し連携させることが多いです。

ここで、わたしたちが考える、この Fargate を理解する上で最も重要なのは、「 Fargate は実際には AWS ECS でコンテナーを実行する方法の1つにすぎない」ということです。( ECS は EC2 インスタンスでの実行中のコンテナと Fargate の両方をサポートしています )

Fargate は、Docker コンテナーを使用してアプリケーションを実行しますが、コンテナーは ECS タスク( Kubernetes のポッドと同様 )として実行され、タスクはサービス( Kubernetes デプロイメントと同様 )によって管理されます。

また、Fargate は Elastic Load Balancer へのターゲットグループに連動が可能です。そのため HTTPトラフィックを受信できますが、この方法の場合は、Fargate のタスクが生きていないとトラフィックに対してレスポンスを返せず、ELB が504タイムアウトエラーを返却してしまいます。サービスでタスクを管理する際に必要タスク数を必ず1以上に設定しましょう。( スケジュールで起こすアーキテクチャーも可能です )

この点は、Lambda と API Gateway のコールドスタート問題と似ていますが、Fargate の場合は実行中のタスクをリアルタイムで監視を行える上、ECS 上コンテナーのログを見ることができます。障害の切り分けが非常にしやすく、一時的に起動するタスクの定義を差し替えるなど柔軟に対応をすることが可能です。

Aws Lambdaは何者?

AWS Lambdaは、サーバーをプロビジョニングすることなく、AWS で関数単位でコードを実行できるようにするサービスです。

  • 開発者は基本的にコードをアップロードし実行
  • 関数のメモリ量を指定可能( メモリ量に応じてCPUが高性能になる )
  • イベント駆動型で様々な Aws サービスのイベントで呼び出せる

Lambda で使用されるインスタンス(OS)は一時的なもので、コードは実行時にのみ呼び出され実行、実行後インスタンスは削除されます。( すぐには消えず、次のリクエストを一定時間待機する様子 )

つまり Lambda は永続的なサーバーではありません。例えば Laravel のセッションをサーバー内のローカルファイルに指定している場合は不具合を起こるので注意が必要です。

例として、Lambda 関数をトリガーできるリソースは下記です。

  • CloudFront と連携する Lambda Edge
  • API ゲートウェイと連携する Lambda Proxy
  • S3 の各種イベント
  • DynamoDB ストリームイベント
  • ELB ターゲットグループ

また、現在利用可能な Lambda のランタイムをご紹介します。

Amazon Linux

  • イメージ – amzn-ami-hvm-2018.03.0.20181129-x86_64-gp2
  • Linux カーネル – 4.14.154-99.181.amzn1.x86_64

Amazon Linux 2

  • イメージ – カスタム
  • Linux カーネル – 4.14.138-99.102.amzn2.x86_64

Node.js ランタイム

名前識別子AWS SDK for JavaScriptオペレーティングシステム
Node.js 12nodejs12.x2.585.0Amazon Linux 2
Node.js 10nodejs10.x2.585.0Amazon Linux 2

Python ランタイム

名前識別子AWS SDK for Pythonオペレーティングシステム
Python 3.8python3.8boto3-1.10.34 botocore-1.13.34Amazon Linux 2
Python 3.7python3.7boto3-1.10.34 botocore-1.13.34Amazon Linux
Python 3.6python3.6boto3-1.10.34 botocore-1.13.34Amazon Linux
Python 2.7python2.7boto3-1.10.34 botocore-1.13.34Amazon Linux

Ruby ランタイム

名前識別子AWS SDK for Rubyオペレーティングシステム
Ruby 2.7ruby2.73.0.1Amazon Linux 2
Ruby 2.5ruby2.53.0.1Amazon Linux

Java ランタイム

名前識別子JDKオペレーティングシステム
Java 11java11amazon-corretto-11Amazon Linux 2
Java 8java8java-1.8.0-openjdkAmazon Linux

Go ランタイム

名前識別子オペレーティングシステム
Go 1.xgo1.xAmazon Linux

.NET ランタイム

名前識別子言語オペレーティングシステム
.NET Core 2.1dotnetcore2.1C#PowerShell Core 6.0Amazon Linux

Lambda で他の言語を使用するには、カスタムランタイムも実装が可能となっています。

名前識別子オペレーティングシステム
カスタムランタイムprovidedAmazon Linux

ここで重要なのは、Lambda は Docker コンテナーの実行をサポートしていないということです。

Fargate VS Lambda

わたしたちは、ウェブサーバークラスの大きなプロセスを実行する際は Fargate、小粒のイベント処理する際は Lambda を採用しています。

ただ正直なところ多くのケースで Lambda より Fargate を採用することが多いです。

  • Lambda での開発をは制約との戦いになることがしばしば( 例えば API Gateway と連携させる場合はレスポンスサイズに制限があったり… )
  • Fargate はローカルでの開発とデプロイ環境での実行を Docker で統一化できるのでデプロイ後に不具合がほぼない( 開発と Fargate は疎結合 )
  • ECS でタスクを一元管理できるのでアプリ全体を Fargate で閉じることが可能、管理しやすく勝手にスケールするので楽できる

Lambda は付き合い方を間違えるとしばしば苦しむことがあります。例えば、Nuxtjs などを Lambda へデプロイし SSR し、API Gateway へレスポンスするケースを想像してください。

もし Nuxtjs で Ant-Design などの UIフレームワークと AwsSDK などの大容量のバンドルファイルを返却しようとした場合は、確実に Lambda のレスポンスサイズの制約に引っかかりエラーとなります。( 下手したらデプロイサイズの制限に引っかかりデプロイできません… )

詳しくはLambdaの制約を参照ください。

このような理由から、Lambda より Fargate の方が開発時の制約が少ない上に、デプロイ時のトラブルが圧倒的に少なく、運用・リリースでストレスがかからないことが分かります。( 使いどころによっては Lambda の方が開発効率が良いケースもあります )

LambdaとFargateどっちが高い?

前提としてLambda と Fargate は完全に別々の課金モデルを使用しているため、コードを実行する際の料金を比較することは困難です。もしこれを明確にしたい場合は、Lambda と Fargate のコストを見積もるのに多くの時間が必要ですね。(現実的なワークロードでの違いを確認するために両方を試す必要があります)

Fargateの料金体系

Fargateは、1時間あたりのCPUとメモリの使用に対して課金されます。最新の価格情報はこちらをご覧ください

高いスケールで非常に予測可能なワークロードで使用する場合、Fargate だけに依存するのではなく、EC2 インスタンスを使用して一部のECSタスクを実行することも可能です。EC2 タスクの実行の場合「サーバーレス」の側面は失われますが、スポットインスタンスまたは予約済みインスタンスを使用すると、EC2 を大幅に安価にできます。EC2 の価格情報はここにあります

Lambdaの料金体系

Lambda は、リクエスト数、メモリ、関数実行の秒数の組み合わせで課金されます。最新の価格情報はこちらをご覧ください。

Lambda コストを節約したい場合は、関数のメモリ要件のサイズを適切に設定することがとても重要です。512Mbのメモリを使用するように関数を構成しても、実行中に128Mbしか消費しない場合、基本的に各呼び出しのコストが4倍に増加しています…。

Lambda を初めて使用する場合は、CloudWatch請求アラームをセットアップし、Lambda による想定以上の請求を回避する方法があります。

ラムダ関数のログを参照すると、呼び出されたラムダの使用メモリと実行時間を確認できますので確認してみてください。

また、Lambda 関数が Kinesis などのイベントストリームからトリガーされる場合は、バッチサイズ設定し、呼び出しの数も減らすことができますので、こちらも合わせて検討してみてください。

比較してみた所感

途中にも書きましたが、やはり小粒処理は Lambda、大きな処理は Fargate やその他の Aws サービスを活用することを推奨します。( 例えばストリーミング処理であれば KinesisStream など )

Aws での開発は、各種サーバーレスサービスを上手に組み合わせることで、物理設計を意識することなくサービスのソフトウェア開発に集中させてくれます。

Fargate やサーバーレス開発は是非ご相談ください。