Aws fargate ResourceInitializationError: 无法获取秘密或注册表身份验证

我试图在 aws-ecs-fargate-1.4.0平台上运行一个私有存储库。

对于私有存储库身份验证,我遵循了 医生,它工作得很好。

在多次更新现有服务之后,无论如何都无法运行任务并报告错误,比如

ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to get registry auth from asm: service call has been retried 1 time(s): asm fetching secret from the service for <secretname>: RequestError: ...

我没有更改 ecsTaskExecutionRole,它包含了获取秘密值所需的所有策略。

  1. 角色执行策略
  2. CloudWatchFullAccess
  3. 角色执行策略
  4. 获取 Secret Value
  5. 参数
107817 次浏览

当 Fargate 代理未能创建或引导启动容器所需的资源或任务属于。只有在使用平台版本1.4或更高版本时才会发生此错误,最有可能的情况是使用 因为版本1.4使用了 Task ENI(在您的 VPC 中)而不是 Fargate ENI (在 AWS 的 VPC 中)。我认为这可能是由于需要额外的 IAM 权限才能从 ECR 中提取图像。你有使用私人连线吗?如果是,您可能需要查看 ECR 端点的策略。

我将尝试复制它,但我建议如果可以的话,用 AWS 打开一个支持 Ticket,这样他们就可以更仔细地查看您的资源并提出更好的建议。

确保通过 IGWNAT的互联网连接,并确保启用公共 IP,如果其 IGW 在远门任务/服务网络配置。

{
"awsvpcConfiguration": {
"subnets": ["string", ...],
"securityGroups": ["string", ...],
"assignPublicIp": "ENABLED"|"DISABLED"
}
}

我不完全确定你的设置,但是在我关闭 NAT-Gateways 以节省一些 $之后,我在 aws-ecs-fargate-1.4.0平台上有一个非常相似的错误消息:

Stopped reason: ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve ecr registry auth: service call has been retried 1 time(s): RequestError: send request failed caused by: Post https://api.ecr....

事实证明,我必须为这些服务名称创建 VPC 端点:

  • 亚马逊区域3
  • Com.amazonaws.Region.ecr.dkr
  • Com.amazonaws.Region.ecr.api
  • 亚马逊,区域,日志
  • 亚马逊

我不得不降级到 aws-ecs-fargate-1.3.0平台。降级后,Docker 图像可以从 ECR 中提取出来,部署再次成功。

如果您正在使用没有 NAT-Gateway 的秘密管理器,那么可能需要为 com.amazonaws.REGION.secretsmanager创建一个 VPC 端点。

我通过更新 ECS 服务的安全组中的规则解决了类似的问题。

Inbound Rules:
* HTTP          TCP   80    0.0.0.0/0
Outbound Rules:
* All traffic   All   All   0.0.0.0/0


我在使用 Fargate 作为平台版本 1.4.0的启动类型时遇到了完全相同的问题。最后,由于我使用的是公共子网,所有我需要做的就是 允许公共 IP 的分配到任务,以便允许任务有出站网络访问来拉图像。

当我尝试使用平台版本 1.3.0创建服务时,我得到了解决这个问题的提示,但是任务创建失败,出现了类似的但是 幸运的记录在案错误。

由于 FARGATE 版本1.4.0中的 ECS 代理使用任务 ENI 来检索信息,因此对 Secret Manager 的请求将通过这个 ENI。

您必须确保到 Secret Manager api (Secret smanager. { region } . amazonaws.com)的流量是“开放的”:

  • 如果您的任务是私有的,那么您必须有一个 vpc 端点(com.amazonws)。{区域}。或者一个 NAT 网关,并且 ENI 的安全组必须允许 https 向其发送流量。

  • 如果您的任务是公共的,则安全组必须允许 https 向外发送流量(或 AWS 公共 cidr)。

如果使用的是 选择「不要指定公共地址」,则可能发生此错误。

如果您有一个私有子网,并且在您的 VPC 中没有互联网网关或 NAT 网关,也可以使用同样的方法。它需要一条上网的路线。

这在所有 AWS 生态系统中都是相同的行为。如果 AWS 能够在这种情况下显示一个大的横幅警告,那就太好了。

如果你的 Fargate 运行在一个私有子网中,没有互联网接入,技术上来说,你的 vpc 应该已经有 dkr vpc 端点,这样你的 Fargate (版本1.3及以下)就可以到达那个端点并旋转容器。对于 Fargate 的 ver1.4,只需要额外的 api ecr 端点。

