ECSのサービス検出を理解する

記事タイトルとURLをコピーする

こんにちは
技術課の山本です

雪が続くと夏山が恋しくなりますね

天狗岳(八ヶ岳)

そして久保史緒里さんオールナイトニッポンのメインパーソナリティー就任おめでとうございます

さて本題です
ECSのサービス検出機能(サービスディスカバリ)について
改めて理解を深めるためにブログを書くことにしました

ECS のサービス検出機能とはなにか

ドキュメント
サービス検出 - Amazon Elastic Container Service

ECSのサービス検出機能を使うとECSクラスターの中にある各サービス間の名前解決が可能になります
パブリックではなくプライベートな名前空間での名前解決が可能です

  1. ECSのサービス検出機能はECSクラスターの中にあるサービスにDNS名を付与します (xxxx.service など)
  2. サービス内のタスクの増減に応じてDNS名に対応するレコード値(IPアドレス)を自動更新します
  3. レコードはRoute53 のプライベートホストゾーンを使って内部的に管理しています

ECSのサービス検出機能が登場する前のサービス間通信

内部用のロードバランサー(ELB)を配置して ロードバランサー(ELB)のDNS名に向けて通信します

サービス検出機能が登場する前

ECSのサービス検出機能が登場した後のサービス間通信

サービスの持つ DNS 名に向けて通信します

ECSのサービス検出機能が登場した後

使ってみる

作成

前提としましてawsvpc ネットワークモードのFargateタスクを使用してサービスを作成します
クラスターにサービスを作成する際にサービス検出の設定があります

ピンク線の箇所を設定しました
このサービスは「サービスの検出名.名前空間名」すなわち「yamamoto-test-service-a.service」というDNS名になります
TTLは5分としています

サービスを作成した際にサービスの検出機能も作成されていることが確認できます

確認

Route53

サービスの作成時に「名前空間名」に指定したプライベートホストゾーン(service)が出来ていました
プライベートホストゾーンにはサービスを作成した VPC が紐付いています
サービスのタスク数を 2つに設定しているため 「yamamoto-test-service-a.service」のAレコード が 2つあります
値はタスクに割り当たっているプライベートIPアドレスになっています
ルーティングポリシーは「複数値回答(MultiValue)」になっています

試しに サービスのタスク数を 1 に減らすと Aレコードも 1つになりました

試しに サービスのタスク数を 20 にしてみると Aレコード も20個になりました

ルーティングポリシー:「複数値回答(MultiValue)」とは?

上の例には「yamamoto-test-service-a.service」のAレコードが 20 あります
このAレコードに名前解決(dig)のリクエストを行うと Route53 は ランダムに選択した 8つのレコードを返却します

試しに名前解決(dig)のリクエストを行うと 8つ返ってきました
クライアント(コンテナ)はこの 8つのIPアドレスのどれかに接続することになります

TTL(300秒)を待ってもう一度実行すると中身が変わっていました
ランダムに選択した 8つレコードを返却していそうです

タスク数を 4つに減らすと 4つの Aレコード全てが返ってきました
8つ以下の場合は全てのレコードを常に返す仕様になっています

ALB はラウンドロビンのアルゴリズムでターゲットにルーティングするのに対し
ECSのサービス検出機能は ランダムに 最大8個の IPアドレスを返すという動きをする点が少し異なりますね
ただしどちらも可用性の高い仕組みですので運用上あまり困ることは無さそうです

参考: 複数値回答ルーティングポリシーとシンプルルーティングポリシーの違い | AWS re:Post

クライアントが複数値回答ルーティングを使用して DNS リクエストを行うと、Route 53 は DNS クエリに応答して特定のドメイン名の正常なレコードを最大 8 個ランダムに選択して返します

複数値回答ルーティングは、複数の IP アドレスに DNS レスポインスを分散します。リゾルバーがレスポンスをキャッシュした後でウェブサーバーが使用できなくなると、クライアントはダウンタイムを避けるためにレスポンス内の他の最大 8 個の IP アドレスを試すことができます

