如何配置 AWS ECS Fargate 任务/集群以使用 Pulumi 访问私有 Docker 容器注册表(如 GitHub 容器注册表)?

jon*_*ckt 2 amazon-web-services docker spring-boot aws-fargate pulumi

我正在使用 Pulumi 进行 AWS Fargate 集群设置,我当前的程序已经成功创建了一个集群,包括。Fargate 运行公共可访问容器映像的任务。我的镜像是基于Spring Boot的(项目代码在GitHub上):

import * as awsx from "@pulumi/awsx";

// Spring Boot Apps port
const port = 8098;

// Create a ApplicationLoadBalancer to listen for requests and route them to the container.
const alb = new awsx.lb.ApplicationLoadBalancer("fargateAlb");

const albTargetGroup = alb.createTargetGroup("fargateAlbTargetGroup", {
    port: port,
    protocol: "HTTP",
    healthCheck: {
        // Use the default spring-boot-actuator health endpoint
        path: "/actuator/health"
    }
});

const albListener = albTargetGroup.createListener("fargateAlbListener", { port: port, protocol: "HTTP" });

// Define Container image published to the GitHub Container Registry
const service = new awsx.ecs.FargateService("microservice-api-spring-boot", {
    taskDefinitionArgs: {
        containers: {
            microservice_api_spring_boot: {
                image: "ghcr.io/jonashackt/microservice-api-spring-boot:latest",
                memory: 768,
                portMappings: [ albListener ]
            },
        },
    },
    desiredCount: 2,
});

// Export the URL so we can easily access it.
export const apiUrl = albListener.endpoint.hostname;
Run Code Online (Sandbox Code Playgroud)

