By using AWS re:Post, you agree to the AWS re:Post Terms of Use

How do I use Amazon ECS service discovery with CloudFormation?

5 minute read
0

I want to use Amazon Elastic Container Service (Amazon ECS) service discovery with AWS CloudFormation.

Short description

The Amazon ECS console allows you to use AWS Cloud Map to directly configure Service Discovery resources during service creation.

Resolution

The following sections use AWS Cloud Map to create an example Service Discovery for an Amazon ECS service in an AWS CloudFormation template.

To create an AWS Cloud Map private DNS namespace, complete the following steps:

  1. In the Resources section of your CloudFormation template, create a private service discovery namespace, such as example.com. Create the namespace in an existing Amazon Virtual Private Cloud (Amazon VPC). See the following JSON and YAML examples.

    JSON:

    {
      "PrivateNamespace": {
        "Type": "AWS::ServiceDiscovery::PrivateDnsNamespace",
        "Properties": {
          "Name": "example.com",
          "Vpc": "vpc-#######"
        }
      }
    }

    YAML:

    PrivateNamespace:
        Type: AWS::ServiceDiscovery::PrivateDnsNamespace
        Properties:
            Name: example.com
            Vpc: vpc-#######

    Note: Replace example.com with a name for your namespace. Replace vpc-####### with the ID of a VPC from your account.

  2. Create a service discovery service using the namespace ID of the namespace that you created in Step 1. To get the value of the namespace ID, use the Ref intrinsic function in your CloudFormation template. See the following JSON and YAML examples.

    JSON:

    {  "DiscoveryService": {
        "Type": "AWS::ServiceDiscovery::Service",
        "Properties": {
          "Description": "Discovery Service for the Demo Application",
          "DnsConfig": {
            "RoutingPolicy": "MULTIVALUE",
            "DnsRecords": [
              {
                "TTL": 60,
                "Type": "A"
              },
              {
                "TTL": 60,
                "Type": "SRV"
              }
            ]
          },
          "HealthCheckCustomConfig": {
            "FailureThreshold": 1
          },
          "Name": "awsExampleService",
          "NamespaceId": {
            "Ref": "PrivateNamespace"
          }
        }
      }
    }

    YAML:

    DiscoveryService:  Type: AWS::ServiceDiscovery::Service
      Properties: 
        Description: Discovery Service for the Demo Application
        DnsConfig:
          RoutingPolicy: MULTIVALUE
          DnsRecords:
            - TTL: 60
              Type: A
            - TTL: 60
              Type: SRV
        HealthCheckCustomConfig: 
          FailureThreshold: 1
        Name: awsExampleService
        NamespaceId: !Ref PrivateNamespace

    Note: Replace awsExampleService with the name of your service.

    The DnsConfig property specifies the DNS records that are automatically created in Amazon Route 53. These DNS records are created when your Amazon ECS task is registered with the service discovery service. DNS records of type A and SRV are supported. For more information, see Use service discovery to connect Amazon ECS services with DNS names.

    Tip: It's a best practice to use the HealthCheckCustomConfig property to allow Amazon ECS to report task health to service discovery. Amazon ECS uses information from container checks, health checks, and task state to update the health of service discovery with AWS Cloud Map.

  3. Create an Amazon ECS service that integrates with the service discovery namespace and service that you created in the previous steps. Use the ServiceRegistries property in the AWS:ECS::Service resource to specify your integration. See the following JSON and YAML examples.

    JSON:

    {  "EcsService": {
        "Type": "AWS::ECS::Service",
        "Properties": {
          "Cluster": "awsExampleCluster",
          "DesiredCount": 4,
          "LaunchType": "FARGATE",
          "NetworkConfiguration": {
            "AwsvpcConfiguration": {
              "SecurityGroups": [
                "sg-#######"
              ],
              "Subnets": [
                "subnet-#######"
              ]
            }
          },
          "ServiceName": "ECSExampleService",
          "TaskDefinition": "awsExampleTaskDefinition",
          "ServiceRegistries": [
            {
              "RegistryArn": {
                "Fn::GetAtt": [
                  "DiscoveryService",
                  "Arn"
                ]
              },
              "Port": 80
            }
          ]
        }
      }
    }

    YAML:

    EcsService:  Type: AWS::ECS::Service
      Properties:
        Cluster: awsExampleCluster
        DesiredCount: 4
        LaunchType: FARGATE
        NetworkConfiguration:
          AwsvpcConfiguration:
            SecurityGroups:
              - sg-#######
            Subnets:
              - subnet-#######
        ServiceName: ECSExampleService
        TaskDefinition: awsExampleTaskDefinition
        ServiceRegistries:
          - RegistryArn: !GetAtt DiscoveryService.Arn
            Port: 80

    Note: Replace awsExampleCluster with your cluster. Replace ECSExampleService with your service. Replace awsExampleTaskDefinition with your task definition. Replace sg-####### with your security group ID. Replace subnet-####### with your subnet ID.

    For RegistryArn, use the Amazon Resource Name (ARN) of the service discovery service that you want to integrate with your Amazon ECS service. Use the intrinsic function Fn::GetAtt to get this value from your CloudFormation template.

    If you use the awsvpc mode, then set the value to either Port or to a combination of ContainerPort and ContainerName (as specified in the task definition). If you use host or bridge mode, then set the value to ContainerPort or to ContainerName (as specified in the task definition).

  4. Open the CloudFormation console, and then choose Create stack to deploy the resources based on your updated template.

  5. To verify that your tasks can be resolved from your VPC, run the following commands:

    $ dig awsExampleService.awsExampleNamespace. +short
    $ dig srv awsExampleService.awsExampleNamespace. +short
    $ curl awsExampleService.awsExampleNamespace. -I

    Note: The value of awsExampleService is the name for your AWS::ECS::Service resource. The value of awsExampleNamespace is the name for your AWS::ServiceDiscovery::PrivateDnsNamespace resource.

    The commands return output similar to the following:

    For $ dig awsExampleService.awsExampleNamespace. +short:

    172.31.182.0
    172.31.160.124
    172.31.137.81
    172.31.149.244

    For $ dig srv awsExampleService.awsExampleNamespace. +short:

    1 1 80 ffe95d27ea8d4f7aba0dfed87297fc5a.awsExampleService.awsExampleNamespace.
    1 1 80 44a17fa781974a93bb563bc1826a8697.awsExampleService.awsExampleNamespace.
    1 1 80 d640ecb3d283421bb2d1318caf4b0d66.awsExampleService.awsExampleNamespace.
    1 1 80 65aff6fff33144b2ad79d283ab52cfe9.awsExampleService.awsExampleNamespace.

    For $ curl awsExampleService.awsExampleNamespace. -I:

    HTTP/1.1 200 OK
    Server: nginx/1.15.12
    Date: Wed, 15 May 2019 02:25:19 GMT
    Content-Type: text/html
    Content-Length: 612
    Last-Modified: Tue, 16 Apr 2019 13:08:19 GMT
    Connection: keep-alive
    ETag: "5cb5d3c3-264"
    Accept-Ranges: bytes
AWS OFFICIAL
AWS OFFICIALUpdated 5 months ago