🤩

ECS コンテナ間通信のベストプラクティス

2024/07/04に公開

こちらのAWS公式のドキュメントではECSコンテナ間通信のベストプラクティスとして、3つの方法が紹介されています。
自分の備忘録として、それぞれの特徴、どのような場面で使用するべきかまとめたいと思います。

サービス検出

特徴

サービス検出は、動的に変化するコンテナのIPアドレスを管理し、サービス間通信を行います。Amazon ECSでは、サービス検出のためにAWS Cloud Mapを使用します。Cloud Mapは、サービス名をIPアドレスにマッピングし、DNS名前解決を行います。

イメージ

引用元: https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/bestpracticesguide/networking-connecting-services.html#networking-connecting-services-direct

設定例

解説

  • exampleという名前空間がCloud Map上に作成され、app-exampleという名前で、サービスが紐づけられます
  • Route53ではプライベートホストゾーンexampleが作成され、レコードとしてapp-example.exampleが設定されます
  • ECSのコンテナからapp-example.exampleドメインに接続すると、このサービス検出が設定されたサービスに接続することができます

デメリット

  • サービス検出に関してのトラフィックのログが収集できません
    • これがどの程度のデメリットになるかは正直よくわかっていませんが、サービス検出を起因とした障害が起きた場合はトラブルシューティングが困難になる可能性があります

Service Connect

特徴

Service Connectは、ECSサービス間の通信を簡素化し、管理を容易にするための機能です。Service Connectでは、サービスのエンドポイントを定義し、そのエンドポイントを通じて通信を行うことができるため、サービスのアドレスやポート番号を直接管理する必要がなくなります。

イメージ


サービスへのエンドポイントに接続するための、プロキシが別途コンテナとして立ち上がるイメージです。
ポートでタスク内のコンテナに振り分けることができます。

設定例

クライアントとサーバー

クライアント側

解説

  • Cloud Map上にexampleという名前空間を先に作成しておきます
  • クライアントとサーバー
    • Service Connectの設定はクライアントとサーバーを選択します
    • 名前空間exampleにサーバー側のサービスをappとして登録します
    • サービスがデプロイされるとタスクの中にプロキシコンテナが立ち上がります
  • クライアント側
    • Service Connectの設定はクライアント側のみを選択します
    • 名前空間exampleを選択して、exampleにあるコンテナに接続できるようにします
    • サービスがデプロイされるとタスクの中にプロキシコンテナが立ち上がります
    • この例では http://app:4000 で接続することができます

クライアント側のhostsファイル

# cat /etc/hosts
127.0.0.1 localhost
10.20.10.30 ip-10-20-10-30.ap-northeast-1.compute.internal
127.255.0.1 app
2600:f0f0:0:0:0:0:0:1 app

appが登録されていることがわかります

デメリット

  • こちらに記載されている通り、Service Connect でサポートされるのは、ローリングデプロイを使用するサービスのみなので、Blue/Greenデプロイは使用できません
  • プロキシコンテナを立ち上げるためにリソースを追加する必要があるため、それに応じてコストが増えます

内部ロードバランサーの使用

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/interconnecting-services.html
English版のドキュメントだとなくなっているので、さっくり説明・・・

特徴

内部ロードバランサーは、サービス間のトラフィックを分散させ、負荷分散を行うために使用されます。ロードバランサーを内部的に使用して、コンテナ間接続を実現できます。

イメージ

引用元: https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/bestpracticesguide/networking-connecting-services.html

解説

  • ロードバランサーをサブネットに配置します
    • イメージ図ではサブネットとの間にありますが、実際はサブネットに属しています
  • ターゲットグループを作成して、サービスタスクのコンテナを紐づけます
  • コンテナには http://[ロードバランサーのドメイン名]:[ポート番号] で接続できます
  • 1つのロードバランサーで複数コンテナに振り分ける場合は、ポート番号が重複しないようにする必要があります

デメリット

  • 内部ロードバランサーの使用には追加のコストが発生します。

補足

こちらの方のようにサービス検出やService Connectの導入が難しい場面でロードバランサーを使うのは有効だと思います。
https://zenn.dev/red_frasco/articles/61b99d8388e51e

おまけ

localhostでの通信

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/fargate-task-networking.html

同じタスク内で起動しているコンテナはlocahostで接続できます。
もちろんポートは分ける必要があります。

まとめ

個人的な感覚としては

  • 基本的にサービス検出、Service Connectを使う
  • コストが気になったり、Blue/Greenデプロイをしたい場合はサービス検出を使う
  • サービス検出、Service Connectを使うことができない場面ではロードバランサーの使用を考える

という感じです。

Service ConnectがBlue/Greenデプロイに対応したら、サービス検出もほぼ使わなくてよくなりそうなので、今後のAWSの動向に注目です。

参考

参考にさせていただきました、ありがとうございます!

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/bestpracticesguide/networking-connecting-services.html

https://pages.awscloud.com/rs/112-TZM-766/images/20230126_26th_ISV_DiveDeepSeminar_ECS_Service_Connect.pdf

https://dev.classmethod.jp/articles/try-amazon-ecs-service-connect/

https://zenn.dev/red_frasco/articles/61b99d8388e51e

SMARTCAMP Engineer Blog

Discussion