如何为在 EC2 模式下在 AWS ECS 集群中运行的容器分配公共 IP

Dav*_*ron 7 amazon-web-services amazon-ecs amazon-vpc aws-nat-gateway

我正在尝试使用服务之间的服务发现来实现多服务 ECS 集群。我正在尝试按照教程创建使用 Amazon ECS CLI 使用服务发现的 Amazon ECS 服务。但是,它不包括完整的工作示例

我所做的是定义两个服务,通过使用定义:

  • docker-compose.yml
  • ecs-params.yml

我可以轻松调出 ECS 集群和这两个服务。一切看起来都不错。但其中一项服务需要公共 IP 地址。所以在相应的ecs-params.yml文件中,我把assign_public_ip: ENABLED. 但是没有分配公共 IP 地址。在 ECS 控制台中,服务详细信息显示Auto-assign public IP DISABLED为 ,对于任务,它列出了私有 IP 地址,没有公有 IP 地址。

不幸的是,根据网络模式任务网络awsvpc的文档,这似乎是不可能的:

该 awsvpc 网络模式不为使用EC2启动类型任务提供任务ENIS与公网IP地址。要访问 Internet,应在配置为使用 NAT 网关的私有子网中启动使用 EC2 启动类型的任务。有关更多信息,请参阅 Amazon VPC 用户指南 中的 NAT 网关。入站网络访问必须来自使用私有 IP 地址的 VPC 内,或从 VPC 内通过负载均衡器路由。在公共子网中启动的任务无法访问 Internet。

问题:如何解决 AWS ECS EC2 启动类型的这种限制?

我不明白为什么 EC2 启动类型不支持公共 IP 地址?或者 - 我是否使用不同的网络模式,然后分配一个公共 IP 地址?为什么 AWS 文档没有更清楚地说明这一点?

源代码

集群是使用以下方法创建的:

ecs-cli up --cluster-config ecs-service-discovery-stack --ecs-profile ecs-service-discovery-stack --keypair notes-app-key-pair --instance-type t2.micro --capability-iam --force --size 2
Run Code Online (Sandbox Code Playgroud)

正如上面的教程所建议的那样,定义了两个服务。该backend(容器中的一个简单的Node.js应用程序)和frontend(配置为代理到后端一个简单的NGINX服务器)服务,各自在自己的目录中。在每个目录中是docker-compose.ymlecs-params.yml文件。

使用以下方法启动前端服务:

ecs-cli compose --project-name frontend service up --private-dns-namespace tutorial --vpc ${VPC_ID}  --enable-service-discovery --container-port 80 --cluster ecs-service-discovery-stack --force-deployment
Run Code Online (Sandbox Code Playgroud)

docker-compose.yml是:

version: '3'

services:
    nginx:
        image: USER-ID.dkr.ecr.REGION.amazonaws.com/nginx-ecs-service-discovery
        container_name: nginx
        ports:
            - '80:80'
        logging:
            driver: awslogs
            options: 
                awslogs-group: simple-stack-app
                awslogs-region: REGION
                awslogs-stream-prefix: nginx
Run Code Online (Sandbox Code Playgroud)

ecs-params.yml是:

version: 1
task_definition:
    task_execution_role: ecsTaskExecutionRole
    ecs_network_mode: awsvpc
    task_size:
        mem_limit: 0.5GB
        cpu_limit: 256
run_params:
    network_configuration:
        awsvpc_configuration:
            subnets:
                - "subnet-00928d3fc1339b27b"
                - "subnet-0ad961884e5f93fb1"
            security_groups:
                - "sg-0c9c95c6f02597546"
        # assign_public_ip: ENABLED
Run Code Online (Sandbox Code Playgroud)

后端服务提出了使用类似的命令和类似docker-compose.ymlecs-params.yml文件。

sha*_*aws 8

您是对的,使用 EC2 启动类型时,无法为 ECS 任务分配公共 IP。

对于awsvpc 以外的网络模式,它们也无济于事:

  • 如果网络模式设置为 none,则任务的容器没有外部连接,并且无法在容器定义中指定端口映射。
  • 如果网络模式为 bridge,则任务使用 Docker 的内置虚拟网络,该网络在每个容器实例中运行。
  • 如果网络模式为 host,则任务绕过 Docker 的内置虚拟网络并将容器端口直接映射到 Amazon EC2 实例的网络接口。在这种模式下,当使用端口映射时,您无法在单个容器实例上运行同一任务的多个实例。

选项 A - 负载均衡器

如果您希望从 Internet 访问您的任务,您可以考虑创建带有负载均衡器的 ECS 服务,以便客户端能够将请求路由到您的任务。请注意,具有使用 awsvpc 网络模式的任务的服务仅支持应用程序负载均衡器和网络负载均衡器。

选项 B - Fargate 启动类型

另一个选项是将 ECS 任务配置为使用 Fargate 启动类型接收公共 IP 地址:

当您使用 Fargate 启动类型创建 ECS 服务/任务时,您可以选择是否将公网 IP 关联到 ECS 任务使用的 ENI。您可以参考如何配置网络以了解如何在 ECS 中使用 Fargate 类型服务配置公共 IP。基于这样的配置,一旦任务运行,任务使用的网卡要有公网IP,就可以让你直接通过网络访问任务。