Amazon ECSの新ネットワーク機能”Service Connect”をAWSマネジメントコンソールから設定してみた #reinvent

2022.12.07

prismatixのとばち(@toda_kk)です。

AWS re:Invent 2022にて、Amazon ECS Service Connectという新たな機能が発表されました。

マイクロサービスアーキテクチャなどの構成において、ECSサービス間の通信を簡単に設定できるようにしたアップデートとなっています。詳細については、下記の記事をご参照ください。

また、re:Invent 2022のBreakout Sessionにて、ECS Service Connectの特徴や仕組みについて解説されていました。下記の記事にて、セッションの内容をレポートしておりますので、併せてご参照いただけますと幸いです。

本記事では、アップデートのアナウンスと共に公開されたAWS公式ブログを参照しつつ、実際にAWSマネジメントコンソールからECS Service Connectの設定を試してみます。

新UI(v2)に「名前空間」が追加されている

ECS Service Connectの仕組みとして、AWS Cloud Mapを用いた名前解決をECSに統合した形で設定できるようになっています。

AWSマネジメントコンソールでは、新しいUI(v2)を利用している場合に「名前空間(Namespaces)」という項目が増えており、ここにはCloud Mapで作成しているリソースがそのまま表示されるようです。

ECS Service Connectでは、Cloud Mapの名前空間をECSサービスと関連づけることで、ECSサービス間の通信を実現できます。よって、ELBによる通信の制御やAWS App Meshなどサービスメッシュの用意が不要というわけです。

ECSサービスの設定項目が追加されている

今回のアップデートにより、ECSサービスの設定項目としてService Connectの設定が追加されています。

AWSマネジメントコンソールの新しいUI(v2)では、下記のような画面表示となっています。

UIの表示が若干崩れている気もしますが、気にせず行きましょう

設定内容として、下記の3点が表示されています。

  • Service Connectの設定
  • 名前空間
  • ログ出力

Service Connectの設定

Service Connectの設定には、「クライアントモード」と「クライアントサーバーモード」の2種類があります。

日本語のAWSマネジメントコンソール上は「クライアント側のみ」「クライアントとサーバー」という表記になっており、またAWS公式ドキュメント上は「client service」「client-server service」という表記になっています。

表記揺れはありますが、Service Connectを通じてエンドポイントに対してリクエストするクライアントとなるECSサービスは前者を設定し、エンドポイントを提供しクライアントからリクエストを受け付けるサーバーとなるECSサービスは後者を設定します。

ここで、後者の「クライアントとサーバー」としてECSサービスを設定する際には、指定するECSタスク定義の中でポートマッピングに「名前」を設定する必要があります。

特にAWS CLIや、CloudFormationなどのIaCツールを用いて設定する際にはご注意いただきたいのですが、単純にECSタスクにポートマッピングを設定するだけでは不十分です。

また、ポートの「名前」はAWSマネジメントコンソールでも旧UI(v1)の場合には表示されない設定項目であるため、ECSタスク定義をJSON形式で編集するか、新UIに切り替える必要があります。

名前空間

前述の通り、Service ConnectではCloud Mapの名前空間を利用する仕組みになっています。同一の名前空間の内部において、名前解決によるECSサービス間の通信が実現できます。

Service Connectを利用する際には、複数のECSサービス(クライアント/サーバー)において同一の名前空間を指定する必要があるため、ご注意ください。

ログ出力

Service Connectに関するログ出力の設定です。

Service Connectの仕組みとして、ECSタスクの中で、タスク定義で指定したコンテナとは別にService Connect agentと呼ばれるコンテナが立ち上がります。これはEnvoyを含んだSidecarコンテナとなっており、Service Connectを有効化したECSサービスはEnvoyをプロキシとして通信が制御されます。いわばサービスメッシュと同じような通信経路となるわけです。

つまり、このログ出力の設定は、Envoyを含むService Connect agentのログをどのように出力するのかという設定になります。

出力先には、下記を指定できます。

  • CloudWatch Logs
  • FireLens経由で下記にエクスポート
    • Kinesis Data Firehose
    • Kinesis Data Streams
    • OpenSearch
    • S3

具体的な設定手順