Https://aws.amazon.com/blogs/containers/aws-fargate-launches-platform-version-1-4/

我是 AWS 的员工。

您所看到的是由于 Fargate 平台版本1.3.0和 Fargate 平台版本1.4.0之间的网络工作方式发生了变化。作为从使用 Docker 到使用容器变化的一部分,我们还对网络的工作方式做了一些更改。在版本1.3.0及以下版本中,每个 Fargate 任务都有两个网络接口:

  • 一个网络接口用于来自应用程序容器的应用程序流量,以及日志和容器映像层拉动。
  • Fargate 平台使用了一个二级网络接口 本身,以获得 ECR 认证凭据,并获取机密。

不过,这种辅助网络接口有一些缺点。这个次要流量没有出现在您的 VPC 流量日志中。而且,虽然大多数流量停留在客户 VPC,辅助网络接口发送流量以外的您的 VPC。一些客户抱怨说,他们没有能力在这个辅助网络接口上指定网络级别控制以及它能够连接到什么。

为了使网络模型不那么令人困惑,并给予客户更多的控制,我们在 Fargate 平台1.4.0版本中更改为使用单一网络接口,并将所有流量保持在您的 VPC 内,甚至 Fargate 平台流量。用于获取 ECR 认证和任务秘密的 Fargate 平台流量现在使用与您的其余任务流量相同的任务网络接口,您可以在 VPC 流量日志中观察这种流量,并使用您自己的 AWS VPC 中的路由表控制这种流量。

然而,随着观察和控制 Fargate 平台网络的能力的提高,您还要负责确保在您的 VPC 中实际配置了一个网络路径,允许任务与 ECR 和 AWS 保密管理器通信。

有几种方法可以解决这个问题:

  • 将任务启动到具有公共 IP 地址的公共子网中,以便它们能够使用因特网网关与 ECR 和其他后台服务通信
  • 在私有子网中启动任务,该私有子网具有 VPC 路由表,该路由表配置为通过公共子网中的 NAT 网关路由出站流量。这样,NAT 网关可以代表任务打开到 ECR 的连接。
  • 在私有子网中启动任务,并确保在 VPC 中配置了用于所需服务的 AWS PrivateLink 端点(用于图像拉身份验证的 ECR、用于图像层的 S3和用于机密的 AWS 保密管理器)。

您可以在这篇官方博客文章的“任务弹性网络接口(ENI)现在运行额外的流量流”一节中了解更多关于这一变化的信息

Https://aws.amazon.com/blogs/containers/aws-fargate-launches-platform-version-1-4/

我刚刚遇到了这个问题,之所以会遇到这个问题,是因为我忘记向与我的服务相关联的安全组添加入站和出站规则。(添加从我的 ALB 入站和出站 *)

服务的安全组需要在端口443上进行出站访问(所有端口上的出站访问都可以满足这个要求)。没有这个,它就无法访问秘密管理器。

对我来说,这是一个组合,没有 秘密经理读写政策附加到我的 IAM 角色(感谢 Jinkko) ; 和 没有在计算实例上启用公共 ip (以获得 ECR 回购)

这个问题今天已经让我焦头烂额,我想我应该分享一下我的经验,因为它与以上几乎所有问题都不同(AWS Employee 的回答在技术上涵盖了这个问题,但没有详细说明问题所在)。

如果以下所有情况均属实:

  • 您正在运行的是1.4.0平台(或者更新的平台——在编写本文时,1.4.0是最新的平台)
  • 你在一个 VPC 环境中
  • 您的 VPC (代表“ 原因”)运行自己的 DNS (即不在 VPC _ BASE + 2)
  • 对于“ 原因”,您不允许所有的出站流量,因此要在任务安全组上设置出口规则

因此,所有事物都有端点,那么下面的结果也必须是正确的:

  • 您自己开发的 DNS 需要能够正确地解析端点的私有地址(例如,使用 VPC _ BASE + 2,但如何解析并不重要)
  • 您还需要确保您的任务安全组具有允许 DNS 流量到您的 DNS 服务器的规则。

雪上加霜的是,你从 Fargate 得到的一点点错误信息并不能真正表明你有 DNS 问题,当然你的 CloudTrails 也不会显示任何该死的东西,因为从一开始就没有任何东西会触发 API。

