AWS CopilotでBackend Serviceのサービスディスカバリーを有効にする

AWS CopilotのBackend Serviceでは、デフォルトの状態ではサービスディスカバリーが有効にならないようです。有効化するためにはコンテナ実行時にリッスンするポート番号を指定する必要があります。
2021.04.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンサル部のとばち(@toda_kk)です。

AWS Copilotは、Amazon ECSの導入を簡単にしてくれるツールです。

実行されるサービスは、インターネット経由で通信できるLoad Balanced Web Serviceと、VPC内部でのみ通信するBackend Serviceの2種類があります。

copilot svc initコマンドを実行するだけで初期設定ができるのですが、Backend Serviceの場合はデフォルトの設定ではサービスディスカバリーが有効になっておらずVPC内部での名前解決ができません。

そこで、Backend Serviceでサービスディスカバリーを有効にする方法を記載します。内容としては簡単なのですが、意外と日本語で書かれた記事がなかったため記録として残しておきます。

結論

方法1. 上記コマンドで生成されたManifestファイルにimage.port設定を追加する。

name: ${service name}
type: Backend Service

image:
  build: app/Dockerfile
  port: ${ポート番号} # ←ここを追加する

cpu: 256
memory: 512
count: 1
exec: true

方法2. DockerfileにEXPOSE命令を追加する。

EXPOSE ${ポート番号}

解説

先日の弊社主催のイベントで登壇した際もちらっと紹介したのですが、設定内容についてもう少し詳しく解説してみます。

ECS on Fargateにおけるサービスディスカバリーの仕組み

まず、Amazon ECSでサービスディスカバリー(マネジメントコンソール上は「サービス検出」と表記されている)の仕組みとしては、AWS Cloud Mapを利用しています。これは、VPC内部でプライベートな名前空間を作成して管理するサービスであり、裏側ではRoute 53の設定を動かしています。

ECSでコンテナの実行基盤としてFargateを選択する場合、ネットワークモードはawsvpcで固定となります。

そして下記のAWS公式ドキュメントにあるようにawsvpcでサービスディスカバリーを有効にするためにはコンテナのポート番号を指定する必要があります。

サービス検出 では、awsvpc、bridge、host のいずれかのネットワークモードをタスクで指定する必要があります (none はサポートされていません)。 サービスタスクで指定されたタスク定義が awsvpc ネットワークモードを使用する場合、各サービスタスクで A レコードまたは SRV レコードを組み合わせて作成できます。SRV レコードを使用する場合、ポートが必要です。

ポート番号の指定

Copilotでは、Manifestファイルのimage.portの項目でコンテナを公開するポート番号を指定できます。

また、Copilot公式のドキュメントにある通り、svc initコマンドを実行する際に指定したDockerfileにEXPOSE命令が設定されている場合、Copilotではポート番号をパースしてManifestファイルに追加してくれます。

The port exposed in your Dockerfile. Copilot should parse this value for you from your EXPOSE instruction.

なお、EXPOSEはDockerfile内でコンテナ起動時にリッスンするポート番号を指定する命令です。

svc initコマンドでBackend Serviceを初期化すると、デフォルトではなぜかimage.port項目が設定されていない状態になります。

そのため、サービスディスカバリーを有効にするためには、ManifestもしくはDockerファイルでポート番号を明示的に指定する必要があるようです。

以上、コンサル部のとばち(@toda_kk)でした。