さて、いよいよ実際にService Connectを設定してみます。具体的な手順としては下記のようになります。

  1. Cloud Mapから名前空間リソースを作成する
  2. 「ポート名」を設定したECSタスク定義を作成する(Service Connect設定で「クライアントとサーバー」を選択する場合)
  3. ECSサービスの新規作成または更新の際に、Cloud Mapの名前空間を参照してService Connectを設定する

まず、事前にCloud Mapから名前空間リソースを作成する必要があります。

なお、2022/12/7現在、ECSのコンソールから名前空間を作成するページへの動線は用意されていなさそうなので、AWSサービスの検索ボックスなどから直接Cloud Mapのコンソールに遷移して名前空間を作成します。「インスタンスの検出」は「API呼び出し」を指定すれば問題ないです。

名前空間を作成したら、次にECSサービスで指定したいECSタスク定義を作成します。今回は「クライアント側のみ」「クライアントとサーバー」の両方でECSサービスを作成してみたいので、「ポート名」を設定したECSタスク定義を作成します。

続いて、ECSサービスを作成してService Connectの設定をします。

「クライアント側のみ」のECSサービスの場合には、ポートの設定が特に必要ないため、名前空間を指定するのみで問題ありません。

「クライアントとサーバー」のECSサービスの場合には、名前空間に加えて、名前解決による検出名やDNSを設定する必要があります。

ここで、前述のECSタスク定義で指定した「ポート名」が「ポートエイリアス」として表示されているのがわかります。クライアントから指定するサーバーのエンドポイントとしては、通常は{discovery-name}.{namespace}といった形式になります。

例えば上図の例では、名前空間(namespace)はtest-namespaceであり、検出名(discovery name)はnginx-80-tcpとなっているため、クライアントからは`http://nginx-80-tcp.test-namespace:80`と指定することでサーバーとなるECSサービスに対してリクエストを送信できます。

ちなみに、実際に起動したECSタスクを確認してみると、前述の通りタスク定義で指定したコンテナとは別にecs-service-connect-xxxxxxxといった名前のコンテナが立ち上がっていることが確認できます。

また、Cloud Mapのコンソールから名前空間の詳細を確認してみると、サーバー側で指定していたポートマッピングの設定がサービスとして関連づけられていることがわかります。この辺りは、既存のECSサービス間通信のための機能であるサービス検出(Service Discovery)と同様の仕組みになっているようです。

動作確認

では、上記の設定でECSサービス間通信が実現できているのか、動作確認をしてみます。

なお、以降の内容は、AWS CDKでService Connectを設定する下記の記事とほぼ同様のものになっておりますので、そちらも併せてご参照ください。

動作確認の手順としては、クライアント側のECSサービスに対してECS Execで接続した後、サーバー側のECSサービスに対してcurlコマンドでリクエストを送信してみます。

サーバー側への疎通確認

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.

Starting session with SessionId: ecs-execute-command-xxxxxxxxxxxxxxxxx
# curl http://nginx-80-tcp.test-namespace:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

問題なく名前解決できていることがわかります。ちなみに、仕組みとしては/etc/hostsにDNSを書き込んで実現しているようです。

/etc/hosts の内容

# cat /etc/hosts
127.0.0.1 localhost
10.1.0.222 ip-10-1-0-222.ap-northeast-1.compute.internal
127.255.0.1 nginx-80-tcp.test-namespace
2600:f0f0:0:0:0:0:0:1 nginx-80-tcp.test-namespace

既存のECSサービス間通信の課題を解決するための新機能

上述のBreakout Sessionにて、ECS Service Connectは既存のECSサービス間通信(ELB、Service Discovery、App Mesh)における課題を解決するために開発された機能だと説明されていました。

実際に試してみた通り、ECSサービス間通信を実現するために必要なインフラリソースは少なくて済む上に、Envoyが通信に挟まることで通信のロギングやメトリクスを取得しやすい機能となっています。

App Meshと同じくEnvoyを含めた形でマネージドとなっているため、具体的な設定値などを制御できるわけではありませんが、これからECSを利用する場合はもちろん、既に多数のECSサービスを動作させている環境においてもService Connect利用を検討する価値は十分にあるのではないかと感じます。

今後もECSのアップデートに注目していきたいと思います。

以上、prismatixのとばち(@toda_kk)でした。