我有这个问题,并最终解决了它。

我的解决办法是:

  1. 在私有子网中设置 ECS
  2. 在 VPC 中添加 AWS PrivateLink 端点

把我的 CDK 代码贴在这里作为参考。我在函数注释中粘贴了一些文档链接,以便您更好地理解其用途。

这是 EcsStack:

export class EcsStack extends Stack {


constructor(scope: cdk.App, id: string, props: EcsStackProps) {
super(scope, id, props);
this.createOrderServiceCluster(props.vpc);
}


private createOrderServiceCluster(serviceVpc:ec2.IVpc) {
const ecsClusterName = "EcsClusterOfOrderService";


const OrderServiceCluster = new ecs.Cluster(this, ecsClusterName, {
vpc: serviceVpc,
clusterName: ecsClusterName
});


// Now ApplicationLoadBalancedFargateService just pick a randeom private subnet.
// https://github.com/aws/aws-cdk/issues/8621
new ecs_patterns.ApplicationLoadBalancedFargateService(this, "FargateOfOrderService", {
cluster: OrderServiceCluster, // Required
cpu: 512, // Default is 256
desiredCount: 1, // Default is 1
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry("12345.dkr.ecr.us-east-1.amazonaws.com/comics:user-service"),
taskRole: this.createEcsTaskRole(),
executionRole: this.createEcsExecutionRole(),
containerPort: 8080
},
memoryLimitMiB: 2048, // Default is 512
// creates a public-facing load balancer that we will be able to call
// from curl or our web browser. This load balancer will forward calls
// to our container on port 8080 running inside of our ECS service.
publicLoadBalancer: true // Default is false
});
}


/**
* This IAM role is the set of permissions provided to the ECS Service Team to execute ECS Tasks on your behalf.
* It is NOT the permissions your application will have while executing.
* https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
* @private
*/
private createEcsExecutionRole() : iam.IRole {
const ecsExecutionRole = new iam.Role(this, 'EcsExecutionRole', {
//assumedBy: new iam.ServicePrincipal(ecsTasksServicePrincipal),
assumedBy: new iam.ServicePrincipal("ecs-tasks.amazonaws.com"),
roleName: "EcsExecutionRole",
});
ecsExecutionRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly'));
ecsExecutionRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLogsFullAccess'));
return ecsExecutionRole;
}




/**
* Creates the IAM role (with all the required permissions) which will be used by the ECS tasks.
* https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html
* @private
*/
private createEcsTaskRole(): iam.IRole {
const ecsTaskRole = new iam.Role(this, 'OrderServiceEcsTaskRole', {
//assumedBy: new iam.ServicePrincipal(ecsTasksServicePrincipal),
assumedBy: new iam.ServicePrincipal("ecs-tasks.amazonaws.com"),
roleName: "OrderServiceEcsTaskRole",
});


ecsTaskRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly'));
ecsTaskRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLogsFullAccess'));
ecsTaskRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonS3ReadOnlyAccess'));


return ecsTaskRole;
}


}

这是 VpcStack 的代码片段:

export class VpcStack extends Stack {
readonly coreVpc : ec2.Vpc;
constructor(scope: cdk.App, id: string) {
super(scope, id);


this.coreVpc = new ec2.Vpc(this, "CoreVpc", {
cidr: '10.0.0.0/16',
natGateways: 1,
enableDnsHostnames: true,
enableDnsSupport: true,
maxAzs: 3,
subnetConfiguration: [
{
cidrMask: 28,
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
cidrMask: 24,
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE,
}
]
});
   

this.setupInterfaceVpcEndpoints();
}






/**
* Builds VPC endpoints to access AWS services without using NAT Gateway.
* @private
*/
private setupInterfaceVpcEndpoints(): void {
// Allow ECS to pull Docker images without using NAT Gateway
// https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html
this.addInterfaceEndpoint("ECRDockerEndpoint", ec2.InterfaceVpcEndpointAwsService.ECR_DOCKER);
this.addInterfaceEndpoint("ECREndpoint", ec2.InterfaceVpcEndpointAwsService.ECR);
this.addInterfaceEndpoint("SecretManagerEndpoint", ec2.InterfaceVpcEndpointAwsService.SECRETS_MANAGER);
this.addInterfaceEndpoint("CloudWatchEndpoint", ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH);
this.addInterfaceEndpoint("CloudWatchLogsEndpoint", ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS);
this.addInterfaceEndpoint("CloudWatchEventsEndpoint", ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_EVENTS);
this.addInterfaceEndpoint("SSMEndpoint", ec2.InterfaceVpcEndpointAwsService.SSM);
}


private addInterfaceEndpoint(name: string, awsService: ec2.InterfaceVpcEndpointAwsService): void {
const endpoint: ec2.InterfaceVpcEndpoint = this.coreVpc.addInterfaceEndpoint(`${name}`, {
service: awsService
});


endpoint.connections.allowFrom(ec2.Peer.ipv4(this.coreVpc.vpcCidrBlock), endpoint.connections.defaultPort!);
}
}

