如何让 AWS ECS 自动将我的容器的端口映射到主机(EC2)

Posted

技术标签:

【中文标题】如何让 AWS ECS 自动将我的容器的端口映射到主机(EC2)【英文标题】:How to have AWS ECS automatically map ports of my container to the host machine(EC2) 【发布时间】:2021-02-14 07:50:31 【问题描述】:

上下文:

我正在使用 Circle CI 的 aws-ecs/deploy-service-update orb 来部署我的 docker 容器,方法是拉取 AWS ECR 中的最新映像,并将其部署在带有 AWS EC2 实例的 AWS ECS 中。这个容器是一个机器学习模型,它在 TCP 端口 3000(我为此使用fastAPI)接受 API 请求并返回预测。部署后,我无法向在端口 3000 部署容器的任务的容器实例的公共 IP 发送请求(此 IP 不是我的 EC2 实例的公共 IP;它只有私有 IP,公共 IP 已禁用) .

调试

    我检查了我的安全组,并确保端口 3000 已打开以接收来自所有 IP (0.0.0.0) 的请求,作为入站规则的一部分。 我停止了任务(这将自动停止在 EC2 实例中运行的容器),并认为 Circle CI 可能出现了问题。然后,根据 AWS ECS 的服务配置(1 个期望任务)和任务定义,自动启动了一个新任务(因此是容器)。但是,我也无法向它发送请求。 我通过 SSH 连接到我的 EC2 实例以了解端口 3000 是否打开。这是我了解到端口根本没有映射的时候: 如您所见,容器的 PORTS 列是空的,容器必须接受来自命令的 3000 端口的请求。

以下是 EC2 实例的开放端口: 如您所见,此处未列出端口 3000。


这是部署容器(到 AWS ECS)的端口映射任务,您在上面看到 docker ps 屏幕截图: 在任务定义中可以看到我为容器定义的端口映射。


这是在我的 EC2 实例上运行的任务,任务定义如上所示,我使用的网络模式是“awsvpc”:


这里是与任务关联的 ENI 的“网络”选项卡,以及与运行任务的 EC2 实例关联的安全组的入站规则,它接受来自所有 IP 的端口 3000 上的请求。

编辑 1:

之后

docker run -p 3000:3000 <my-image:my-tag>

在 EC2 机器内(通过从我的笔记本电脑进行 SSH 连接),我可以发送 API 请求并接收对容器的正确响应,以响应 AWS ECS 集群的公共 IP。这意味着只有在我手动运行容器时才会映射端口。

当我使用 FARGATE、从 Circle CI 更新服务时,甚至当我手动启动任务时,我的端口都没有问题。

那么,当从 AWS ECS 服务仪表板或 Circle CI 运行任务时,如何自动映射端口?如果我手动运行 docker 容器,我将无法从 AWS Cloudwatch 自动获取日志,也无法从 AWS ECS 控制面板停止它。 AWS 在 EC2 实例中运行的另一个容器将负责这些事情。它将日志路由到 Cloudwatch 并接受停止现有日志并启动命令以使用存储在 AWS ECR 中的新映像启动新容器,而无需每次我想查看日志或启动/停止容器时都使用 SSH。

这里出了什么问题,导致端口未映射以及如何修复它并正确映射端口,以便我能够将 API 请求发送到我的容器。

【问题讨论】:

【参考方案1】:

awsvpc 网络模式端口映射的工作方式略有不同。 hostPort 在这里不是有效选项,创建的 ENI 会将容器端口暴露给 VPC。

此模式有几个先决条件,例如 ECS 代理版本、实例类型(ENI 计数限制)、实例配置文件……查看官方 AWS 文档: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-networking.html

您是否检查了连接的 ENI 以及这些 ENI 上打开了哪些端口?

【讨论】:

是的,此任务附加了一个 ENI。但我没有看到任何显示开放端口的选项。附加到此 ENI 的安全组具有向所有 IP 开放端口 3000 的入站规则。而且我还禁用了所有级别的公共 IP。 检查我的编辑。我已经展示了附加到任务的 ENI,它是入站规则,它将端口 3000 暴露给所有 IP。 TBH,我对您在答案中链接的文档了解不多。 非常感谢 f7o 的回答!!我遇到了同样的问题,我无法访问 Fargate 容器中的应用程序。最后,我检查了子网上 ENI 上的端口映射,发现只有 PORT 80 被映射,尽管在我的任务定义中我的端口映射为 3000。至少,我现在有一个解决方法:)【参考方案2】:

我犯的错误是使用 FARGATE 优化集群和其中的 EC2 实例;这可能导致我的应用程序无法使用网络模式(默认、网桥、主机、awsvpc 和无)。因此,当我重做一切与上次相同但使用 EC2 优化集群类型时,bridge 网络模式按预期工作。

【讨论】:

以上是关于如何让 AWS ECS 自动将我的容器的端口映射到主机(EC2)的主要内容,如果未能解决你的问题,请参考以下文章

AWS ECS 使用 docker 和 nginx,如何将我的 nginx 配置放入容器中?

没有链路和端口映射,如何让容器在 ECS 中相互通信?

AWS ECS Fargate 和端口映射

AWS 目标组在同一个 ECS 任务上注册 2 个目标?

AWS ECS Docker 容器 Boto3 IAM 权限

将多个 docker 容器部署到 AWS ECS