Claus Agerskov
Claus Agerskov

Reputation: 13

AWS CDK pipeline with ECS service discovery as well as Route53 Cname records

I am building a pipeline with three stacks in AWS CDK (python), a vpc stack, a database stack, and an application/ecs service and container stack. I need to have be able to create route53 cname records that connects a record name e.g. db.domain.com to a database dns, as well as service discovery records that connects a record name e.g. serviceA.domain.com to an ECS service dns.

I am only able to do one of these currently, either by creating a private dns namespace that autocreates a route53 hosted zone that I am unable to add cname records to, because I don't know its id, or I can create a route53 hosted zone which I am unable to create records for ECS services in, because I don't know their dns's/ips.

How do I achieve both of these objectives at the same time in the AWS CDK?

Possibly another way to put the question: How do I add CName records to a private hosted zone that is autocreated by CloudMap when creating a private dns namespace in AWS CDK?

The following approach to getting the hosted zone fails, either during deployment if I don't add vpc_id (because it returns DUMMY as hosted zone id) or when running cdk synth if I do add vpc_id with the error:

jsii.errors.JSIIError: Cannot determine scope for context provider hosted-zone.

This usually happens when one or more of the provider props have unresolved tokens

aws_route53.PrivateHostedZone.from_lookup(
    self, 
    id="zone", 
    domain_name="domain.com", 
    private_zone=True, 
    vpc_id=vpc.vpc_id 
)

Upvotes: 1

Views: 1997

Answers (1)

LRutten
LRutten

Reputation: 1902

So from your comments a assume you have a container service and want private access to that container service.

To expose the service using private dns you have two options. Firstly, you can create a cloud map namespace (e.g. example.local) and create a cloudmap service (e.g. my-service) under than namespace and link it to the ECS service. You can do that using CDK. The resulting record will be my-service.exampme.local. To connect to for example a database, add a cloud map service like specified in the CDK docs:

import * as cdk from '@aws-cdk/core';
import * as servicediscovery from '../lib';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-servicediscovery-integ');

const namespace = new servicediscovery.PublicDnsNamespace(stack, 'Namespace', {
  name: 'foobar.com',
});

# this is where the interesting stuff happens.
const service = namespace.createService('Service', {
  name: 'foo',
  dnsRecordType: servicediscovery.DnsRecordType.CNAME,
  dnsTtl: cdk.Duration.seconds(30),
});

service.registerCnameInstance('CnameInstance', {
  instanceCname: 'my-database.rds.region.amazonaws.com',
});

app.synth();

https://docs.aws.amazon.com/cdk/api/latest/docs/aws-servicediscovery-readme.html

The second way to do it is to add a load balancer in front of your service and create a hosted zone yourself and add a DNS record pointing to that load balancer. CDK has constructs available for that.

    // Create a load-balanced Fargate service and make it public
    new ecs_patterns.ApplicationLoadBalancedFargateService(this, "MyFargateService", {
      cluster: cluster, // Required
      cpu: 512, // Default is 256
      desiredCount: 6, // Default is 1
      taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample") },
      memoryLimitMiB: 2048, // Default is 512
      publicLoadBalancer: false // Default is false
    });

Snippet taken from an AWS tutorial Then simultaneously create another record in this hosted zone for your DB as you normally would.

Edit: regarding your snippet to get the zone, you need to add the construct to a stack for it to work. Also make sure you're on the latest CDK version. The latest version synthesizes iteratively. The first time will resolve DUMMY but the next it somehow does resolve to the right id for me. I did use the Hostezone construct though, not the PrivateHostezone.

Upvotes: 1

Related Questions