ECSサービス間通信にService Connectを試してみる
AWS re:Invent 2022で発表された機能で、ECSサービス間のネットワーク構築を容易にしてくれるものです。
今回は実際に使って使用感を確かめます。
概要図
クライアントにECS EXECし、サーバ(nginx)にリクエストを投げる
クラスタ作成
aws ecs create-cluster --cluster-name tutorial --service-connect-defaults-namespace=service-connect-local
最新版で試すこと
筆者環境の2.8.9
ではserviceconnect関連のオプションがなかった
この時点でクラスタに紐付いたnamespaceが確認可能
# 作成されたnamespaceを確認
aws ecs describe-clusters --clusters tutorial | jq -r '.clusters[].serviceConnectDefaults.namespace'
# namespaceを確認
aws servicediscovery --region ap-northeast-1 get-namespace --id <作成したnamespace>
サーバ側サービス作成
# サーバ側nginx作成
aws ecs create-service \
--cluster tutorial \
--service-name tutorial-server-service \
--task-definition <タスク定義> \
--desired-count 1 \
--launch-type FARGATE \
--platform-version LATEST \
--network-configuration "awsvpcConfiguration={subnets=[<サブネット>],securityGroups=[<セキュリティグループ>],assignPublicIp=ENABLED}" \
--service-connect-configuration '{
"enabled": true,
"namespace": "service-connect-local",
"services":
[
{
"portName": "nginx-80-tcp",
"clientAliases": [
{
"port": 80,
"dnsName": "nginx-80-tcp.service-connect-local"
}
]
}
]
}'
- awscliでのserviceconnect設定は以下を参考にした
- <ポート名>.<名前空間>のようなURLになる
- 上記の場合、
nginx-80-tcp.service-connect-local
でサーバにアクセスできる
- 上記の場合、
-
--service-connect-configuration
のservices
を入力することでエンドポイントを提供する(サーバになれる)- クライアントの場合は
services
を指定しなければOK
- クライアントの場合は
クライアント側サービス作成
aws ecs create-service \
--cluster tutorial \
--service-name tutorial-client-service \
--task-definition <タスク定義> \
--desired-count 1 \
--launch-type FARGATE \
--platform-version LATEST \
--network-configuration "awsvpcConfiguration={subnets=[<サブネット>],securityGroups=[<セキュリティグループ>],assignPublicIp=ENABLED}" \
--enable-execute-command \
--service-connect-configuration '{
"enabled": true,
"namespace": "service-connect-local"
}'
-
--enable-execute-command
でECS Exec可能にする
ECS Execしてcurlを打つ
クライアント側にECS Execし、/etc/hosts
を確認する。
# cat /etc/hosts
127.0.0.1 localhost
10.0.96.72 ip-10-0-96-72.ap-northeast-1.compute.internal
127.255.0.1 nginx-80-tcp.service-connect-local
2600:f0f0:0:0:0:0:0:1 nginx-80-tcp.service-connect-local
ループバックアドレスの127.255.0.1
にサイドカーのenvoyがいて、それ経由で通信するということでしょうか。
curlを打つと
# curl -v http://nginx-80-tcp.service-connect-local
* Trying 127.255.0.1:80...
* Connected to nginx-80-tcp.service-connect-local (127.255.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: nginx-80-tcp.service-connect-local
> User-Agent: curl/7.74.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< server: envoy
< date: Sun, 12 Mar 2023 01:25:44 GMT
< content-type: text/html
< content-length: 615
< last-modified: Tue, 13 Dec 2022 15:53:53 GMT
< etag: "6398a011-267"
< accept-ranges: bytes
< x-envoy-upstream-service-time: 0
<
<!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>
* Connection #0 to host nginx-80-tcp.service-connect-local left intact
のように通信が可能。
サーバ側のログを見て、アクセスログが出力されていればOK
注意
- 後からserviceconnectに登録したサーバコンテナを追加した場合、クライアントコンテナの再デプロイが必要となる
既存のタスクを解決して新しいエンドポイントに接続することはできません。このエンドポイントを解決して接続できるのは、同じ名前空間に Service Connect 設定があり、このデプロイ後に実行を開始した新しい Amazon ECS タスクだけです。例えば、クライアントアプリケーションを実行する Amazon ECS サービスは、接続先のサーバーのデプロイが完了した後に新しいタスクを開始する必要があります。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/service-connect.html
クラスメソッドさんの記事にもありました
- blue/greenデプロイは不可
Service Connect でサポートされるのは、ローリングデプロイを使用するサービスのみです。ブルー/グリーンおよび外部デプロイタイプを使用するサービスはサポートされていません。
まとめ
簡単に設定できたが、以下の考慮が必要だと感じた
- cloudmap、envoyへの理解が前提となる
- blue/greenデプロイなど、できないこともある
便利なのでぜひとも使いこなしたいところ