Web アプリケーションにおける Amazon ECS / AWS Fargate アーキテクチャデザインパターン

2024-09-03
コミュニティ通信

Author : 新井 雅也 (AWS Container HERO)

こんにちは。AWS Container Hero の新井です。

Amazon ECS の登場から間もなく 10 年が経ちますが、その間、ECS ⾃体の進化に加えて、さまざまな AWS マネージドサービスとの連携が可能になりました。 現在では、コンテナベースのワークロードを活⽤することで実現できないことを探す⽅が難しいほど、柔軟なアーキテクチャが構築できるようになっています。 しかし、⾃由度が⾼い分、要件に合ったアーキテクチャを模索する際には、迷うことも多いでしょう。

AWS上でシステムを適切に構築するためには、あらかじめサービス間のつなぎ⽅やパターン、その特徴を把握しておくことが重要です。 これにより、フィージビリティを迅速に確認でき、その後のトライアンドエラーのサイクルを加速させることができます。

今回は、最新の AWS サービスアップデートを踏まえつつ、Amazon ECS / AWS Fargate を中⼼とした代表的なアーキテクチャパターンを紹介します。

アーキテクチャの前提

本投稿では、ECS/Fargate を前提とした Web アプリケーションの代表的なアーキテクチャ例をご紹介します。 アプリケーションのソースコードは GitHub で管理されていることを想定しています。 なお、本投稿で紹介するアーキテクチャはあくまで⼀例です。

ビジネスやサービスの要件によっては、これらのアーキテクチャが最適ではない場合もあります。 選択肢が存在するアーキテクチャには常にトレードオフが伴うことをご留意ください。

このクラウドレシピ (ハンズオン記事) を無料でお試しいただけます »

毎月提供されるクラウドレシピのアップデート情報とともに、クレジットコードを受け取ることができます。 


1. パブリック API サービスパターン

まず最初に紹介するアーキテクチャは、外部向けに API を公開するパターンです。 ECS / Fargate タスクのみでサービスを公開することも可能ですが、可⽤性のスケーリングやセキュリティの観点から、Application Load Balancer (ALB) や Amazon API Gateway を利⽤するケースが⼤半です。それでは、順に紹介していきましょう。

1-1. ALB による API サービスパターン (WAF なし)

パブリック ALB で ECS タスクを束ねてサービス公開するパターンです。
シンプルなサービス提供であれば、この構成でも十分機能します。
加えて、Application Auto Scaling と組み合わせることで、適切な負荷分散とスケーリングを実現できます。

1-2. ALB による API サービスパターン (WAF あり)

セキュリティをさらに強化するために、AWS WAF を構成して ALB と連携させることができます。

WAF を設定することで、SQL インジェクションや XSS などの一般的な攻撃から防御し、アクセス元の地域を制限することも可能となり、より安全なAPI提供が実現します。

1-3. API Gateway による API サービスパターン (WAF なし)

ビジネスやサービスの要件に応じて、認証処理のカスタマイズやアクセスの流量制御を実装したい場合には、Amazon API Gateway を利用することが効果的です。API Gateway には REST API と HTTP API の 2 種類 があり、それぞれで利用できる機能が異なります。

今回は HTTP API の例を紹介しますが、このパターンでは バックエンドリソースとして ALB とのプライベート統合が可能 です。

また、AWS Cloud Map とプライベート統合することで、ECS タスクに直接処理を連携させることもできます。

1-4. API Gateway による API サービスパターン (WAF あり)

先ほど紹介した HTTP API を使用する API Gateway パターンでは、仕様上 WAF との連携ができません。セキュリティ対策として WAF を利用したい場合には、REST API による API Gateway を選択する必要があります。

一方、REST API を使用する API Gateway では、ALB や Cloud Map とのプライベート統合はサポートされていません。

そのため、WAF の利用を前提として、REST API による API Gateway を利用しつつ、API Gateway と ECS タスク間をプライベートな経路に保つためには、NLB を経由させる必要があります。

代替策として、ALB をパブリックエンドポイントとして設定し、HTTP API を使用する API Gateway リソースと接続することが可能です。

また、HTTP API の前に CloudFront を配置し、CloudFront に AWS WAF を設定することで、HTTP API を使用しつつも WAF による保護を実現することができます。


2. SPA パターン

Next.js や Nuxt.js などを用いてシングルページアプリケーション (SPA) を AWS 上で実現する場合、CloudFront と Amazon S3 を組み合わせてサービスを提供するパターンが一般的です。

具体的には、パッケージを含む Web アプリケーションに必要な資材を S3 に配置し、Web アプリケーションから必要なデータを API として呼び出す構成です。

