Configuração do Amazon ECS Service Connect com a AWS CLI - Amazon Elastic Container Service

Configuração do Amazon ECS Service Connect com a AWS CLI

É possível criar um serviço do Amazon ECS para uma tarefa do Fargate que usa o Service Connect com a AWS CLI.

Pré-requisitos

Confira a seguir os pré-requisitos do Service Connect:

  • Verifique se a região oferece suporte ao Service Connect. Para ter mais informações, consulte Regions with Service Connect.

  • Verifique se a versão mais recente da AWS CLI está instalada e configurada. Para obter mais informações, consulte Instalar a AWS Command Line Interface.

  • Seu usuário da AWS tem as permissões necessárias especificadas no exemplo de política AmazonECS_FullAccess do IAM.

  • Você tem uma VPC, uma sub-rede, uma tabela de rotas e um grupo de segurança criados para serem usados. Para ter mais informações, consulte Criar uma nuvem privada virtual.

  • Você tem um perfil de execução de tarefa com o nome ecsTaskExecutionRole e a política gerenciada AmazonECSTaskExecutionRolePolicy está anexada ao perfil. Esse perfil permite que o Fargate grave os logs da aplicação NGINX e os logs do proxy do Service Connect no Amazon CloudWatch Logs. Para ter mais informações, consulte Criação do perfil de execução de tarefas (ecsTaskExecutionRole) do Amazon ECS.

Etapa 1: criar um cluster

Use as etapas a seguir para criar um cluster e um namespace do Amazon ECS.

Para criar o cluster e o namespace AWS Cloud Map do Amazon ECS
  1. Crie um cluster do Amazon ECS denominado tutorial a ser usado. O parâmetro --service-connect-defaults define o namespace padrão do cluster. Na saída do exemplo, um namespace do AWS Cloud Map com o nome service-connect não existe nessa conta nem na Região da AWS. Portanto, o namespace é criado pelo Amazon ECS. O namespace é criado no AWS Cloud Map na conta e é visível com todos os outros namespaces. Portanto, use um nome que indique a finalidade.

    aws ecs create-cluster --cluster-name tutorial --service-connect-defaults namespace=service-connect

    Saída:

    {
        "cluster": {
            "clusterArn": "arn:aws:ecs:us-west-2:123456789012:cluster/tutorial",
            "clusterName": "tutorial",
            "serviceConnectDefaults": {
                "namespace": "arn:aws:servicediscovery:us-west-2:123456789012:namespace/ns-EXAMPLE"
            },
            "status": "PROVISIONING",
            "registeredContainerInstancesCount": 0,
            "runningTasksCount": 0,
            "pendingTasksCount": 0,
            "activeServicesCount": 0,
            "statistics": [],
            "tags": [],
            "settings": [
                {
                    "name": "containerInsights",
                    "value": "disabled"
                }
            ],
            "capacityProviders": [],
            "defaultCapacityProviderStrategy": [],
            "attachments": [
                {
                    "id": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
                    "type": "sc",
                    "status": "ATTACHING",
                    "details": []
                }
            ],
            "attachmentsStatus": "UPDATE_IN_PROGRESS"
        }
    }
    }
  2. Verifique se o cluster foi criado:

    aws ecs describe-clusters --clusters tutorial

    Saída:

    {
        "clusters": [
            {
                "clusterArn": "arn:aws:ecs:us-west-2:123456789012:cluster/tutorial",
                "clusterName": "tutorial",
                "serviceConnectDefaults": {
                    "namespace": "arn:aws:servicediscovery:us-west-2:123456789012:namespace/ns-EXAMPLE"
                },
                "status": "ACTIVE",
                "registeredContainerInstancesCount": 0,
                "runningTasksCount": 0,
                "pendingTasksCount": 0,
                "activeServicesCount": 0,
                "statistics": [],
                "tags": [],
                "settings": [],
                "capacityProviders": [],
                "defaultCapacityProviderStrategy": []
            }
        ],
        "failures": []
    }
                    
  3. (opcional) verifique se o namespace foi criado no AWS Cloud Map. É possível usar o AWS Management Console ou a configuração normal da AWS CLI, pois ela é criada no AWS Cloud Map.

    Por exemplo, use a AWS CLI:

    aws servicediscovery --region us-west-2 get-namespace --id ns-EXAMPLE

    Saída:

    {
        "Namespace": {
            "Id": "ns-EXAMPLE",
            "Arn": "arn:aws:servicediscovery:us-west-2:123456789012:namespace/ns-EXAMPLE",
            "Name": "service-connect",
            "Type": "HTTP",
            "Properties": {
                "DnsProperties": {
                    "SOA": {}
                },
                "HttpProperties": {
                    "HttpName": "service-connect"
                }
            },
            "CreateDate": 1661749852.422,
            "CreatorRequestId": "service-connect"
        }
    }
                    

