ECS 任务未启动 - 已停止(CannotPullContainerError:“来自守护程序请求的错误响应在等待连接时取消”

Posted

技术标签:

【中文标题】ECS 任务未启动 - 已停止(CannotPullContainerError:“来自守护程序请求的错误响应在等待连接时取消”【英文标题】:ECS task not starting - STOPPED (CannotPullContainerError: “Error response from daemon request canceled while waiting for connection” 【发布时间】:2020-02-29 09:08:32 【问题描述】:

我正在使用 Fargate 在 ECS 中启动一项任务,在 PENDING 一段时间后它以 STOPPED 结束并出现以下错误:

STOPPED (CannotPullContainerError: "Error response from daem

当我展开我看到的细节时

STOPPED (CannotPullContainerError: "Error response from daemon: Get https://id.dkr.ecr.ap-southeast-2.amazonaws.com/v2/: net/http: request canceled while waiting for connection"

原因

(Client.Timeout exceeded while awaiting headers)

所以任务由于某种原因无法访问容器,但我不确定缺少什么权限以及来自什么资源。我已经阅读了一些,我发现唯一真正的建议是将 AssignPublicIp: ENABLED 添加到 AwsvpcConfiguration 但这没有帮助。

【问题讨论】:

【参考方案1】:

所以看起来错误消息在某些时候发生了变化:https://aws.amazon.com/premiumsupport/knowledge-center/ecs-pull-container-api-error-ecr/ 有一些步骤可以解决,但提到错误 CannotPullContainerError: API error 可能与 CannotPullContainerError: "Error response from daem 同义?

至少对我来说,创建 AWS::EC2::VPCEndpoint 似乎让我更进一步。

【讨论】:

【参考方案2】:

我通过在 ECS 上为使用我的服务创建的每个 Fargate 实例启用公共 IP 来修复此错误。

服务配置:


  ...
  "networkConfiguration": 
    "awsvpcConfiguration": 
      "subnets": [
        "my-subnets",
      ],
      "securityGroups": [
        "my-security-group"
      ],
      "assignPublicIp": "ENABLED" // <-- ENABLED HERE
    
  ,

【讨论】:

我同意这应该可行,但由于安全策略,我无法将公共 IP 地址分配给 Fargate 实例。 这个解决方法对我有用。你能解释一下为什么吗?仅供参考 - 我正在运行 Fargate 实例。【参考方案3】:

我使用 Fargate 找到了适合我的解决方案。他们的文件指出:

    如果您正在使用 Amazon Elastic Compute Cloud (Amazon EC2) 启动类型运行任务并且您的容器实例位于私有子网中,或者如果您正在使用 AWS Fargate 启动类型在私有子网中运行任务,确认您的子网在路由表中有到 NAT 网关的路由。

这只是意味着,

    您必须找到您使用的 VPC。 然后在您拥有 VPC 的表中,您将找到它的主路由表。 打开路由表,然后确保您有链接到 Internet 网关的条目。

它看起来像igw-006b1917dc348d10d。完成后,您的 vpc 将可以访问互联网,并能够获取您的 ECR 图像。

来源:AWS docs

【讨论】:

【参考方案4】:

Alan Sereb 的解决方案对我有用。

似乎在AWS launched Fargate platform version 1.4.0 之后,使用配置了 ECS 服务的 VPC 完成了对远程映像注册表(如我的情况下是 Gitlab 注册表)的访问。

所以现在 Fargate 容器网络接口(以及 ECS 使用的 VPC)需要有 Internet 访问权限,因此必须在 VPC 路由表中设置 Internet 网关。

【讨论】:

【参考方案5】:

这是一个错误,当您无法拉取图像时出现。它可能有很多原因,例如 VPC 内部的权限和 Internet 访问。

如果您的 VPC 是仅限公共子网,那么您需要添加 Internet 网关以访问 Internet。 如果您的 VPC 仅是私有的,那么您需要一个 NAT 网关,以便该任务可以访问 docker 映像以进行拉取。

【讨论】:

【参考方案6】:

原因是运行任务定义的服务没有连接到互联网。

我有它,因为我的 vpc 在公共子网中,并且该服务没有公共 IP 地址。

以of this answer 为基础,如果您使用python cdk 创建服务,您可以在创建服务时指定服务中的任务是否应使用公共IP 地址以及子网和安全组。

基本上,你应该有这样的东西..:

service = ecs.FargateService(self,
                             "service-name",
                             cluster=cluster,
                             task_definition=task_definition,
                             service_name="service-name", 
                             assign_public_ip=True, # this is important
                             security_groups=[list of security groups , also important],
                             vpc_subnets=[list of subnets]
                             )

有关 FragateService 的更多信息,请参阅this

如果您使用的是 cli,您可以使用以下命令更新您的服务:

aws ecs update-service --service service-name --cluster the_Cluster  --network-configuration "
    \"awsvpcConfiguration\": 
      \"subnets\": [\"subnet-***\",\"subnet-****\",\"subnet-*****\"],
      \"securityGroups\": [\"sg-******\"],
      \"assignPublicIp\": \"ENABLED\"
    

有关如何更新服务检查的更多信息this

【讨论】:

【参考方案7】:

使用 Fargate 拉取映像 ECS 使用必须具有策略 AmazonECSTaskExecutionRolePolicy 的任务执行角色(例如:ecsTaskExecutionRole)。

当从 ECR 外部的私有存储库中提取图像时,此任务执行角色将需要在远程容器注册表中进行身份验证,因此正如 AWS 文档所述 https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html,它需要一个带有凭证的密钥,并且对于任务执行角色来说访问秘密,也是一个内联策略secretsmanager:GetSecretValue

假设映像可在任何容器注册表(DockerHub、ECR、GitLab 等)中公开访问,则可能涉及其他内容。

    确保您的 VPC 已将 DNS resolution 设置为 Enable,否则它将无法访问外部 URL 确保运行 fargate 服务的子网可以访问互联网。如果它们是公共的,子网将有一个路由表将流量重定向到任何 IP (0.0.0.0/0) 到 Internet 网关。否则,他们将不得不使用 NAT 网关作为跳转服务来访问互联网。 确保您在子网级别的 NACL 和正在使用的安全组允许传出和传入流量。

附带说明一下,VPC 下有一项称为可达性分析器的服务,可让您检查连接路径并检测 NACL 或路由表中的任何错误。例如,您可以验证任何子网中的网络接口是否可以访问 Internet 网关。它用作跟踪路由。

【讨论】:

【参考方案8】:

我也遇到了同样的问题。经过调查,我看到何时禁用 Auto-assign public IP 我们必须通过与 NAT 网关关联的私有子网将您的服务连接到公共互联网。

这里一步一步来:

1.创建 2 - 3 个私有子网

2。创建新的路由表并与这些子网关联

3.创建 NAT 网关

-- 分配您的私有子网之一

-- 使用上述子网创建服务

【讨论】:

以上是关于ECS 任务未启动 - 已停止(CannotPullContainerError:“来自守护程序请求的错误响应在等待连接时取消”的主要内容,如果未能解决你的问题,请参考以下文章

在 Beanstalk 部署或 ECS 任务不使用时安排 EC2 实例的停止/启动?

AWS ECS Fargate 未创建任务 AmazonECSTaskExecutionRole 错误

ECS 停止实例

优雅地停止 ecs 容器

ECS 容器实例生命周期

ECS任务定义App Mesh虚拟节点名称未通过控制台设置