全体構成図

先ほど取り上げた「API Gateway による API サービスパターン」と組み合わせることで、Web アプリケーションに必要な API を提供する構成となっていますね。

API Gateway による API サービスパターンとの違いは、API リクエストが CloudFront を通過する点です。もちろん、CloudFront を経由せずに API を実装することも可能ですが、エンドポイントを分離すると CORS の対応が必要になるため、CloudFront でエンドポイントを集約することで実装をシンプルにすることができます。

CloudFront と WAF を連携させているにもかかわらず、CloudFront を経由せずに API Gateway に直接アクセスされることは避けたいところです。

これを防ぐために、CloudFront のオリジンカスタムヘッダーと API Gateway の API キー認証を有効化する構成が有効です。ただし、API Gateway の API キー認証は REST API のみが対応しており、HTTP API では対応していません。その場合、カスタム認証などで制御する必要があります。


3. SSR パターン

Next.js や Nuxt.js などを使用してサーバーサイドレンダリング (SSR) アプリケーションをデプロイする際にも、ECS/Fargate アーキテクチャは有効です。
構成は比較的シンプルであり、レンダリング用サーバーとバックエンド API 用サーバーを ECS タスクとして設定することで実現できます。

このアーキテクチャ例では、エンドポイントを提供するために ALB を使用していますが、API Gateway を利用したサービス提供ももちろん構成可能です。
また、グローバルからのアクセスを最適化したいケースでは、エッジロケーションの有効活用の観点から ALB の手前に CloudFront を配置することも有効でしょう。


4. ソーシャルログインパターン

Web アプリケーションをユーザーに提供する際、Google や Facebook などのソーシャルログインを利用した認証を導入するケースが増えています。
ECS/Fargate ベースの Web アプリケーションでソーシャルログインを実装する場合は、外部 IdP (アイデンティティプロバイダー) と連携する役割を担う Amazon Cognito を、ALBAPI Gateway と組み合わせることで実現できます。


5. 内部サービス連携パターン

マイクロサービスアーキテクチャでサービスを展開する際、各サービス間をどのように接続するかは重要な設計ポイントのひとつです。ECS/Fargate を前提としたサービスにおいては、その接続方法は非常に多岐にわたりますが、本投稿では 4 種類の内部サービス連携パターンを紹介します。各サービスは ECS サービスを想定しています。

5-1. 内部 ALB 接続パターン

ECS サービスのエンドポイントとして内部 ALB を利用するパターンです。
ALB を介することで、後述する CI/CD パターンにおいて AWS CloudDeploy と組み合わせた Blue/Green デプロイメントの実現や、リスナールールを追加してカスタムレスポンスを返すなど、さまざまなメリットを享受できます。

ただし、ALB のリソース管理と利用料金が発生するため、多数のサービスや複数の環境を持つシステムの場合、コストが高くなる可能性があります。

5-2. ECS サービス検出パターン

ALB を使用せずに、ECS のサービス検出機能を活用するアーキテクチャパターンです。
ECS サービスを作成する際、AWS Cloud Map に自身の DNS 名を登録し、他の ECS サービスから参照可能にします。

後述する App Mesh パターンと比べてネットワークトラフィックの情報は取得できないものの、内部 ALB 接続パターンと比べてコストが低く、構成もシンプルで、DNS ラウンドロビンによる負荷分散も可能です。

5-3. App Mesh 接続パターン

ECS サービス間の接続に AWS App Mesh を活用するパターンです。
App Mesh を利用するには、ECS タスクに Envoy コンテナをサイドカー構成で追加し、サービス検出を自動化します。

App Mesh を使用することで、サービス間の一貫したモニタリングやネットワークトラフィック管理が可能になります。ただし、Virtual Node や Virtual Router、Virtual Service といった App Mesh のリソース管理が追加で必要です。

5-4. ECS Service Connect パターン

4 つ目の ECS サービス間接続パターンは、ECS Service Connect を活用するアーキテクチャです。
ECS Service Connect は比較的新しい接続パターンですが、Elastic Load Balancer や App Mesh 等の追加コンポーネントの管理が不要となります。

また、ECS の機能として完結した形でトラフィックのメトリクスや通信品質の向上するため、これまで紹介した 3 つの接続パターンのデメリット解消が期待できます。ただし、ECS Service Connect を利用する際には、透過的に Envoy がサイドカーとして付与されます。このサイドカーに必要なリソースを設計し、割り当てる必要があり、ECS タスク数が増えるとコストが高くなる可能性がある点には注意が必要です。