我得到了这个问题后,我的 Cloudform 文件翻译成 Terraform 文件。

在挣扎之后,我发现我在我的 Fargate 安全组中遗漏了一条出站规则。事实上,AWS 会自动创建一个“ ALLOW ALL”规则,但是 terraform 会禁用它。你需要增加你的 aws_security_group:

resource "aws_security_group" "example" {
# ... other configuration ...


egress = [
{
from_port        = 0
to_port          = 0
protocol         = "-1"
cidr_blocks      = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
]
}

你可以查一下 给你医生。

转到“任务定义”> “更新任务定义”。在“任务角色”下拉菜单中选择“ ecsTaskExecutionRole”。

您需要在 IAM 设置中修改此 ecsTaskExecutionRole,以包括以下权限:

  1. 保密经理
  2. CloudWatchFullAccess
  3. 亚马逊 SSMFullAccess
  4. 角色执行策略

然后创建新的任务定义,应该就可以了。

参考资料: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data-parameters.html

如果将任务放置在私有子网中,则可能需要添加入站和出站规则,以允许通信流到相关的 ACL。

ecsTaskExecutionRole => ECS-SecretsManager-Permission policy中,请确保您的区域特定的秘密添加了正确的访问级别。有时候,如果您正在使用 Secret 在一个地区创建,然后克隆到另一个地区处理 多区域设置多区域设置,那么仍然需要将它添加到 ecsTaskExectionRole = > ECS-Secret sManager-Permission,以便您的区域 ECS 可以访问它。

对我来说,在我的任务角色中引用的秘密 ARN 是不正确的。

我不得不自动分配公共 IP。

若要从控制台执行此操作,请在运行任务时..。 enter image description here

... 我必须选择“启用”为“自动分配公共 IP”。

enter image description here

如何执行“在私有子网中启动任务,该私有子网具有配置为通过公共子网中的 NAT 网关路由出站流量的 VPC 路由表。这样,NAT 网关可以代表任务打开到 ECR 的连接”:

这个解决方案的假设:

  1. ECR 存储库中有 docker 映像
  2. 您有一个具有 AmazonECSTaskExectionRolePolicy 权限的 IAM 角色
  3. 您还希望您的任务使用相同的 IP 地址。如果您不需要这个部分,我已经标记了这个可选部分。

解决方案:

  1. 创建新集群
    • AWS > ECS > Clusters > Create cluster > Networking only > 复选框 to Create VPC > Create
  2. 创建新的任务定义
    • AWS > ECS > 任务定义 > 创建新任务定义 > Fargate
      • 添加容器 > Image * 字段应该包含来自 ECR 的 Image URI
  3. 创建弹性 IP 地址(可选,只有当您想要一致的 IP 输出时,比如使用代理服务时)
    • AWS > VPC > 弹性 IP > 分配弹性 IP 地址 > 创建
    • 把这个 IP 地址列在 Fargate 想要访问的任何服务上
  4. 创建 NAT 网关
    • AWS > VPC > NAT 网关 > 创建 NAT 网关
      • 选择自动创建的子网
      • 连接类型: Public
      • ^ 因为你把它公开在一个子网上,这就是所谓的“ NAT 网关在一个公共子网上”的意思
      • (可选)从下拉菜单中选择弹性 IP
  5. 使用 Internet 网关路由公共子网
    • AWS > VPC > Route tables > find one w/public subnet auto-create in step 1 > click on Route table ID > Edit path > Add path > Destination is 0.0.0.0.0,Target is igw-{ Internet-gate-autocreate-in-step-1}
    • ^ 这就是 VPC 实际上可以访问互联网的原因
  6. 创建子网
    • AWS > VPC > 子网 > 创建子网 > 在步骤1中选择自动创建的 VPC,对于 IPv4,如果您感到困惑,只需输入10.0.0.0/24 > Add new subnet
  7. 将新创建的子网(步骤6)路由到使用 NAT
    • AWS > VPC > Route tables > find one w/subnet create in step 6 > 单击 Route table ID > Edit routs > Add path > Destination: 0.0.0.0.0,Target: nat-{ nat-gate-create-in-step-4}
    • ^ 这就是所谓的“具有 VPC 路由表的私有子网,该路由表被配置为通过 NAT 网关路由出站流量”
  8. 运行 Fargate 任务
    • AWS > ECS > Clusters > your cluster > Run new Task
    • 发射类型: Fargate
    • 任务定义: 您的任务
    • 群集: 您的群集
    • 群集 VPC: 您的 VPC
    • 子网: 你创建的子网,而不是自动创建的
    • 自动分配公共 IP: 这取决于您是否使用弹性 IP。如果你这样做了,那么这个应该被禁用。如果您没有分配一个弹性 IP 地址,那么这应该是启用。
    • 执行任务

对我来说,我有一个 VPC 与公共和私有子网和公共和私有子网之间的 nat 网关。当我试图访问机密时,这项服务必须在私有子网中启动。除非设置了 vpc 端点,否则秘密检索不能在公共子网中工作。在使用 Fargate 1.4版本的私有子网中工作良好。

对我来说,我的问题是我为我的私有子网配置的 NAT 网关被错误地配置为私有 NAT 网关。哎呀。转换到公共 NAT 网关和更新路由表解决了我的问题

对于我的情况,我尝试了以上所有的解决方案,似乎没有一个是有效的。 这是一个非常简单的错误,但是如果没有一个答案对你有用的话,其他人可能会发现这个错误。

任务定义 json 文件的 containerDefinition部分中的 valueFrom需要在值的末尾使用 ::

也就是说。 就我而言:

{
"containerDefinitions": [{
"secrets": [{
"name": "MY_SECRET",
"valueFrom": "arn:aws:secretsmanager:<region>:<aws_account_id>:secret:<sm_resource_name>:MY_SECRET"
}]
}]
}

正确的格式是:

{
"containerDefinitions": [{
"secrets": [{
"name": "MY_SECRET",
"valueFrom": "arn:aws:secretsmanager:<region>:<aws_account_id>:secret:<sm_resource_name>:MY_SECRET::"
}]
}]
}

注意在正确的解决方案 valueFrom的末尾有额外的 ::

在检查了这个 AWS 支持页面: https://aws.amazon.com/premiumsupport/knowledge-center/ecs-unable-to-pull-secrets/和这里的其他流行答案之后,还需要检查的一件事是,正在检索的秘密实际上具有一个值集。

在使用 SecretesManager 时,如果您的 ECS Task 试图检索已创建的 但是没有值集秘密,那么您也将收到此类错误。

为 secret 设置一个值将解决这个特定的问题。

这主要是由于您的安全组中的出站限制(在公共子网的情况下)。

打开 TCP 端口将帮助您解决同样的问题。

ResourceInitializationError: 无法获取秘密或注册表身份验证: 执行资源检索失败: 无法检索 ecr 注册表身份验证

当图像 URI 中有一个输入错误时,ECS 会抛出同样的错误,这很奇怪... 但可能对某人有帮助。肯定吃了我几个小时。干杯!

感谢解决方案,我有同样的问题,答案是正确的,这是由于在 Fargate v1.3和 v1.4的差异,所以它可能有点忙碌,但这一个确实工作。 译自: 美国《 https://stackoverflow.com/a/70857885/14975561》杂志网站(https://stackoverflow. com/a/70857885/14975561)

你的问题可能是你没有把 public IP 分配给你的群组。

在集群上创建任务时启用它。

自动分配公共 IP = TRUE

对于我来说,这个问题出现在我添加了我自己的 VPC 和子网按照这个模板 https://github.com/thombergs/code-examples/blob/master/aws/cloudformation/ecs-in-two-public-subnets/network.yml

但我不得不添加一个互联网网关,以使其工作。在上面的配置中,它就在子网配置之后。

我通过在作业定义中设置“ Assign public IP”= ENABLED 来解决这个问题。

档号: 连接到 ECR 的批量超时