如何将 Amazon ECS 服务发现功能与 CloudFormation 结合使用?

上次更新时间:2021 年 9 月 23 日

我想将 Amazon Elastic Container Service(Amazon ECS)服务发现功能与 AWS CloudFormation 结合使用。

简短描述

Amazon ECS 控制台允许您在服务创建期间创建服务发现资源。但 CloudFormation 的 AWS::ECS::Service 资源类型不允许您在服务创建期间创建服务发现资源。

注意:Amazon ECS 控制台使用集成 API CreatePrivateDnsNamespaceCreateService(AWS Cloud Map)和 CreateService(Amazon ECS)。在 CloudFormation 中,您可以使用资源类型 AWS::ServiceDiscovery::PrivateDnsNamespaceAWS::ServiceDiscovery::ServiceAWS::ECS::Service 在单个 CloudFormation 模板中实施一项集成。

解决方法

1.    在 CloudFormation 模板的 Resources(资源)部分,创建一个私有服务发现命名空间,例如 example.com。在一个现有的 Amazon Virtual Private Cloud(Amazon VPC)中创建该命名空间。请参阅以下 JSON 和 YAML 示例。

JSON:

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

YAML:

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

注意:example.com 替换为您的命名空间的名称。将 vpc-xxxxxxx 替换为您账户中 VPC 的 ID。

2.    使用您在第 1 步中所创建命名空间的命名空间 ID 创建服务发现服务。

您可以使用 CloudFormation 模板中的 Ref 内置函数获取命名空间 ID 的值。请参阅以下 JSON 和 YAML 示例。

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": "example-service-name",
      "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: example-service-name
    NamespaceId: !Ref PrivateNamespace

注意:请将 example-service-name 替换为您服务的名称

DnsConfig 属性指定在 Amazon Route 53 中自动创建的 DNS 记录。这些 DNS 记录是在您的 Amazon ECS 任务向服务发现服务注册时创建的。支持类型 A 和 SRV 的 DNS 记录。

提示:最佳实践是使用 HealthCheckCustomConfig 属性来允许 Amazon ECS 向服务发现报告任务运行状况。Amazon ECS 使用来自容器检查、运行状况检查和任务状态的信息来更新 AWS Cloud Map 的服务发现的运行状况。

3.    创建一个与您在之前步骤中创建的服务发现命名空间和服务集成的 Amazon ECS 服务。使用 AWS:ECS::Service 资源中的 ServiceRegistries 属性来指定您的集成。请参阅以下 JSON 和 YAML 示例。

JSON:

{
  "EcsService": {
    "Type": "AWS::ECS::Service",
    "Properties": {
      "Cluster": "awsExampleCluster",
      "DesiredCount": 4,
      "LaunchType": "FARGATE",
      "NetworkConfiguration": {
        "AwsvpcConfiguration": {
          "SecurityGroups": [
            "sg-xxxxxxx"
          ],
          "Subnets": [
            "subnet-xxxxxxx"
          ]
        }
      },
      "ServiceName": "awsExampleService",
      "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-xxxxxxx
        Subnets:
          - subnet-xxxxxxx
    ServiceName: awsExampleService
    TaskDefinition: awsExampleTaskDefinition
    ServiceRegistries:
      - RegistryArn: !GetAtt DiscoveryService.Arn
        Port: 80

注意:请将 awsExampleCluster 替换为您的集群。将 awsExampleService 替换为您的服务。将 awsExampleTaskDefinition 替换为您的任务定义。将 sg-xxxxxxx 替换为您的安全组 ID。将 subnet-xxxxxxx 替换为您的子网 ID。

对于 RegistryArn 属性,将值设置为要与 Amazon ECS 服务集成的服务发现服务的 Amazon Resource Name(ARN)。使用内置函数 Fn::GetAtt 从您的 CloudFormation 模板中获取此值。

如果使用 awsvpc 模式,请将值设置为 PortContainerPortContainerName 的组合(如任务定义中所指定)。如果使用 host bridge 模式,请将值设置为 ContainerPort ContainerName (如任务定义中所指定)。

4.    打开 CloudFormation 控制台,然后选择 Create stack(创建堆栈)以根据更新后的模板部署资源。

5.    要验证是否可以从 VPC 中解析您的任务,请运行以下命令:

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

注意:awsExampleService 的值是 AWS::ECS::Service 资源的名称。awsExampleNamespace 的值是 AWS::ServiceDiscovery::PrivateDnsNamespace 资源的名称。

命令将返回类似于以下内容的输出:

对于 $ dig awsExampleService.awsExampleNamespace. +short

172.31.182.0
172.31.160.124
172.31.137.81
172.31.149.244

对于 $ 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.

对于 $ 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

这篇文章对您有帮助吗?


您是否需要账单或技术支持?