AWS Fargate资源初始化错误:无法拉取密钥或注册表授权:拉取命令失败:信号:被终止

51

这个问题让我有点崩溃...我正在尝试在公共子网的VPC上运行Fargate中的Docker镜像。当我将其作为任务运行时,出现以下错误:

ResourceInitializationError: unable to pull secrets or registry auth: pull
command failed: : signal: killed

如果我在私有子网中通过NAT运行任务,则可以正常工作。如果我在默认VPC的公共子网中运行它,它也可以正常工作。
我已经查看了这里的建议: Aws ecs fargate ResourceInitializationError: unable to pull secrets or registry auth 特别是,我设置了安全组以允许所有流量。网络ACL设置为允许所有流量。我甚至非常慷慨地授予了IAM权限,以尝试消除可能性:
任务执行角色具有:
   {
        "Action": [
            "kms:*",
            "secretsmanager:*",
            "ssm:*",
            "s3:*",
            "ecr:*",
            "ecs:*",
            "ec2:*"
        ],
        "Resource": "*",
        "Effect": "Allow"
    }

通过信任关系,允许ecs-tasks扮演此角色:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

安全组是:

sg-093e79ca793d923ab All traffic All traffic All 0.0.0.0/0

网络访问控制列表(Network ACL)如下:

Inbound
Rule number Type Protocol Port range Source Allow/Deny
100 All traffic All All 0.0.0.0/0    Allow
*   All traffic All All 0.0.0.0/0    Deny

Outbound
Rule number Type Protocol Port range Destination Allow/Deny
100 All traffic All All 0.0.0.0/0    Allow
*   All traffic All All 0.0.0.0/0    Deny

我在子网上设置了流日志,并且可以看到双向流量都被接受。

我没有设置任何接口终端来直接访问AWS服务而不经过Internet Gateway。

同时,我创建Fargate实例时分配了公共IP地址。

这应该可以正常工作,因为公共子网应该通过Internet Gateway访问所有所需的服务。在默认VPC或私有子网中也可以正常工作。

有人能建议我检查什么以调试此问题吗?

8个回答

50

ResourceInitializationError: unable to pull secrets or registry auth: pull command failed: : signal: killed 的一个潜在问题是禁用了自动分配公共 IP。在我重新创建服务并启用它后,任务成功运行且没有出现问题。

enter image description here


1
嗨Chez。我更新了答案,添加了截图,您可以在其中配置自动分配公共IP。 - valdem
25
如果您不想让任务拥有公共 IP,该怎么办? - TheRennen
2
对于私有子网,您很可能需要一个 NAT 网关。这也允许您拥有没有公共 IP 的任务。需要注意的是,NAT 网关非常昂贵。通常最好使用公共 IP 和安全组进行锁定。 - morras
@valdem - 非常感谢,你救了我的一天!(顺便说一句,这个问题似乎非常奇怪 - 据我所知,我们应该能够在公共子网中运行没有公共IP的实例) - Vitaly Karasik DevOps
1
没有公共IP,您的实例无法与互联网通信(或在这种情况下是ECR注册表,它位于VPC之外),因为接收端不知道将数据包发送回哪里。在私有子网的情况下,NAT网关具有公共IP(并且它可以将数据包路由回原始实例,因为NAT位于子网内)。 - Kicsi
显示剩余3条评论

15

根据@nathan和@howard-swope的反馈进行了编辑

检查清单:

  • VPC启用了“DNS主机名”和“DNS解析”
  • “任务执行角色”具有访问ECR的权限,例如拥有AmazonECSTaskExecutionRolePolicy角色

如果任务在公共子网上运行:

  • 子网可以访问互联网,即向子网分配互联网网关。

  • 创建任务时启用“分配公共IP”选项。

如果任务在私有子网上运行:

  • 子网可以访问互联网,即向子网分配NAT网关。 … NAT网关位于公共子网上

1
这是一个很好的清单,适用于在私有子网中运行容器并配置VPC路由表以通过位于公共子网中的NAT网关路由出站流量的任务。 - Nathan
3
@Nathan,我不确定这是否准确。如果您正在谈论ECS任务,我认为它们并不是从容器中触发的,而是相反的。任务会拉取和启动容器。如果您的容器在私有子网中运行,则不应具有公共IP地址。这就是私有子网的意义,不是吗? - Howard Swope
1
关于任务拉取容器的问题,您是正确的。ECR不位于私有子网中,__某些东西__需要处理它。对于在私有子网中运行的任务,可以使用NAT网关处理数据包解析,或者分配公共IP地址。 - Nathan
1
@HowardSwope 你说得对。我的原始帖子假设任务在公共子网中。 我会编辑我的回答。 感谢反馈! :) - Koroslak