なお、今回は詳しく触れませんが、VPC Lattice を利用することで、複数のマイクロサービスリソースを抽象化しつつ接続するパターンも存在します。VPC やアカウントを跨る場合のサービス間接続において有効です。


6. ジョブ構成パターン

これまで接続してきたパターンは主に常に稼働する Web アプリケーションを前提としたアーキテクチャでした。

一方、Web アプリケーションではデータ加工等の非同期処理が必要になるケースも多いでしょう。ECS/Fargate はデータ加工や非同期によるジョブにも大いに活用できます。

いくつかの代表的なデザインパターンを見ていきましょう。

6-1 ジョブ定期実行パターン

あらかじめ決まった時刻や周期で処理を実行したいケースでは、Amazon EventBridge で Cron 式を定義し、ECS タスクを定期実行することで構成可能です。

シンプルなジョブを実装する場合は十分なアーキテクチャパターンですが、AWS リソース側でリトライ制御ができないため、アプリケーション側でフォローが必要です。また、一時的なタスク起動のエラー等に関してもハンドリングできないため、これに対処する場合は後述の StepFuctions によるジョブフローパターンを活用しましょう。

6-2. ジョブワークフローパターン

AWS Step Functions を活用することで ECS や AWS Lambda によるジョブワークフローを構成するアーキテクチャパターンです。

AWS 上でマネージド・サービスを活用しつつ複数の処理を連携する際はデファクトスタンダードともいえる構成ですが、ジョブ定期実行パターンと異なり、各処理のエラーハンドリング等も実装可能です。

6-3 ジョブ API 実行パターン

「ジョブワークフローパターン」の応用ですが、Step Functions 上にてコールされる処理から、マイクロサービスとして用意されている API を実行しながら処理を実行していくパターンです。オンラインで発生した処理を非同期で実行するケースでも利用されます。

なお、今回は一般的な Web アプリケーションサービスを想定しているため紹介は割愛しますが、金融系サービスやヘルスケア等で求められるハイワークロードなジョブ実行が必要ケースでは、AWS Batch および Amazon EC2 や ECS を組み合わせたパターンも有効でしょう。


7. ログ運用パターン

ここからは、Web アプリケーションのサービスというよりも、運用に必要なアーキテクチャパターンを紹介します。

ログの管理や運用といえば、Amazon CloudWatch Logs が一般的ですが、目的によってはログの長期保管のために Amazon S3 への保存が求められるケースもあります。

ここでは、ECS/Fargate における代表的なログ運用の構成を見ていきましょう。

7-1. CloudWatch Logs 連携パターン

ECS では、タスク定義に CloudWatch Logs の出力先と適切な IAM ロールを設定することで、アプリケーションログを簡単に実装できます。この連携により、後述するアラート通知の実現が可能となります。

アーキテクチャパターンとしては基本的なものですが、運用面で重要な役割を果たします。

7-2. ログ長期保管向け S3 連携パターン

CloudWatch Logs へのログ出力はシンプルで便利ですが、ログの出力ボリュームによっては取り込み料金や保存料金が高額になることがあります。法令やガバナンスの要件による長期保管が必要な場合、S3 にログを転送し、CloudWatch Logs には一部のエラーログや分析対象のログのみを保存したいこともあるでしょう。

そうした場合には、FireLens for Amazon ECS を利用したカスタムログルーティングが有効です。具体的には、AWS 推奨の Fluent Bit を同梱したコンテナをサイドカーとして構成し、ログ内容に応じて出力先を制御するアーキテクチャです。

サイドカー構成のため、追加の ECS タスクリソース設計が必要ですが、ログの構成を柔軟に行えるため、筆者としては単純な CloudWatch Logs の利用よりも推奨したい構成です。


8. アラート通知パターン

Web アプリケーションを安定稼働させるためには、アプリケーションのエラーログやクラウドの異常なイベントを、適切なタイミングで通知して対処することが重要です。

ここでは、Slack への通知を例に、代表的なアーキテクチャパターンを紹介します。

8-1. アプリケーションエラー通知パターン

CloudWatch Logs では、サブスクリプションフィルターを利用して、「ERROR」を含むログなど、特定の条件に合致したログのみを抽出できます。この抽出内容を Amazon SNS に連携し、さらに AWS Chatbot と関連付けることで、アプリケーションのエラーログに基づいた Slack 通知が可能になります。

別のパターンとして、CloudWatch メトリクスフィルターから CloudWatch アラームを作成し、それを SNS→Chatbot→Slack へと接続する方法もあります。ただし、この場合、アプリケーションのエラーログ内容を Slack に直接通知することはできません。そのため、ログ内容も含めて通知したい場合には、最初に述べたアーキテクチャパターンをお勧めします。

