Search code examples
amazon-web-servicesaws-cloudformationamazon-ecsamazon-route53service-discovery

CloudFormation: Access PrivateDnsNamespace as HostedZone


The documentation for ServiceDiscovery::PrivateDnsNamespace states that:

When you create a private DNS namespace, AWS Cloud Map automatically creates an Amazon Route 53 private hosted zone that has the same name as the namespace.

In CloudFormation, is there any way to access the created HostedZone (as a Route53::HostedZone) so I can add additional Route53:RecordSets to it?

  • Is the ID the same?
  • Can I include a Route53::HostedZone with the same name to get the right ID?
  • Is there some other trick?

For example, I'd like to expose my RDS and ElastiCache (Redis) instance at private DNS entries. I realize this could be the XY problem, but I'm accessing these systems at standard locations in my legacy code and am trying minimize the customization (and thus potential bugs) in my first ECS attempt.

WARNING: While AWS Service Discovery strategies can be used to expose services like DB and RDS, there are several qualifications:

  • AWS Service Discovery requires the syntax <name>.<namespace> so you can't simply expose the services at db and redis. Your best odds for a 'standard' domain is something like redis.local and db.local. While local is a reserved TLD, there's some hostility to its use.
  • RDS SSL certificates are tied to the RDS domain name and custom SSL certificates are not supported so you can't expose it at db.<mydomain>.com. If you don't use the RDS CNAME, you won't be able to connect to these instances over trusted SSL connection.

Solution

  • There's no way to access the created HostedZone in CloudFormation.

    Still, if you want to add additional records to this private zone you can use the AWS::ServiceDiscovery::Service and AWS::ServiceDiscovery::Instance resources.

    Basically, you need to create one service for your RDS instance and one service for your Redis instance. Then you create instances in your services.

    Example for RDS:

    RDSSDService:
      Type: AWS::ServiceDiscovery::Service
      Properties:
        DnsConfig:
          DnsRecords:
            - TTL: 60
              Type: CNAME
          NamespaceId:
            Ref: YourNamespace
          RoutingPolicy: WEIGHTED
        Name: my-rds-service # this will become the record name
        NamespaceId:
          Ref: YourNamespace
    
    RDSSDInstance: # If your RDS instance is in the same stack
      Type: AWS::ServiceDiscovery::Instance
      Properties:
        InstanceAttributes:
          AWS_INSTANCE_CNAME:
            Fn::GetAtt:
              - YourInstanceLogicalName
              - Endpoint.Address
        ServiceId:
          Fn::GetAtt:
            - RDSSDService
            - Id
        InstanceId: # this is optional
          Ref: YourInstanceLogicalName
    
    RDSInstance: # If referencing an existing instance
      Type: AWS::ServiceDiscovery::Instance
      Properties:
        InstanceAttributes:
          AWS_INSTANCE_CNAME: xyz.abc.us-east-1.rds.amazonaws.com # or with Fn::ImportValue
        ServiceId:
          Fn::GetAtt:
            - RDSSDService
            - Id
        InstanceId: xyz # this is optional