Etapa 2: criar o serviço para o servidor

O recurso Service Connect é destinado à interconexão de várias aplicações no Amazon ECS. Pelo menos uma dessas aplicações precisa fornecer um serviço Web ao qual se conectar. Nessa etapa, você criará:

  • A definição de tarefa que usa a imagem oficial do contêiner NGINX não modificada e inclui a configuração do Service Connect.

  • A definição de serviço do Amazon ECS que configura o Service Connect para fornecer a descoberta de serviços e o proxy de malha de serviços para o tráfego desse serviço. A configuração reutiliza o namespace padrão da configuração do cluster para reduzir a quantidade de configuração de serviço feita para cada serviço.

  • O serviço do Amazon ECS. Ele executa uma tarefa usando a definição de tarefa e insere um contêiner adicional para o proxy do Service Connect. O proxy recebe a porta proveniente do mapeamento da porta do contêiner na definição de tarefa. Em uma aplicação cliente executada no Amazon ECS, o proxy na tarefa do cliente recebe as conexões de saída para o nome da porta de definição de tarefa, o nome da descoberta do serviço ou o nome do alias do cliente de serviço e o número da porta do alias do cliente.

Como criar o serviço Web com o Service Connect
  1. Registre uma definição de tarefa compatível com o Fargate e use o modo de rede awsvpc. Siga estas etapas:

    1. Crie um arquivo denominado service-connect-nginx.json com o conteúdo da seguinte definição de tarefa.

      Essa definição de tarefa configura o Service Connect adicionando os parâmetros name e appProtocol ao mapeamento de portas. O nome da porta torna essa porta mais identificável na configuração do serviço quando várias portas são usadas. O nome da porta também é usado por padrão como o nome detectável para uso por outras aplicações no namespace.

      A definição da tarefa contém o perfil do IAM da tarefa, pois o serviço tem o ECS Exec ativado.

      Importante

      Essa definição de tarefa usa a logConfiguration para enviar a saída do nginx de stdout e stderr para o Amazon CloudWatch Logs. Esse perfil de execução de tarefas não tem as permissões extras necessárias para a criação do grupo de logs do CloudWatch Logs. Crie o grupo de logs no CloudWatch Logs usando o AWS Management Console ou a AWS CLI. Se você não quiser enviar os logs do nginx para o CloudWatch Logs, poderá remover a logConfiguration.

      Substitua o ID da Conta da AWS no perfil de execução de tarefas pelo ID da sua Conta da AWS.

      { "family": "service-connect-nginx", "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole", "taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole", "networkMode": "awsvpc", "containerDefinitions": [ { "name": "webserver", "image": "public.ecr.aws/docker/library/nginx:latest", "cpu": 100, "portMappings": [ { "name": "nginx", "containerPort": 80, "protocol": "tcp", "appProtocol": "http" } ], "essential": true, "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/service-connect-nginx", "awslogs-region": "region", "awslogs-stream-prefix": "nginx" } } } ], "cpu": "256", "memory": "512" }
    2. Registre a definição de tarefa usando o arquivo service-connect-nginx.json:

      aws ecs register-task-definition --cli-input-json file://service-connect-nginx.json
  2. Crie um serviço:

    1. Crie um arquivo denominado service-connect-nginx-service.json com o conteúdo do serviço do Amazon ECS que você está criando. Este exemplo usa a definição de tarefa criada na etapa anterior. Uma awsvpcConfiguration é necessária, pois o exemplo de definição de tarefa usa o modo de rede awsvpc.

      Ao criar o serviço do ECS, especifique o tipo de inicialização do Fargate e a versão LATEST da plataforma que oferece suporte ao Service Connect. Os securityGroups e as subnets devem pertencer a uma VPC que tenha os requisitos para usar o Amazon ECS. É possível obter os IDs de grupos de segurança e sub-redes no console da Amazon VPC.

      Esse serviço configura o Service Connect adicionando o parâmetro serviceConnectConfiguration. O namespace não é necessário porque o cluster tem um namespace padrão configurado. As aplicações cliente em execução no ECS no namespace se conectam a esse serviço usando o portName e a porta no clientAliases. Por exemplo, esse serviço pode ser acessado usando http://nginx:80/, pois o nginx fornece uma página de boas-vindas no / do local raiz. Aplicações externas que não estão sendo executadas no Amazon ECS ou não estão no mesmo namespace podem acessar essa aplicação por meio do proxy do Service Connect usando o endereço IP da tarefa e o número da porta da definição de tarefa. Na configuração do tls, adicione o arn do certificado para awsPcaAuthorityArn, kmsKey e roleArn do perfil do IAM.

      Esse serviço usa uma logConfiguration para enviar a saída do proxy de conexão do serviço de stdout e stderr para o Amazon CloudWatch Logs. Esse perfil de execução de tarefas não tem as permissões extras necessárias para a criação do grupo de logs do CloudWatch Logs. Crie o grupo de logs no CloudWatch Logs usando o AWS Management Console ou a AWS CLI. Recomendamos que você crie esse grupo de logs e armazene os logs de proxy no CloudWatch Logs. Se você não quiser enviar os logs do proxy para o CloudWatch Logs, poderá remover a logConfiguration.

      { "cluster": "tutorial", "deploymentConfiguration": { "maximumPercent": 200, "minimumHealthyPercent": 0 }, "deploymentController": { "type": "ECS" }, "desiredCount": 1, "enableECSManagedTags": true, "enableExecuteCommand": true, "launchType": "FARGATE", "networkConfiguration": { "awsvpcConfiguration": { "assignPublicIp": "ENABLED", "securityGroups": [ "sg-EXAMPLE" ], "subnets": [ "subnet-EXAMPLE", "subnet-EXAMPLE", "subnet-EXAMPLE" ] } }, "platformVersion": "LATEST", "propagateTags": "SERVICE", "serviceName": "service-connect-nginx-service", "serviceConnectConfiguration": { "enabled": true, "services": [ { "portName": "nginx", "clientAliases": [ { "port": 80 } ], "tls": { "issuerCertificateAuthority": { "awsPcaAuthorityArn": "certificateArn" }, "kmsKey": "kmsKey", "roleArn": "iamRoleArn" } } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/service-connect-proxy", "awslogs-region": "region", "awslogs-stream-prefix": "service-connect-proxy" } } }, "taskDefinition": "service-connect-nginx" }
    2. Crie um serviço usando o arquivo service-connect-nginx-service.json:

      aws ecs create-service --cluster tutorial --cli-input-json file://service-connect-nginx-service.json

      Saída:

      {
          "service": {
              "serviceArn": "arn:aws:ecs:us-west-2:123456789012:service/tutorial/service-connect-nginx-service",
              "serviceName": "service-connect-nginx-service",
              "clusterArn": "arn:aws:ecs:us-west-2:123456789012:cluster/tutorial",
              "loadBalancers": [],
              "serviceRegistries": [],
              "status": "ACTIVE",
              "desiredCount": 1,
              "runningCount": 0,
              "pendingCount": 0,
              "launchType": "FARGATE",
              "platformVersion": "LATEST",
              "platformFamily": "Linux",
              "taskDefinition": "arn:aws:ecs:us-west-2:123456789012:task-definition/service-connect-nginx:1",
              "deploymentConfiguration": {
                  "deploymentCircuitBreaker": {
                      "enable": false,
                      "rollback": false
                  },
                  "maximumPercent": 200,
                  "minimumHealthyPercent": 0
              },
              "deployments": [
                  {
                      "id": "ecs-svc/3763308422771520962",
                      "status": "PRIMARY",
                      "taskDefinition": "arn:aws:ecs:us-west-2:123456789012:task-definition/service-connect-nginx:1",
                      "desiredCount": 1,
                      "pendingCount": 0,
                      "runningCount": 0,
                      "failedTasks": 0,
                      "createdAt": 1661210032.602,
                      "updatedAt": 1661210032.602,
                      "launchType": "FARGATE",
                      "platformVersion": "1.4.0",
                      "platformFamily": "Linux",
                      "networkConfiguration": {
                          "awsvpcConfiguration": {
                              "assignPublicIp": "ENABLED",
                              "securityGroups": [
                                  "sg-EXAMPLE"
                              ],
                              "subnets": [
                                  "subnet-EXAMPLEf",
                                  "subnet-EXAMPLE",
                                  "subnet-EXAMPLE"
                              ]
                          }
                      },
                      "rolloutState": "IN_PROGRESS",
                      "rolloutStateReason": "ECS deployment ecs-svc/3763308422771520962 in progress.",
                      "failedLaunchTaskCount": 0,
                      "replacedTaskCount": 0,
                      "serviceConnectConfiguration": {
                          "enabled": true,
                          "namespace": "service-connect",
                          "services": [
                              {
                                  "portName": "nginx",
                                  "clientAliases": [
                                      {
                                          "port": 80
                                      }
                                  ]
                              }
                          ],
                          "logConfiguration": {
                              "logDriver": "awslogs",
                              "options": {
                                  "awslogs-group": "/ecs/service-connect-proxy",
                                  "awslogs-region": "us-west-2",
                                  "awslogs-stream-prefix": "service-connect-proxy"
                              },
                              "secretOptions": []
                          }
                      },
                      "serviceConnectResources": [
                          {
                              "discoveryName": "nginx",
                              "discoveryArn": "arn:aws:servicediscovery:us-west-2:123456789012:service/srv-EXAMPLE"
                          }
                      ]
                  }
              ],
              "roleArn": "arn:aws:iam::123456789012:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS",
              "version": 0,
              "events": [],
              "createdAt": 1661210032.602,
              "placementConstraints": [],
              "placementStrategy": [],
              "networkConfiguration": {
                  "awsvpcConfiguration": {
                      "assignPublicIp": "ENABLED",
                      "securityGroups": [
                          "sg-EXAMPLE"
                      ],
                      "subnets": [
                          "subnet-EXAMPLE",
                          "subnet-EXAMPLE",
                          "subnet-EXAMPLE"
                      ]
                  }
              },
              "schedulingStrategy": "REPLICA",
              "enableECSManagedTags": true,
              "propagateTags": "SERVICE",
              "enableExecuteCommand": true
          }
      }
                              

      A serviceConnectConfiguration que você forneceu aparece na primeira implantação da saída. À medida que você faz alterações no serviço do ECS de maneiras que precisam fazer alterações nas tarefas, uma nova implantação é criada pelo Amazon ECS.

Etapa 3: verificar se você pode se conectar

Para verificar se o Service Connect está configurado e funcionando, siga estas etapas para se conectar ao serviço Web em uma aplicação externa. Em seguida, consulte as métricas adicionais que o proxy do Service Connect cria no CloudWatch.

Para se conectar ao serviço Web em uma aplicação externa
  • Conecte-se ao endereço IP da tarefa e à porta do contêiner usando o endereço IP da tarefa

    Use a AWS CLI para obter o ID da tarefa, usando o aws ecs list-tasks --cluster tutorial.

    Se suas sub-redes e seu grupo de segurança permitirem tráfego da Internet pública na porta da definição da tarefa, será possível se conectar ao IP público no seu computador. No entanto, o IP público não está disponível em “describe-tasks”. Portanto, as etapas envolvem acessar o AWS Management Console ou a AWS CLI do Amazon EC2 para obter os detalhes da interface de rede elástica.

    Nesse exemplo, uma instância do Amazon EC2 na mesma VPC usa o IP privado da tarefa. A aplicação é nginx, mas o cabeçalho server: envoy mostra que o proxy do Service Connect é usado. O proxy do Service Connect recebe a porta do contêiner vindo da definição de tarefa.

    $ curl -v 10.0.19.50:80/
    *   Trying 10.0.19.50:80...
    * Connected to 10.0.19.50 (10.0.19.50) port 80 (#0)
    > GET / HTTP/1.1
    > Host: 10.0.19.50
    > User-Agent: curl/7.79.1
    > Accept: */*
    >
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 200 OK
    < server: envoy
    < date: Tue, 23 Aug 2022 03:53:06 GMT
    < content-type: text/html
    < content-length: 612
    < last-modified: Tue, 16 Apr 2019 13:08:19 GMT
    < etag: "5cb5d3c3-264"
    < accept-ranges: bytes
    < x-envoy-upstream-service-time: 0
    <
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
            width: 35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html> 
                    
Para visualizar as métricas do Service Connect

O proxy do Service Connect cria métricas de aplicações (conexão HTTP, HTTP2, gRPC ou TCP) nas métricas do CloudWatch. Ao usar o console do CloudWatch, consulte as dimensões de métricas adicionais de DiscoveryName, (DiscoveryName, ServiceName, ClusterName), TargetDiscoveryName e (TargetDiscoveryName, ServiceName, ClusterName) no namespace do Amazon ECS. Para obter mais informações sobre essas métricas e dimensões, consulte Visualizar métricas disponíveis no Guia do usuário do Amazon CloudWatch Logs.