先日AWS CDKでAmazon ECSの名前解決をAWS CloudMapに設定する方法を調べたのですが1週間くらいかかったので紹介します。
動機(Service Connectの落とし穴)
そもそも改造することになったECSは名前解決にService Connectを使っていました。AWS的にはメトリクス取得と機能が両立していてイチオシらしいのですが、実装に/etc/hosts
を使っていて、新しいサービスを追加したときに、既存サービスは再デプロイしないと新しいサービスの名前解決ができない、ということが分かりました1。
通常はそれでよいのでしょうが、今回は1つ共通リソースになっているコンテナが存在し、裏方のコンテナのデプロイにあわせて共通リソースコンテナを再デプロイしてしまうと既存の利用者に影響が出てしまう状態でした。
裏方コンテナのデプロイの時には、共通リソースコンテナは名前解決だけできれば良いため、Service Connectの利用をやめて、動的に名前解決のできるCloudMapの利用に切り替えました。
ECSのサービスでCloudMapを使うよう指定する
コードのスニペットではまず新しいCloudMapの名前空間を作って、それをECSのサービスに紐づける例を記載しています。CloudMapはCDKではservicediscoveryで呼び出せます。
// ポイントのみの記載のため、このままでは動きません。
import { aws_ecs as ecs } from 'aws-cdk-lib';
import { aws_servicediscovery as servicediscovery } from 'aws-cdk-lib';
// 新規にCloudMapのNameSpaceを作る場合のコード
const namespace = new servicediscovery.PrivateDnsNamespace(this, 'Namespace', {
name: 'domain.local',
vpc,
});
const service = new ecs.FargateService(this, 'Service', {
cluster,
taskDefinition,
// CloudMapとECSのサービスを紐づけるにはcloudMapOptionsを使う
cloudMapOptions: {
cloudMapNamespace: namespace,
name: "newone" //この例だと newone.domain.local になる
dnsRecordType: servicediscovery.DnsRecordType.A,
},
});
問題はこのとき既存のCloudMapの名前空間に追加したいときどうかけばよいか?がわからずはまりました2。
既存のCloudMapを指定してサービスを紐づける
1週間の調査と試行錯誤でわかったのは、servicediscovery.PrivateDnsNamespace
クラスにfromPrivateDnsNamespaceAttributes
メソッドがあるので、そこで既存のCloudMapを指定することができます。下記にコードスニペットを記載します。
// ポイントのみの記載のため、このままでは動きません。
import { aws_ecs as ecs } from 'aws-cdk-lib';
import { aws_servicediscovery as servicediscovery } from 'aws-cdk-lib';
// 既存のCloudMapをインスタンスにするコード。
const namespace = servicediscovery.PrivateDnsNamespace.fromPrivateDnsNamespaceAttributes(this, 'Namespace', {
namespaceArn: `arn:aws:servicediscovery:region:accountId:namespace/ns-xxxxxxxxx`,
namespaceId: "ns-xxxxxxxxx",
namespaceName: "domain.local",
});
const service = new ecs.FargateService(this, 'Service', {
cluster,
taskDefinition,
// CloudMapとECSのサービスを紐づけるにはcloudMapOptionsを使う
cloudMapOptions: {
cloudMapNamespace: namespace,
name: "newone" //この例だと newone.domain.local になる
dnsRecordType: servicediscovery.DnsRecordType.A,
},
});
なお、CDKでECSのサービス全体を立てるのは、参考文献6が分かりやすいと思うのでご紹介します(Service Connectのケースの書き方ですが、serviceConnectConfiguration
の設定の代わりにcloudMapOptions
を指定)。
どなたかのお役に立てば幸いです。