

# Use service discovery to connect Amazon ECS services with DNS names
<a name="service-discovery"></a>

Your Amazon ECS service can optionally be configured to use Amazon ECS service discovery. Service discovery uses AWS Cloud Map API actions to manage HTTP and DNS namespaces for your Amazon ECS services. For more information, see [What Is AWS Cloud Map](https://docs.aws.amazon.com/cloud-map/latest/dg/Welcome.html) in the *AWS Cloud Map Developer Guide*.

Service discovery is available in the following AWS Regions:


| Region Name | Region | 
| --- | --- | 
|  US East (N. Virginia)  |  us-east-1  | 
|  US East (Ohio)  |  us-east-2  | 
|  US West (N. California)  |  us-west-1  | 
|  US West (Oregon)  |  us-west-2  | 
|  Africa (Cape Town)  |  af-south-1  | 
|  Asia Pacific (Hong Kong)  |  ap-east-1  | 
|  Asia Pacific (Taipei)  |  ap-east-2  | 
|  Asia Pacific (Mumbai)  |  ap-south-1  | 
|  Asia Pacific (Hyderabad)  |  ap-south-2  | 
|  Asia Pacific (Tokyo)  |  ap-northeast-1  | 
|  Asia Pacific (Seoul)  |  ap-northeast-2  | 
|  Asia Pacific (Osaka)  |  ap-northeast-3  | 
|  Asia Pacific (Singapore)  |  ap-southeast-1  | 
|  Asia Pacific (Sydney)  |  ap-southeast-2  | 
|  Asia Pacific (Jakarta)  |  ap-southeast-3  | 
|  Asia Pacific (Melbourne)  |  ap-southeast-4  | 
|  Asia Pacific (Malaysia)  |  ap-southeast-5  | 
|  Asia Pacific (New Zealand)  |  ap-southeast-6  | 
|  Asia Pacific (Thailand)  |  ap-southeast-7  | 
|  Canada (Central)  |  ca-central-1  | 
|  Canada West (Calgary)  |  ca-west-1  | 
|  China (Beijing)  |  cn-north-1  | 
|  China (Ningxia)  |  cn-northwest-1  | 
|  Europe (Frankfurt)  |  eu-central-1  | 
|  Europe (Zurich)  |  eu-central-2  | 
|  Europe (Ireland)  |  eu-west-1  | 
|  Europe (London)  |  eu-west-2  | 
|  Europe (Paris)  |  eu-west-3  | 
|  Europe (Milan)  |  eu-south-1  | 
|  Europe (Stockholm)  |  eu-north-1  | 
|  Israel (Tel Aviv)  |  il-central-1  | 
|  Europe (Spain)  |  eu-south-2  | 
|  Middle East (UAE)  |  me-central-1  | 
|  Mexico (Central)  |  mx-central-1  | 
|  Middle East (Bahrain)  |  me-south-1  | 
|  South America (São Paulo)  |  sa-east-1  | 
|  AWS GovCloud (US-East)  |  us-gov-east-1  | 
|  AWS GovCloud (US-West)  |  us-gov-west-1  | 

## Service Discovery concepts
<a name="service-discovery-concepts"></a>

Service discovery consists of the following components:
+ **Service discovery namespace**: A logical group of service discovery services that share the same domain name, such as `example.com`, which is where you want to route traffic. You can create a namespace with a call to the `aws servicediscovery create-private-dns-namespace` command or in the Amazon ECS console. You can use the `aws servicediscovery list-namespaces` command to view the summary information about the namespaces that were created by the current account. For more information about the service discovery commands, see `[create-private-dns-namespace](https://docs.aws.amazon.com/cli/latest/reference/servicediscovery/create-private-dns-namespace.html)` and `[list-namespaces](https://docs.aws.amazon.com/cli/latest/reference/servicediscovery/list-namespaces.html)` in the *AWS Cloud Map (service discovery) AWS CLI Reference Guide*.
+ **Service discovery service**: Exists within the service discovery namespace and consists of the service name and DNS configuration for the namespace. It provides the following core component:
  + **Service registry**: Allows you to look up a service via DNS or AWS Cloud Map API actions and get back one or more available endpoints that can be used to connect to the service.
+ **Service discovery instance**: Exists within the service discovery service and consists of the attributes associated with each Amazon ECS service in the service directory.
  + **Instance attributes**: The following metadata is added as custom attributes for each Amazon ECS service that is configured to use service discovery:
    + **`AWS_INSTANCE_IPV4`** – For an `A` record, the IPv4 address that Route 53 returns in response to DNS queries and AWS Cloud Map returns when discovering instance details, for example, `192.0.2.44`.
    + **`AWS_INSTANCE_IPV6`**– For an `AAAA` record, the IPv6 address that Route 53 returns in response to DNS queries and AWS Cloud Map returns when discovering instance details, for example, ` 2001:0db8:85a3:0000:0000:abcd:0001:2345`. Both `AWS_INSTANCE_IPv4` and `AWS_INSTANCE_IPv6` are added for Amazon ECS dualstack services. Only `AWS_INSTANCE_IPv6` is added for Amazon ECS IPv6-only services.
    + **`AWS_INSTANCE_PORT`** – The port value associated with the service discovery service.
    + **`AVAILABILITY_ZONE`** – The Availability Zone into which the task was launched. For tasks using EC2, this is the Availability Zone in which the container instance exists. For tasks using Fargate, this is the Availability Zone in which the elastic network interface exists.
    + **`REGION`** – The Region in which the task exists.
    + **`ECS_SERVICE_NAME`** – The name of the Amazon ECS service to which the task belongs.
    + **`ECS_CLUSTER_NAME`** – The name of the Amazon ECS cluster to which the task belongs.
    + **`EC2_INSTANCE_ID`** – The ID of the container instance the task was placed on. This custom attribute is not added if the task is using Fargate.
    + **`ECS_TASK_DEFINITION_FAMILY`** – The task definition family that the task is using.
    + **`ECS_TASK_SET_EXTERNAL_ID`** – If a task set is created for an external deployment and is associated with a service discovery registry, then the `ECS_TASK_SET_EXTERNAL_ID` attribute will contain the external ID of the task set.
+ **Amazon ECS health checks**: Amazon ECS performs periodic container-level health checks. If an endpoint does not pass the health check, it is removed from DNS routing and marked as unhealthy.

## Service discovery considerations
<a name="service-discovery-considerations"></a>

The following should be considered when using service discovery:
+ Service discovery is supported for tasks on Fargate that use platform version 1.1.0 or later. For more information, see [Fargate platform versions for Amazon ECS](platform-fargate.md).
+ Services configured to use service discovery have a limit of 1,000 tasks per service. This is due to a Route 53 service quota.
+ The Create Service workflow in the Amazon ECS console only supports registering services into private DNS namespaces. When an AWS Cloud Map private DNS namespace is created, a Route 53 private hosted zone will be created automatically.
+ The VPC DNS attributes must be configured for successful DNS resolution. For information about how to configure the attributes, see [DNS support in your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-support) in the *Amazon VPC User Guide*.
+ Amazon ECS does not support registering services into shared AWS Cloud Map namespaces.
+ The DNS records created for a service discovery service always register with the private IP address for the task, rather than the public IP address, even when public namespaces are used.
+ Service discovery requires that tasks specify either the `awsvpc`, `bridge`, or `host` network mode (`none` is not supported).
+ If the service task definition uses the `awsvpc` network mode, you can create any combination of `A` or `SRV` records for each service task. If you use `SRV` records, a port is required. You can additionally create `AAAA` records if the service uses dualstack subnets. If the service uses IPv6-only subnets, you can't create `A` records.
+ If the service task definition uses the `bridge` or `host` network mode, the SRV record is the only supported DNS record type. Create a SRV record for each service task. The SRV record must specify a container name and container port combination from the task definition.
+ DNS records for a service discovery service can be queried within your VPC. They use the following format: `<service-discovery-service-name>.<service-discovery-namespace>`.
+ When doing a DNS query on the service name, `A` and `AAAA` records return a set of IP addresses that correspond to your tasks. `SRV` records return a set of IP addresses and ports for each task.
+ If you have eight or fewer healthy records, Route 53 responds to all DNS queries with all of the healthy records.
+ When all records are unhealthy, Route 53 responds to DNS queries with up to eight unhealthy records.
+ You can configure service discovery for a service that's behind a load balancer, but service discovery traffic is always routed to the task and not the load balancer.
+ Service discovery doesn't support the use of Classic Load Balancers.
+ We recommend you use container-level health checks managed by Amazon ECS for your service discovery service.
  + **HealthCheckCustomConfig**—Amazon ECS manages health checks on your behalf. Amazon ECS uses information from container and health checks, and your task state, to update the health with AWS Cloud Map. This is specified using the `--health-check-custom-config` parameter when creating your service discovery service. For more information, see [HealthCheckCustomConfig](https://docs.aws.amazon.com/cloud-map/latest/api/API_HealthCheckCustomConfig.html) in the *AWS Cloud Map API Reference*.
+ The AWS Cloud Map resources created when service discovery is used must be cleaned up manually.
+ Tasks and instances are registered as `UNHEALTHY` until the container health checks return a value. If the health checks pass, the status is updated to `HEALTHY`. If the container health checks fail, the service discovery instance is deregistered.

## Service discovery pricing
<a name="service-discovery-pricing"></a>

Customers using Amazon ECS service discovery are charged for Route 53 resources and AWS Cloud Map discovery API operations. This involves costs for creating the Route 53 hosted zones and queries to the service registry. For more information, see [AWS Cloud Map Pricing](https://docs.aws.amazon.com/cloud-map/latest/dg/cloud-map-pricing.html) in the *AWS Cloud Map Developer Guide*.

Amazon ECS performs container level health checks and exposes them to AWS Cloud Map custom health check API operations. This is currently made available to customers at no extra cost. If you configure additional network health checks for publicly exposed tasks, you're charged for those health checks.

# Creating an Amazon ECS service that uses Service Discovery
<a name="create-service-discovery"></a>

Learn how to create a service containing a Fargate task that uses service discovery with the AWS CLI.

For a list of AWS Regions that support service discovery, see [Use service discovery to connect Amazon ECS services with DNS names](service-discovery.md).

For information about the Regions that support Fargate, see [Supported Regions for Amazon ECS on AWS Fargate](AWS_Fargate-Regions.md).

**Note**  
You can use dual-stack service endpoints to interact with Amazon ECS from the AWS CLI, SDKs, and the Amazon ECS API over both IPv4 and IPv6. For more information, see [Using Amazon ECS dual-stack endpoints](dual-stack-endpoint.md).

## Prerequisites
<a name="create-service-discovery-prereqs"></a>

Before you start this tutorial, make sure that the following prerequisites are met:
+ The latest version of the AWS CLI is installed and configured. For more information, see [Installing or updating to the latest version of the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).
+ The steps described in [Set up to use Amazon ECS](get-set-up-for-amazon-ecs.md) are complete.
+ Your IAM user has the required permissions specified in the [AmazonECS\$1FullAccess](security-iam-awsmanpol.md#security-iam-awsmanpol-AmazonECS_FullAccess) IAM policy example.
+ You have created at least one VPC and one security group. For more information, see [Create a virtual private cloud](get-set-up-for-amazon-ecs.md#create-a-vpc).

## Step 1: Create the Service Discovery resources in AWS Cloud Map
<a name="create-service-discovery-namespace"></a>

Follow these steps to create your service discovery namespace and service discovery service:

1. Create a private Cloud Map service discovery namespace. This example creates a namespace that's called `tutorial`. Replace *vpc-abcd1234* with the ID of one of your existing VPCs. 

   ```
   aws servicediscovery create-private-dns-namespace \
         --name tutorial \
         --vpc vpc-abcd1234
   ```

   The output of this command is as follows.

   ```
   {
       "OperationId": "h2qe3s6dxftvvt7riu6lfy2f6c3jlhf4-je6chs2e"
   }
   ```

1. Using the `OperationId` from the output of the previous step, verify that the private namespace was created successfully. Make note of the namespace ID because you use it in subsequent commands.

   ```
   aws servicediscovery get-operation \
         --operation-id h2qe3s6dxftvvt7riu6lfy2f6c3jlhf4-je6chs2e
   ```

   The output is as follows.

   ```
   {
       "Operation": {
           "Id": "h2qe3s6dxftvvt7riu6lfy2f6c3jlhf4-je6chs2e",
           "Type": "CREATE_NAMESPACE",
           "Status": "SUCCESS",
           "CreateDate": 1519777852.502,
           "UpdateDate": 1519777856.086,
           "Targets": {
              "NAMESPACE": "ns-uejictsjen2i4eeg"
           }
       }
   }
   ```

1. Using the `NAMESPACE` ID from the output of the previous step, create a service discovery service. This example creates a service named `myapplication`. Make note of the service ID and ARN because you use them in subsequent commands.

   ```
   aws servicediscovery create-service \
         --name myapplication \
         --dns-config "NamespaceId="ns-uejictsjen2i4eeg",DnsRecords=[{Type="A",TTL="300"}]" \
         --health-check-custom-config FailureThreshold=1
   ```

   The output is as follows.

   ```
   {
       "Service": {
          "Id": "srv-utcrh6wavdkggqtk",
           "Arn": "arn:aws:servicediscovery:region:aws_account_id:service/srv-utcrh6wavdkggqtk",
           "Name": "myapplication",
           "DnsConfig": {
               "NamespaceId": "ns-uejictsjen2i4eeg",
               "DnsRecords": [
                   {
                       "Type": "A",
                       "TTL": 300
                   }
               ]
           },
           "HealthCheckCustomConfig": {
               "FailureThreshold": 1
           },
           "CreatorRequestId": "e49a8797-b735-481b-a657-b74d1d6734eb"
       }
   }
   ```

## Step 2: Create the Amazon ECS resources
<a name="create-service-discovery-cluster"></a>

Follow these steps to create your Amazon ECS cluster, task definition, and service:

1. Create an Amazon ECS cluster. This example creates a cluster that's named `tutorial`. 

   ```
   aws ecs create-cluster \
         --cluster-name tutorial
   ```

1. Register a task definition that's compatible with Fargate and uses the `awsvpc` network mode. Follow these steps:

   1. Create a file that's named `fargate-task.json` with the contents of the following task definition.

      ```
      {
          "family": "tutorial-task-def",
              "networkMode": "awsvpc",
              "containerDefinitions": [
                  {
                      "name": "sample-app",
                      "image": "public.ecr.aws/docker/library/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"
      }
      ```

   1. Register the task definition using `fargate-task.json`.

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

1. Create an ECS service by following these steps:

   1. Create a file that's named `ecs-service-discovery.json` with the contents of the ECS service that you're creating. This example uses the task definition that was created in the previous step. An `awsvpcConfiguration` is required because the example task definition uses the `awsvpc` network mode. 

      When you create the ECS service, specify Fargate and the `LATEST` platform version that supports service discovery. When the service discovery service is created in AWS Cloud Map , `registryArn` is the ARN returned. The `securityGroups` and `subnets` must belong to the VPC that's used to create the Cloud Map namespace. You can obtain the security group and subnet IDs from the Amazon VPC Console.

      ```
      {
          "cluster": "tutorial",
          "serviceName": "ecs-service-discovery",
          "taskDefinition": "tutorial-task-def",
          "serviceRegistries": [
             {
                "registryArn": "arn:aws:servicediscovery:region:aws_account_id:service/srv-utcrh6wavdkggqtk"
             }
          ],
          "launchType": "FARGATE",
          "platformVersion": "LATEST",
          "networkConfiguration": {
             "awsvpcConfiguration": {
                "assignPublicIp": "ENABLED",
                "securityGroups": [ "sg-abcd1234" ],
                "subnets": [ "subnet-abcd1234" ]
             }
          },
          "desiredCount": 1
      }
      ```

   1. Create your ECS service using `ecs-service-discovery.json`.

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

## Step 3: Verify Service Discovery in AWS Cloud Map
<a name="create-service-discovery-verify"></a>

You can verify that everything is created properly by querying your service discovery information. After service discovery is configured, you can either use AWS Cloud Map API operations, or call `dig` from an instance within your VPC. Follow these steps:

1. Using the service discovery service ID, list the service discovery instances. Make note of the instance ID (marked in bold) for resource cleanup. 

   ```
    aws servicediscovery list-instances \
          --service-id srv-utcrh6wavdkggqtk
   ```

   The output is as follows.

   ```
   {
       "Instances": [
           {
               "Id": "16becc26-8558-4af1-9fbd-f81be062a266",
               "Attributes": {
                   "AWS_INSTANCE_IPV4": "172.31.87.2"
                   "AWS_INSTANCE_PORT": "80", 
                   "AVAILABILITY_ZONE": "us-east-1a", 
                   "REGION": "us-east-1", 
                   "ECS_SERVICE_NAME": "ecs-service-discovery", 
                   "ECS_CLUSTER_NAME": "tutorial", 
                   "ECS_TASK_DEFINITION_FAMILY": "tutorial-task-def"
               }
           }
       ]
   }
   ```

1. Use the service discovery namespace, service, and additional parameters such as ECS cluster name to query details about the service discovery instances.

   ```
   aws servicediscovery discover-instances \
         --namespace-name tutorial \
         --service-name myapplication \
         --query-parameters ECS_CLUSTER_NAME=tutorial
   ```

1. The DNS records that are created in the Route 53 hosted zone for the service discovery service can be queried with the following AWS CLI commands:

   1. Using the namespace ID, get information about the namespace, which includes the Route 53 hosted zone ID.

      ```
      aws servicediscovery \
            get-namespace --id ns-uejictsjen2i4eeg
      ```

      The output is as follows.

      ```
      {
          "Namespace": {
              "Id": "ns-uejictsjen2i4eeg",
              "Arn": "arn:aws:servicediscovery:region:aws_account_id:namespace/ns-uejictsjen2i4eeg",
              "Name": "tutorial",
              "Type": "DNS_PRIVATE",
              "Properties": {
                   "DnsProperties": {
                      "HostedZoneId": "Z35JQ4ZFDRYPLV"
                  }
              },
              "CreateDate": 1519777852.502,
              "CreatorRequestId": "9049a1d5-25e4-4115-8625-96dbda9a6093"
          }
      }
      ```

   1. Using the Route 53 hosted zone ID from the previous step (see the text in bold), get the resource record set for the hosted zone. 

      ```
      aws route53 list-resource-record-sets \
            --hosted-zone-id Z35JQ4ZFDRYPLV
      ```

1. You can also query the DNS from an instance within your VPC using `dig`.

   ```
   dig +short myapplication.tutorial
   ```

## Step 4: Clean up
<a name="create-service-discovery-cleanup"></a>

When you're finished with this tutorial, clean up the associated resources to avoid incurring charges for unused resources. Follow these steps:

1. Deregister the service discovery service instances using the service ID and instance ID that you noted previously.

   ```
   aws servicediscovery deregister-instance \
         --service-id srv-utcrh6wavdkggqtk \
         --instance-id 16becc26-8558-4af1-9fbd-f81be062a266
   ```

   The output is as follows.

   ```
   {
       "OperationId": "xhu73bsertlyffhm3faqi7kumsmx274n-jh0zimzv"
   }
   ```

1. Using the `OperationId` from the output of the previous step, verify that the service discovery service instances were deregistered successfully.

   ```
   aws servicediscovery get-operation \ 
         --operation-id xhu73bsertlyffhm3faqi7kumsmx274n-jh0zimzv
   ```

   ```
   {
     "Operation": {
           "Id": "xhu73bsertlyffhm3faqi7kumsmx274n-jh0zimzv",
           "Type": "DEREGISTER_INSTANCE",
           "Status": "SUCCESS",
           "CreateDate": 1525984073.707,
           "UpdateDate": 1525984076.426,
           "Targets": {
               "INSTANCE": "16becc26-8558-4af1-9fbd-f81be062a266",
               "ROUTE_53_CHANGE_ID": "C5NSRG1J4I1FH",
               "SERVICE": "srv-utcrh6wavdkggqtk"
           }
       }
   }
   ```

1. Delete the service discovery service using the service ID.

   ```
   aws servicediscovery delete-service \ 
         --id srv-utcrh6wavdkggqtk
   ```

1. Delete the service discovery namespace using the namespace ID.

   ```
   aws servicediscovery delete-namespace \ 
         --id ns-uejictsjen2i4eeg
   ```

   The output is as follows.

   ```
   {
       "OperationId": "c3ncqglftesw4ibgj5baz6ktaoh6cg4t-jh0ztysj"
   }
   ```

1. Using the `OperationId` from the output of the previous step, verify that the service discovery namespace was deleted successfully.

   ```
   aws servicediscovery get-operation \ 
         --operation-id c3ncqglftesw4ibgj5baz6ktaoh6cg4t-jh0ztysj
   ```

   The output is as follows.

   ```
   {
       "Operation": {
           "Id": "c3ncqglftesw4ibgj5baz6ktaoh6cg4t-jh0ztysj",
           "Type": "DELETE_NAMESPACE",
           "Status": "SUCCESS",
           "CreateDate": 1525984602.211,
           "UpdateDate": 1525984602.558,
           "Targets": {
               "NAMESPACE": "ns-rymlehshst7hhukh",
               "ROUTE_53_CHANGE_ID": "CJP2A2M86XW3O"
           }
       }
   }
   ```

1. Update the desired count for the Amazon ECS service to `0`. You must do this to delete the service in the next step.

   ```
   aws ecs update-service \
         --cluster tutorial \
         --service ecs-service-discovery \
         --desired-count 0
   ```

1. Delete the Amazon ECS service.

   ```
   aws ecs delete-service \
         --cluster tutorial \
         --service ecs-service-discovery
   ```

1. Delete the Amazon ECS cluster.

   ```
   aws ecs delete-cluster \
         --cluster tutorial
   ```