ECS マイクロサービスアーキテクチャ検討

ざっと設計
あたらしいし、いいとこどりっぽいService Connectでいいやろとおもってたけど、
Blue/Greenできないとかいろいろ融通効かないところがありそうだった
よって、サービス間の繋ぎ込みは一周まわって、結局ALBがよさそう?
- リポジトリ:分割
- CI/CD:分割
- ECS:サービスでフロントとその他バックエンド機能それぞれで分割
- DB:単独?(ECと冗長構成)
※参考

どのようにマイクロサービスを組むか(どのような区分けにするか)
ドメイン開発駆動/境界づけられたコンテキスト
1. 境界づけられたコンテキストを定義
ECSの機能(例: 文書管理、アクセス制御、ワークフロー管理)をそれぞれ「境界づけられたコンテキスト」として分ける。
各コンテキストの役割や責任を明確化。
2. マイクロサービス化
各「境界づけられたコンテキスト」を独立したマイクロサービスとして実装。
サービスごとに独自のデータベースとロジックを持たせる。
サービス同士はAPIやメッセージキューを利用して連携。
3. コンテキスト間の関係を設計
境界づけられたコンテキスト間のデータの流れや依存関係を整理(例: 顧客-供給者関係)。
連携方法として、REST API(同期)やKafka(非同期)を採用。
4. 独立したチームを編成
各「境界づけられたコンテキスト」を担当するチームを編成し、独立して開発を進められるようにする。