一切都按预期工作,但现在我需要使用私有容器映像ghcr.io/jonashackt/microservice-api-spring-boot-private:latest。将我的代码切换为使用新映像后,我的 Fargate 集群服务不断停止和启动新任务/容器。查看我的 Fargate 集群的“服务”Task选项卡并切换到Stopped“任务”状态,我看到很多STOPPED (CannotPull...这样的错误:

在此输入图像描述

如果我单击已停止的任务之一,我会看到以下内容Stopped reason

CannotPullContainerError: inspect image has been retried 1 time(s): failed to resolve ref "ghcr.io/jonashackt/microservice-api-spring-boot-private:latest": failed to authorize: failed to fetch anonymous token: unexpected status: 401 Unauthorized
Run Code Online (Sandbox Code Playgroud)

那么如何使用 Pulumi 配置对私有容器注册表(此处为 GitHub 容器注册表)的访问权限?

jon*_*ckt 6

在 AWS 文档中,有关于如何授予 ECS EC2 和 Fargate 启动类型任务对私有注册表的访问权限的详细指南。由此得出,需要采取 4 个步骤:

  1. 获取令牌或凭据以访问私有容器注册表
  2. 创建包含私有注册表的令牌/信用的 AWS Secrets Manager 密钥
  3. 包含用于私有容器注册表访问的 inlinePolicy 的工艺任务执行角色(使用 aws.iam.Role)
  4. 增强 awsx.ecs.FargateService 以使用我们的任务执行角色和存储库凭证中的秘密 ARN

0. 获取Token或凭证来访问私有ContainerRegistry

如果您还没有它们,则需要在我们的私有注册表中创建访问令牌或凭据,以便外部服务能够访问它。以 GitHub Container Registry 为例,我们需要至少使用范围创建个人访问令牌(请参阅此处的文档) :read:packages

在此输入图像描述


1. 创建包含私有注册表的令牌/信用的 AWS Secrets Manager 密钥

现在前往 AWS Secrets Manager 控制台(网址为https://console.aws.amazon.com/secretsmanager/)并通过 按钮创建一个新的 Secret Store a new secret。在 GUI 中选择Other type of secrets-Plaintext然后以 JSON 形式填写您的私有注册表凭据:

{
  "username": "yourGitHubUserNameHere",
  "password": "yourGitHubPATHere"
}
Run Code Online (Sandbox Code Playgroud)

选择Next并提供一个秘密名称,例如githubContainerRegistryAccess。再次点击“下一步”并保留Disable automatic rotation默认值。再次点击Store创建 Secret。最后将 Secret ARN 复制arn:aws:secretsmanager:awsRegionHere:yourAccountIdHere:secret:githubContainerRegistryAccess-randomNumberHere到记事本或编辑器中以供以后参考。


2. 制作包含用于私有容器注册表访问的 inlinePolicy 的任务执行角色(使用 aws.iam.Role)

正如文档告诉我们的,我们需要将访问 Secrets Manager Secret 作为内联策略的权限添加到 Fargate 任务执行角色。现在,由于new awsx.ecs.FargateService自动创建了这样一个任务执行角色,但我们之后无法真正访问它,所以我们需要自己创建整个角色。要创建aws.iam.Role我们可以查看有关它的 Pulumi 文档。Pulumiaws.iam.Role由多个组件组成,我们需要其中 3 个:

  • assumeRolePolicy:我真的不想自己定义这个,但是aws.iam.Role没有它就无法创建。"sts:AssumeRole"选择作为服务主体Action至关重要。"ecs-tasks.amazonaws.com"
  • inlinePolicies:该数组将采用我们的 InlinePolicy,任务需要该 InlinePolicy 来访问 Secrets Manager Secret(也就是此处创建此角色的全部要点)。它与 AWS 文档中描述的完全相同- 请务必注意arn其中的正确名称Resources。两者之一正是我们的 Secrets Manager Secret ARN!
  • managedPolicyArns包含 Pulumi 附加到 Fargate 任务的默认策略(我只是查看了 AWS 控制台以查找其 arns)。

这是正确定义 InlinePolicy 所需的 Pulumi 代码:

const taskExecutionRole = new aws.iam.Role("microservice-api-spring-boot-execution", {
    assumeRolePolicy: {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "",
                "Effect": "Allow",
                "Principal": {
                    "Service": "ecs-tasks.amazonaws.com"
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }, inlinePolicies: [
        {
            name: "ghcr-secret-access",
            policy: JSON.stringify({
                Version: "2012-10-17",
                Statement: [
                    {
                        Effect: "Allow",
                        Action: [
                            "kms:Decrypt",
                            "secretsmanager:GetSecretValue"
                        ],
                        Resource: [
                            "arn:aws:secretsmanager:awsRegionHere:yourAccountIdHere:secret:githubContainerRegistryAccess-randomNumberHere",
                            "arn:aws:kms:awsRegionHere:yourAccountIdHere:key/key_id"
                        ]
                    }]
            })
        },
    ],
    managedPolicyArns: [
        "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
        "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
    ]
});
Run Code Online (Sandbox Code Playgroud)

3. 增强 awsx.ecs.FargateService 以使用我们的任务执行角色和存储库凭证中的秘密 ARN

现在这是最后一步。我们需要使用我们创建的任务执行角色并将其附加到我们的awsx.ecs.FargateServiceusingexecutionRole参数。我们还需要(再次)提供我们的 Secrets Manager Secret ARN 到repositoryCredentials:credentialsParameter我们的awsx.ecs.FargateService. 这看起来有点像这样:

// Define Container image published to the GitHub Container Registry
const service = new awsx.ecs.FargateService("microservice-api-spring-boot", { 
    taskDefinitionArgs: {
        containers: {
            blueprint_helloworld: {
                image: "ghcr.io/jonashackt/microservice-api-spring-boot-private:latest",
                memory: 768,
                portMappings: [ albListener ],
                // Access private GitHub Container Registry: we need to provide the Secret ARN as repositoryCredentials
                // see https://www.pulumi.com/docs/reference/pkg/nodejs/pulumi/awsx/ecs/#Container-repositoryCredentials
                repositoryCredentials: {
                    credentialsParameter: "arn:aws:secretsmanager:awsRegionHere:yourAccountIdHere:secret:githubContainerRegistryAccess-randomNumberHere",
                }
            },
        },
        executionRole: taskExecutionRole,
    },
    desiredCount: 2,
});
Run Code Online (Sandbox Code Playgroud)

现在,pulumi up应该会按预期启动您的 Fargate 任务,因为它们现在能够从私有 GitHub 容器注册表中提取容器映像。在 AWS ECS 集群视图中,您应该会看到正在运行的任务:

在此输入图像描述

  • 从*内部* GitHub Actions 访问 GitHub 容器注册表变得更加容易,您不再需要生成 PAT,并且可以直接使用“GITHUB_TOKEN”。但据我所知,要从 GitHub Actions 上下文的“外部”(例如,从 AWS Fargate)访问 GitHub 容器注册表,您仍然需要 PAT。 (2认同)