如何为在 EC2 模式下运行在 AWS ECS 集群中的容器分配公共 IP
Posted
技术标签:
【中文标题】如何为在 EC2 模式下运行在 AWS ECS 集群中的容器分配公共 IP【英文标题】:How to assign a public IP to container running in AWS ECS cluster in EC2 mode 【发布时间】:2020-07-07 18:38:14 【问题描述】:我正在尝试使用服务之间的服务发现来实现多服务 ECS 集群。我正在尝试遵循教程Creating an Amazon ECS Service That Uses Service Discovery Using the Amazon ECS CLI。但是,它不包含完整的工作示例
我所做的是定义两个服务,通过使用定义:
docker-compose.yml
ecs-params.yml
我可以轻松启动 ECS 集群和这两个服务。一切看起来都不错。但是其中一项服务需要公共 IP 地址。所以在对应的ecs-params.yml
文件中,我放了assign_public_ip: ENABLED
。但是没有分配公共 IP 地址。在 ECS 控制台中,服务详细信息为 Auto-assign public IP DISABLED
,对于任务,它列出了私有 IP 地址,没有公有 IP 地址。
不幸的是,根据Task Networking with the awsvpc
Network Mode 上的文档,这似乎是不可能的:
awsvpc
网络模式不为使用 EC2 启动类型的任务提供具有公共 IP 地址的任务 ENI。要访问 Internet,应在配置为使用 NAT 网关的私有子网中启动使用 EC2 启动类型的任务。有关更多信息,请参阅 Amazon VPC 用户指南中的 NAT Gateways。入站网络访问必须使用私有 IP 地址从 VPC 内部进行,或者从 VPC 内部通过负载均衡器进行路由。在公共子网中启动的任务无法访问互联网。
问题:如何解决 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
根据上述教程的建议,定义了两个服务。 backend
(容器中的简单 Node.js 应用程序)和 frontend
(配置为代理到后端的简单 nginx 服务器)服务都在各自的目录中。每个目录下都有docker-compose.yml
和ecs-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
它的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
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
使用类似的命令和类似的docker-compose.yml
和ecs-params.yml
文件启动后端服务。
【问题讨论】:
您确定您的子网是公共的,并且它们启用了自动分配公共 IP 吗? 同样的问题:| 【参考方案1】:你是对的,当使用 EC2 启动类型时,无法为 ECS 任务分配公共 IP。
关于 network modes 除了 awsvpc,他们也无济于事:
如果网络模式设置为none
,则任务的容器没有外部连接,并且无法在容器定义中指定端口映射。 如果网络模式是bridge
,则任务使用 Docker 的内置虚拟网络,该网络在每个容器实例内运行。 如果网络模式为host
,则任务会绕过 Docker 的内置虚拟网络并将容器端口直接映射到 Amazon EC2 实例的网络接口。在此模式下,当使用端口映射时,您无法在单个容器实例上运行同一任务的多个实例化。
选项 A - 负载均衡器
如果您希望从 Internet 访问您的任务,您可以考虑创建集成了负载均衡器的 ECS 服务,以便客户端能够将请求路由到您的任务。请注意,具有使用 awsvpc 网络模式的任务的服务仅支持 Application Load Balancer 和 Network Load Balancer。
选项 B - Fargate 启动类型
另一种选择是将 ECS 任务配置为使用 Fargate 启动类型接收公共 IP 地址:
当您使用 Fargate 启动类型创建 ECS 服务/任务时,您可以选择是否将公共 IP 关联到 ECS 任务使用的 ENI。您可以参考如何Configure a Network了解如何在ECS中使用Fargate Type服务配置公网IP。基于此配置,一旦任务运行,任务使用的网卡必须有公网IP,才能让你直接通过互联网访问任务。
【讨论】:
以上是关于如何为在 EC2 模式下运行在 AWS ECS 集群中的容器分配公共 IP的主要内容,如果未能解决你的问题,请参考以下文章
如何为 ECS 添加带有应用程序负载均衡器的 AWS API 网关?
AWS Elastic Beanstalk 与 EC2 容器服务 (ECS) - Docker