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

时间:2020-11-01 13:11:41

标签: amazon-web-services amazon-ec2 port amazon-ecs

上下文:

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

调试

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

这是EC2实例的开放端口: enter image description here 如您所见,端口3000未在此处列出。


以下是带有端口映射的任务,该任务已将容器(部署到AWS ECS)部署到了docker ps上面的屏幕截图中: enter image description here
在任务定义中,您可以看到我为容器定义的端口映射。


这是在EC2实例上运行的任务,上面显示了任务定义,并且我正在使用的网络模式是“ awsvpc”: enter image description here


这是与任务关联的ENI的“网络”选项卡,以及与任务在其中运行的EC2实例关联的安全组的入站规则,该规则从所有IP接受端口3000上的请求。 enter image description here

编辑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 个答案:

答案 0 :(得分:2)

对于awsvpc网络模式,端口映射的工作方式略有不同。 hostPort在这里无效,创建的ENI将容器端口公开给VPC。

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

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