構成図のレビュー
- ALBを各サービス上にのる / BFF(Backends for frontends) GraphQL(Ferderation) で各種APIつなぎこみ
- リポジトリは1つと言うパターンもあり(フロントバック同じ)
- DBはインスタンスからわけることもある
つなぎこみはALBかなと思ってたけどGraphQLから考えると、AppSyncも浮上。参考資料でほぼでてこなかったけど、ダメな理由とかあるんだろうか。
↓と思い、調査
※ ALBがベストな理由
AppSyncやAPI Gatewayが今回の構成案に出なかった理由は、ECSとFargateが前提であり、フロントエンドとバックエンドの接続を直接ECSサービスで完結する方が合理的であるためです。ただし、要件やユースケースによっては、これらのサービスを使うケースも十分に考えられます。以下に、それぞれが考慮されなかった理由を詳しく説明します。
- API Gateway
採用しなかった理由:
• API Gatewayは、主にLambdaやHTTPバックエンドと統合する場合に便利ですが、ECSサービスとの統合では追加のオーバーヘッドが発生します。
• ECSサービスをバックエンドに設定する際、API GatewayはVPCリンクを使用して通信を中継します。これにより、通信の遅延やコストが増加する可能性があります。
• ECS間の通信やロードバランサーを利用した構成に比べて直接的な接続が難しくなります。
• ECSの特性上、ALBを利用することでロードバランシングや認証をシンプルに実現でき、API Gatewayを挟む必要がありません。
採用する場合のメリット:
• マイクロサービスごとに認証やリクエスト制御を細かく設定できる。
• REST API設計に適しており、サービスのエンドポイントを簡単に統合可能。
- AWS AppSync
採用しなかった理由:
• AppSyncはGraphQLベースのAPI構築に特化しており、データソース(DynamoDBやRDS、Lambdaなど)を統合するケースに最適です。
• 今回の要件では、バックエンドがECS上に構築されており、AppSyncは直接の接続に適していません。
• AppSyncを使用する場合、ECSサービスを直接GraphQLデータソースとして設定するのが難しく、Lambdaや別の中継層が必要になります。
採用する場合のメリット:
• フロントエンドで複数のバックエンドデータを1つのGraphQL APIに統合可能。
• サブスクリプション(リアルタイム更新)や高度なクエリが必要な場合に便利。
今回の構成でALBを優先した理由
-
ECSに最適化されている: ALBはECSとの統合が容易で、特にFargateのようなサーバーレスコンテナ環境では、シームレスなロードバランシングとヘルスチェックを提供します。
-
ブルーグリーンデプロイに適している: ECSのブルーグリーンデプロイでは、ALBをターゲットグループの切り替えに利用でき、トラフィック制御がシンプル。
-
コストとパフォーマンス: ALBを使う場合、API GatewayやAppSyncに比べて追加の通信オーバーヘッドやリクエストごとの課金が少ない。
AppSyncやAPI Gatewayを採用するべきケース
-
API設計の柔軟性:
• マイクロサービスを統合し、統一されたAPIインターフェースを提供したい場合。
• クライアント側で柔軟にデータを取得するGraphQLが必要な場合。 -
バックエンドが多様化している場合:
• ECSだけでなく、Lambda、DynamoDB、RDSなど異なるバックエンドサービスを統合したい場合。 -
認証やアクセス制御が複雑な場合:
• API GatewayのIAM統合やCognito認証を活用することで、きめ細かいアクセス制御を実現できる。 -
フロントエンドとバックエンドの間で非同期通信が必要な場合:
• AppSyncのリアルタイム更新やAPI Gatewayのリクエスト・レスポンス構造が有利。
結論
現状の要件では、ECSとFargateにALBを組み合わせる構成が最もシンプルでコスト効果が高いです。ただし、認証やAPIの統合、柔軟性の観点で追加の要件が出てくる場合、AppSyncやAPI Gatewayの採用を検討すべきです。
※ 各バックエンドの前段にそれぞれ1つずつALBをかまして、AppSync(GlaphQL)は?
各バックエンドの前にALBを配置する構成を考えると、AppSync (GraphQL) を採用するのは非常に有力な選択肢になります。以下にその理由と利点を詳しく説明します。
- ALB + AppSync (GraphQL) の相性の良さ
GraphQLの強み:
• AppSyncを使うと、クライアントは必要なデータだけを取得できるため、複数のバックエンドサービスからのデータを1つのAPIで集約し、効率的に利用できます。
• ALBで各バックエンドを分離している場合、AppSyncをフロントエンドとバックエンドの統合ポイントとして活用することで、通信が統一されます。
ALBの役割:
• 各バックエンドのALBが、スケールやヘルスチェックなどを担当します。
• AppSyncがALBを介して各バックエンドサービス(ECSタスク)にアクセスできるようにすることで、バックエンド間の管理が簡素化されます。
- AppSync の利点
2.1. 単一のGraphQLエンドポイント
• 複数のバックエンド(例: ユーザー管理、商品データ、注文管理)をGraphQLで統合し、フロントエンドは単一のエンドポイントに問い合わせるだけで済みます。
• AppSyncは各GraphQLリゾルバを使って、ALBを経由して各バックエンドにリクエストを送信できます。
2.2. データの柔軟な取得
• クライアント側が1つのリクエストで複数のバックエンドから必要なデータを統合して取得可能。
• 例: 商品情報とその在庫状況を1回のクエリで取得。
2.3. リアルタイム対応
• サブスクリプション機能を利用すると、バックエンドでの更新(例: 新しい注文の作成)をリアルタイムでフロントエンドにプッシュできます。
2.4. 認証とアクセス制御
• AppSyncにはCognitoやIAMを用いた認証・認可が組み込まれており、フロントエンドからのアクセス制御が簡単になります。
- ALB + AppSync 構成のユースケース
• マイクロサービス:
各バックエンド(サービス)が独立している場合、ALBでリクエストをルーティングし、AppSyncがそれらをGraphQL APIとして統合。
• フロントエンドの効率化:
フロントエンド開発者は、バックエンドの構造を意識することなくGraphQLクエリで必要なデータを取得。
• データ統合が必要なケース:
複数のバックエンドからデータを集約し、1つのレスポンスとして提供する。
- 考慮すべき点
4.1. オーバーヘッド
• AppSyncはGraphQLの利便性を提供しますが、ALBとバックエンド間の通信が増えるため、ネットワークやリソース消費が増加する可能性があります。
• リゾルバの設計が複雑になると、AppSyncのパフォーマンスに影響する可能性があるため、リゾルバを適切に設計する必要があります。
4.2. コスト
• AppSyncのリクエスト数に応じた課金が加算されるため、ALBとAppSyncの組み合わせがフロントエンドの負荷に見合うコスト効率か検討が必要です。
4.3. 開発の複雑さ
• GraphQLスキーマとリゾルバを設計・実装する必要があるため、追加の開発コストが発生します。
- 構成例
- フロントエンド → AppSync (GraphQL) → 各バックエンドALB → ECSタスク
• 各バックエンドのALBは特定のサービス(例: ユーザー管理、商品管理)にルーティング。
• AppSyncのリゾルバがALBのエンドポイントにアクセス。
- リアルタイム通知
• AppSyncのサブスクリプションを使って、注文状況の更新や在庫ステータスをフロントエンドにプッシュ。
結論
バックエンドごとにALBを配置する構成では、AppSyncを活用することで、以下のメリットを最大化できます:
• フロントエンドの開発効率が向上。
• 複数バックエンドの統合が容易。
• リアルタイムデータ更新が可能。
GraphQLの柔軟性を求める場合、AppSyncは強力な選択肢です。バックエンドが単一機能で完結する場合は、ALBだけでも十分ですが、データ統合やフロントエンドの利便性を重視するならAppSyncは非常に適しています。

