How do I use AWS Cloud Map to set up cross-account service discovery for ECS services?

5 minute read
1

I want to use AWS Cloud Map to set up cross-account service discovery for my Amazon Elastic Container Service (Amazon ECS) services.

Short description

Creating a private namespace in AWS Cloud Map, also creates an Amazon Route 53 hosted zone. Because the Route 53 hosted zone is associated with an Amazon Virtual Private Cloud (Amazon VPC), DNS records are discoverable. So, other AWS accounts and Amazon VPCs can't discover the Amazon ECS service through DNS.

Prerequisites:

  • Two Amazon VPCs in the same or different accounts with the required subnets, security groups, and non-overlapping CIDR.
  • Both Amazon VPCs using AmazonProvidedDNS, with the attributes enableDnsHostnames and enableDnsSupport turned on.
  • One Amazon ECS cluster.
  • The latest version of AWS Command Line Interface (AWS CLI) installed and configured with the appropriate permissions.

Note: If you receive errors when running AWS CLI, confirm that you're running a recent version of the AWS CLI.

Resolution

Important: The following steps use examples for the target Amazon VPC, the source Amazon VPC, and the Amazon ECS cluster. In the AWS CLI, replace the example values with your values.

  • The example Amazon ECS cluster example-cluster is in AWS account 1.
  • The example target Amazon VPC example-target-vpc hosts the Amazon ECS task and is in AWS account 1.
  • The example source Amazon VPC example-source-vpc performs the DNS query and is in AWS account 2.

Create a namespace and an AWS Cloud Map service

1.    Configure your AWS CLI with the credentials of account 1.

2.    Create a private AWS Cloud Map service discovery namespace in account 1:

$ aws servicediscovery create-private-dns-namespace --name example-namespace  --vpc example-target-vpc

Note: The preceding command creates a namespace with name example-namespace and returns OperationID as the output in JSON.

3.    Use the OperationID to check the status of the namespace and namespace ID:

$ aws servicediscovery get-operation --operation-id <example-OperationId> --query 'Operation.{Status: Status, NamespaceID: Targets.NAMESPACE}'

4.     Locate the hosted zone ID that's associated with the namespace:

$ aws servicediscovery get-namespace --id <example-NamespaceID> --query 'Namespace.Properties.DnsProperties.{HoztedZoneId: HostedZoneId}'

5.    Use the namespace ID to create an AWS Cloud Map service:

$ aws servicediscovery create-service \
    --name myservice \
    --namespace-id  <example-NamespaceID> \
    --dns-config "NamespaceId=<example-NamespaceID>,RoutingPolicy=MULTIVALUE,DnsRecords=[{Type=A,TTL=60}]"

Note: The preceding command creates an AWS Cloud Map service with name example-myservice and returns a service ARN as the output.

Register a task definition that uses the awsvpc network mode

Register a task definition that's compatible with AWS Fargate and uses the awsvpc network mode:

1.    Create a file named fargate-task.json with the following task definition contents:

{
    "family": "tutorial-task-def",
        "networkMode": "awsvpc",
        "containerDefinitions": [
            {
                "name": "sample-app",
                "image": "httpd:2.4",
                "portMappings": [
                    {
                        "containerPort": 80,
                        "hostPort": 80,
                        "protocol": "tcp"
                    }
                ],
                "essential": true,
                "entryPoint": [
                    "sh",
                    "-c"
                ],
                "command": [
                    "/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' >  /usr/local/apache2/htdocs/index.html && httpd-foreground\""
                ]
            }
        ],
        "requiresCompatibilities": [
            "FARGATE"
        ],
        "cpu": "256",
        "memory": "512"
}

2.    Use the fargate-task.json file to register the task definition:

$ aws ecs register-task-definition --cli-input-json file://fargate-task.json

Create an Amazon ECS service

1.    Create a file named ecs-service-discovery.json, and include the contents of the Amazon ECS service that you're creating:

  • Specify launchType as FARGATE.
  • Specify platformVersion as the latest version.
  • Make sure that the securityGroups and subnets parameters belong to the example-target-vpc. You can get the security group and subnet IDs from your Amazon VPC console.

Note: Because the task definition uses awsvpc network mode, an awsvpcConfiguration is required.

Example JSON file:

{
    "cluster": "example-cluster",
    "serviceName": "ecs-service-discovery",
    "taskDefinition": "tutorial-task-def",
    "serviceRegistries": [
       {
          "registryArn": "<Cloudmap service ARN>"
       }
    ],
    "launchType": "FARGATE",
    "platformVersion": "example-latest-version",
    "networkConfiguration": {
       "awsvpcConfiguration": {
          "assignPublicIp": "ENABLED",
          "securityGroups": [ "example-target-vpc-sg" ],
          "subnets": [ "example-target-vpc-subnet" ]
       }
    },
    "desiredCount": 1
}

2.    Use the ecs-service-discovery.json file to create your Amazon ECS service:

$ aws ecs create-service --cli-input-json file://ecs-service-discovery.json

3.    Confirm whether the service task is registered as an instance in the AWS Cloud Map service:

$ aws servicediscovery list-instances --service-id <example-cloud-map-service-id>

Note: Your Amazon ECS service is now discoverable within example-target-vpc.

Associate the source Amazon VPC to the Route 53 hosted zone

1.    If the Amazon VPCs are in different accounts, then submit an Amazon VPC association authorization request to account 2:

$ aws route53 create-vpc-association-authorization --hosted-zone-id <example-HoztedZoneId>  --vpc VPCRegion=<example_VPC_region>,VPCId=<example-source-vpc>

2.    Configure awscli with the credentials of account 2, and associate the example-source-vpc in account 2 with the hosted zone in account 1:

$ aws route53 associate-vpc-with-hosted-zone --hosted-zone-id <example-HoztedZoneId> --vpc VPCRegion=<example_VPC_region>,VPCId=<example-source-vpc>

3.    Check whether the example-source-vpc is added to the hosted zone:

aws route53 get-hosted-zone --id <example-HoztedZoneId> --query 'VPCs'

4.    Check that the Amazon ECS service is discoverable through DNS in example-source-vpc. Query the DNS from an Amazon Elastic Compute Cloud (Amazon EC2) instance with example-source-vpc:

$ dig +short example-service.example-namespace

Note: In the preceding command example-service.example-namespace is the DNS name. Replace it with your AWS Cloud Map service and namespace.

Set up Amazon VPC peering 

1.    Use Amazon VPC peering to connect example-target-vpc with example-source-vpc.

2.    Update the route tables.

3.    Update the security groups.

Note: After you set up Amazon VPC peering with the route tables and security groups, resources in example-source-vpc can connect to Amazon ECS tasks in example-target-vpc.

If you experience issues when setting up Amazon VPC peering, then see the following AWS Knowledge Center articles:

AWS OFFICIAL
AWS OFFICIALUpdated a year ago
2 Comments

Is there a way to perform this using transit gateway instead of vpc peering?

Shahab
replied 6 months ago

Thank you for your comment. We'll review and update the Knowledge Center article as needed.

profile pictureAWS
MODERATOR
replied 6 months ago