Route 53 は 8 個のレコードをランダムに選択します。ドメイン名に対して dig (Linux の場合) または nslookup (Windows の場合) を複数回実行すると、IP アドレスのローテーションに気付く場合があります。このローテーションで可用性が向上し、ある程度のロードバランシング機能が提供されます。オペレーティングシステムでは、Route 53 ではなく、キャッシュされたレスポンスで、このラウンドロビン DNS を実行します

VPC

サービスを作成した VPC が Route53のプライベートホストゾーンに紐付いているためVPC 内の他サービス(EC2,他のECSクラスター内のサービスなど)からも名前解決可能になっています
EC2 から名前解決してみると 名前解決出来ていました

VPC の DNSに関する設定が 2つとも有効になっている必要がある点にはご注意ください

参考: VPC の DNS 属性 - Amazon Virtual Private Cloud

AWS Cloud Map

サービスの作成時に「名前空間名」に指定した名前空間(service)が出来ていました

名前空間

名前空間の中にサービスが 1つ作成されていました

ECSのサービス検出機能と連動して動いているサービスなので普段ユーザーはあまり意識しなくて良さそうです
ただし環境を削除する際にはAWS Cloud Mapのリソースを個別に削除しないといけません

参考:サービス検出 - Amazon Elastic Container Service

サービス検出を使用するときに作成される AWS Cloud Map リソースは、手動でクリーンアップする必要があります。

ロードバランサー(ELB)から ECSのサービス検出に移行する際に注意すること

ECSのサービス検出は名前解決の仕組みを提供しているため ロードバランサー(ELB)の代替にはなりません
例えばALBのリスナールールを使用してパスベースルーティング等をしている場合には ALBを使用し続けたほうが良いでしょう
もっとも気を付けるべきはヘルスチェックです
ELB はヘルスチェックに不合格になったターゲット(タスク)にはルーティングしません ※例外として全てのターゲットが不合格のときにはルーティングします
同等のことを実装するためにはECSのタスク定義にコンテナのヘルスチェックを定義しておきましょう
コンテナのヘルスチェックに失敗するとサービスと紐づくタスクをECSが自動削除する仕組みです ※後日ブログ記載予定です

参考:タスク定義パラメータ - Amazon Elastic Container Service

※ルーティングポリシー「複数値回答(MultiValue)」の Aレコードは
タスクの増減に応じて ECSのサービス検出機能が都度作成・削除するため
このAレコードにヘルスチェックを設定するのは避けましょう

他、制約

ドキュメントから本記事内では解説しなかった制約を抜粋しておきます
SRVレコードを使用した構成は今後追記するかもしれません(今回は割愛)

  • サービス検出では、awsvpc、bridge、host のいずれかのネットワークモードをタスクで指定する必要があります (none はサポートされていません)
  • サービスタスクで指定されたタスク定義が awsvpc ネットワークモードを使用する場合、各サービスタスクで A レコードまたは SRV レコードを組み合わせて作成できます。SRV レコードを使用する場合、ポートが必要です
  • サービスタスクで指定されたタスク定義が bridge または host ネットワークモードを使用する場合、SRV のレコードのみがサポートされる DNS レコードタイプです。各サービスタスクの SRV レコードを作成します。SRV レコードのコンテナ名とコンテナポートの組み合わせをタスク定義から指定する必要があります。
  • すべてのレコードが異常である場合、Route 53 は DNS クエリに最大 8 つの異常なレコードを返します。
  • サービス検出では、Classic Load Balancer の使用はサポートされていません。
  • サービス検出は、最初にサービスを作成するときにのみ設定できます。サービス検出を初めて構成するための既存のサービスの更新、または現在の構成の変更はサポートされていません。

山本 哲也 (記事一覧)

カスタマーサクセス部のエンジニア。2024 Japan AWS Top Engineers に選んでもらいました。

今年の目標は Advanced Networking – Specialty と Machine Learning - Specialty を取得することです。

山を走るのが趣味です。今年の目標は 100 km と 100 mile を完走することです。 100 km は Gran Trail みなかみで完走しました。OSJ koumi 100 で 100 mile 砕け散りました。どこかで 100 mile やりたいです。

基本的にのんびりした性格です。座右の銘は「いつか着く」