ここの通信を検証する
フロントエンド→各種バックエンド(API)

大まかに手順
-
フロントエンドつくる
-
バックエンド作る(API化して2つ作っておく)
-
ビルドしてECRへプッシュ
-
TerraformでVPC、ALB、ECS構築
※ APIつなぎこみの検証なので、このALBにフロントをまぜこみ&パブリックのみ。
※ 本来であればパブリックにALB、プライベートにフロント、ALBたててバックエンドと繋ぐ。 -
ALBにアクセス
-
成功すればこんなかんじ(Hello from Service X がバックエンドから取得してる部分)
※リソースマップ
GitHub
とりあえず動くだけのコード(それ以上の精査なし)

※なんでLambdaじゃだめなの?
ECS (Elastic Container Service)がWebサービスのバックエンドで採用される理由に対し、Lambdaではダメな理由は以下のように考えられます。
ステートフルな処理に向いていない: Lambdaは、主にステートレスな処理に最適化されています。つまり、リクエストごとに独立して動作することを前提にしています。対して、ECSはステートフルなアプリケーション(状態を持つアプリケーション)や、複雑なサービス間の通信が求められるアーキテクチャに適しています。
長時間実行されるプロセスのサポート: Lambdaには最大実行時間(15分制限)があり、長時間実行されるバックエンドプロセスには向いていません。ECSは、長期間にわたって安定して実行し続けるサービスやタスクに適しており、特にバックエンドの常駐プロセスや継続的な処理に向いています。
複雑な依存関係の管理: 複数のサービスやライブラリが密接に連携するアーキテクチャでは、ECSの方が適しています。Lambdaは短期的なタスクに適しており、複数の依存関係を扱う大規模なバックエンドシステムには、コンテナ化されたアーキテクチャであるECSの方が管理が容易です。
高いカスタマイズ性とコントロール: ECSは、インフラや設定の柔軟性があり、必要に応じてサービスを細かく制御できます。Lambdaではその柔軟性が限られており、特にエラー処理やデバッグ、特定の環境設定をカスタマイズする場面ではECSの方が優れています。
料金体系の違い: Lambdaはリクエストごとに課金されますが、ECSはタスク単位やコンテナ単位でリソースが管理されるため、大量のリクエストや長時間にわたる処理が必要な場合、ECSの方がコスト効率が良い場合があります。
Lambdaは短期間の処理やイベント駆動型アーキテクチャには非常に便利ですが、複雑なバックエンド処理やステートフルなサービスには、ECSがより適しています。
※AWS コンテナ本 P281
サービス検出(名前空間・Cloud Map)の設定をしていた。
フロントとバックの間にALBをかましてるし、サービス検出は「必須ではない」と書いてあるので、本検証とおなじくパスパターンでサービス間通信してると思ったけど、そのあたりの記述がみつからず。フロントのコードも見つけられず、結局ここはよくわからずだった。