8-2. ECS アラート通知パターン

たとえば、ECS タスクの起動に失敗した場合など、ECS に関連するエラーイベントは Amazon EventBridge で取得できます。

EventBridge から SNS トピックとして通知し、AWS Chatbot に連携することで、簡単に Slack へのアラート通知を実装できます。通知したい ECS のイベントを EventBridge でフィルタリングすることで、運用に適した情報のみを通知できます。


9. ECS タスク CI/CD パターン

ECS/Fargate を中心としたアプリケーションにおける CI/CD のアーキテクチャについても触れていきましょう。

GitHub によるアプリケーションコードリポジトリ管理を前提としたパターンを 2 つほど取り上げます。

9-1. GitHub Actions による CI/CD パターン

ひとつの方法として、GitHub Actions を活用し、静的解析、テスト、イメージのビルドからデプロイまでを実行する CI/CD アーキテクチャがあります。このアーキテクチャの特徴は、CI/CD に関連するすべての処理が GitHub 側で完結する点や、アプリケーション開発者が CI/CD パイプラインの構築に対してオーナーシップを持ちやすい点にあります。

一方、この構成では、Amazon ECR へのイメージプッシュや ECS タスクの更新するための IAM 権限や OIDC 等による連携が必要であり、それらの権限を GitHub リポジトリに適切に付与することが求められます。

9-2. Code シリーズによる CI/CD パターン

AWS では、AWS CodeBuild や AWS CodeDeploy、さらに CI/CD パイプラインを管理する AWS CodePipeline などのサービスが提供されています。たとえば、ビルド処理時に AWS の各種リソースにアクセスする必要がある場合、GitHub 側ではなく CodeBuild 側に必要な IAM ロールを付与することで、AWS 内で完結した権限管理が可能となります。

また、CodeDeploy を活用することで、カナリアデプロイや Blue/Green デプロイメント、リリース後のロールバックを迅速に実行できます。


10. 開発デバッグパターン

最後に紹介するのは、開発時にデバッグが必要な際に役立つアーキテクチャパターンです。

アプリケーション内部の挙動を確認したり、特定のサービスに対する通信ができないといったネットワークの問題が発生した際に、原因を切り分けるために活用できるものです。

10-1. ECS exec 利用パターン

1 つ目は、ECS タスクに対してコマンド実行やシェルアクセスを行うための ECS Exec パターンです。

このしくみは、AWS Systems Manager のセッションマネージャーがコンテナとの接続を確立するものです。利用するには、ECS タスク定義の変更や ECS サービスおよび ECS タスク実行時のオプション指定が必要です。

デバッグが必要な状況に備えて、これらの手順を事前に準備しておきましょう。

10-2. CloudShell 利用パターン

最近のアップデートにより、AWS CloudShell が特定の VPC およびサブネット内で利用できる ようになりました。これにより、ECS サービスやタスクと同一のサブネットやセキュリティグループに一時的にアタッチすることで、デバッグが容易になります。

ECS Exec 利用パターンと異なり、ECS 側の設定変更が不要です。しかし、CloudShell は永続ストレージをサポートしていないため、セッション終了後にホームディレクトリが削除されます。継続的にデバッグを行う場合は、この点に注意が必要です。

また、CloudShell は リージョン毎に実行環境の利用時間に関する上限 があります。アカウント全体で月 200 時間までの制限があり、上限緩和申請により月 1000 時間まで増やすことができます。利用においては、この制約内で運用できるか判断しましょう。


11. まとめ

いかがでしたでしょうか。

今回紹介したアーキテクチャパターンは、一般的な Web サービスを前提に ECS/Fargate を中心に据えた一例に過ぎません。実際のビジネスで活用する際には、これらのアーキテクチャを組み合わせながら利用することが多いでしょう。

また、これらのアーキテクチャは一般的によく採用される構成を汎化したものであり、ご自身のビジネス要件に合わせて取捨選択することがもっとも重要です。
自分たちのニーズと照らし合わせながら、ぜひ参考にしていただければと思います。


builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます

著者プロフィール

新井 雅也 (@msy78)
AWS Container HERO | 2021-2022 AWS APN Ambassador

2012 年、株式会社野村総合研究所に入社。入社以来、アーキテクト兼エンジニアとして、主に金融業界のお客様に向けたビジネス提案やシステム設計、開発、運用を担当。
2023 年 6 月、Synspective にジョイン。クラウドに関する技術力を活かしつつ、宇宙業界の発展に尽力している。

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する