15

对于那些不幸的人,还有一件要检查的事情。

我已经在我的VPC中拥有一个Internet网关,DNS已启用,所有容器都获得了公共IP,执行角色已经可以访问ECR。但即使如此,我仍然收到相同的错误。

事实证明问题出在路由表上。我的VPC的路由表没有包括将出站流量定向到Internet网关的路由,因此我的子网无法访问互联网。

在该表中添加第二行以将0.0.0.0/0流量路由到Internet网关解决了这个问题。

输入图像描述


终于成功了!!谢谢!!! - Joshua Marble
这终于成功了!! - Beraki
谢谢你,你救了我的一天!!!在清理的时候,我可能不小心删除了这个关联,所以想知道出了什么问题。 - Raj
救星,谢谢。我的路由表指向一个不存在的NAT网关,这是导致问题的原因。 - Brandon Dooley

12

我遇到了同样的问题。但在我的情况下,我是使用RunTask操作从Lambda函数触发Fargate容器的。所以在RunTask操作中,我没有传递以下参数:

assignPublicIp: ENABLED

添加此参数后,容器就可以正常触发。


6

事实证明我没有启用VPC的DNS支持。启用后,它可以正常工作。

我没有在任何关于Fargate的文档中明确提到DNS支持 - 我猜这很显然,否则它将如何查找所需的各种AWS服务。但我认为值得在回答中注意这个错误信息。


您是否需要为容器使用的每个服务添加VPC端点? - santamanno
@santamanno 是的,您需要为每个服务创建一个VPC终端节点。 - Irtiza
是的,谢谢。它必须位于公共子网、带有NAT的私有子网或所需服务的私有VPC端点上。无论如何,正如OP指出的那样,根据我的经验,DNS解析必须启用。 - santamanno

4
对于使用Fargate的AWS Batch,此错误是由“禁用分配公共IP”设置所触发。
该设置可在“作业定义”步骤中配置。然而,在“作业定义”已经创建之后,它在UI中不可配置。 enter image description here

这很有帮助,主要答案没有指明在哪里启用此参数,因为我正在使用CDK创建我的作业定义,所以我没有遇到“创建服务”界面。 - Outpox
对于boto3,我花了一点时间才找到它。对于JobDefinition,它位于ContainerProperties > NetworkConfiguration > AssignPublicIp: ENABLED下。https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-jobdefinition-containerproperties-networkconfiguration.html - Moemars
这非常有用,可以在创建现有的“作业定义”的新版本时完成。 - isudarsan

3
AWS容器运行程序需要访问容器仓库和AWS服务。
如果您在公共子网上,则最简单的方法是“自动分配公共IP”,即使您的应用程序不需要对Internet进行出站访问,也可以让您的容器访问Internet。
否则,如果您仅使用AWS服务(ECR,并且没有从docker.io拉取的镜像),则可以使用VPC端点来访问ECR/S3/Cloudwatch,并在VPC上启用DNS选项。
对于私有子网,情况也是一样的。
如果您使用docker.io镜像,则您的子网无论如何都需要对Internet进行出站访问。

1
抱歉,不起作用。我有一个带有NAT的私有子网(并尝试过没有),并且所有端点都添加到了VPC中,但仍然无法访问... - santamanno
1
如果您在私有网络上拥有一个用于出口流量的NAT网关(实例/任务没有Internet网关/公共IP),甚至不需要使用VPC端点。我建议您在子网上启动一个EC2实例,ssh到该实例,并在那里测试您的连接性。AWS网络设置可能会非常令人沮丧,以确保正确设置。 - FredG

1
在处理上述错误时,我通过运行run-task命令(而不是通过服务路由)时,没有在aws ecs run-task --network-configuration中指定安全组。这导致任务VPC中选择默认SG。该VPC中的默认SG未定义任何入站/出站规则。我只添加了出站规则以允许所有流量到达任何地方,错误就消失了。
我的设置是ECS/Fargate任务将在私有子网中运行,并通过VPC接口端点连接ECR。我检查了上面提到的清单,并额外添加了SG规则。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接