症状
AWS ECSでサービス間通信(=コンテナ間通信)をするためにサービスの検出(サービスディスカバリ)を設定したけど、上手く通信してくれない。
状況
- ECSでクラスターを作る時、あるいはタスク定義を作るときに、EC2タイプを選んだ。
- ローカルではコンテナ間通信できているのにアップしたらできないのは何で?
- タスク定義するとき、「ネットワークモード?何それ?適当にDefaultとかでいいでしょ」
みたいな状況。
通信できなさすぎて何度もクラスターとかタスク定義とかサービスとか作り直して、もう細かいことを説明しなくても大体分かる人向け。
原因
タスク定義を作成するときのネットワークモードをawsvpc
以外にしていると、サービスディスカバリはDNS(=Route 53)にA
レコードではなく、SRV
レコードを作る。
サービスタスク定義が bridge または host ネットワークモードを使用する場合、SRV レコードのみがサポートされる DNS レコードタイプです。各サービスタスクの SRV レコードを作成します。SRV レコードのコンテナ名とコンテナポートの組み合わせをタスク定義から指定する必要があります。
サービス検出 - Amazon Elastic Container Service の中ほどより
だから、SRVレコードから上手くIPを引っ張ってくるような作り方をしないと、ただ単に問い合わせしただけでは解決してくれない。
例:ECS Service Discoveryを試してみる - Qiita
(IPを見つけるためにDNSレコードを手動で辿って行っている。アプリで自動化するならそんな感じの対策が必要と思われる。)
ネットワークモードをawsvpc
にすると、
サービスタスク定義が awsvpc ネットワークモードを使用する場合、各サービスタスクに A または SRV レコードを自由に組み合わせて作成できます。SRV レコードを使用する場合、ポートが必要です。
サービス検出 - Amazon Elastic Container Service の中ほどより
ということで、サービスを作成するときの「サービスの検出」でA
レコードが選べるようになるからそれを選ぶと普通に一発で名前解決をして通信できるようになる。
ちなみに、クラスターを作る時とタスク定義を作るときにデータプレーンとしてFargateを指定するように作っていくと、ネットワークモードは勝手にawsvpc
になるので、サービス作るときに「サービスの検出」で自然とA
レコードが選べるようになるってわけ。
よく考えたら・・・
「サービスディスカバリやってみた」的な記事はほぼ全部Fargate使ってるから、「ほら、簡単でしょう?」みたいなことしか書いていない。
自分は「EC2の方が実体が見えて分かり良いでしょ!」みたいに考えて勝手にEC2タイプで進んでしまったので、なぜ自分はできないのか気づくのに時間がかかった。
同じように苦しむ人が成仏できますように・・・
その他
↓ここにコンテナ間通信のやり方を3通り書いてくれている。
VPC 内の Amazon ECS サービス間のネットワーキング - Amazon Elastic Container Service