如何配置 AWS ECS Fargate Tasks/Cluster 以使用 Pulumi 访问私有 Docker Container Registry(如 GitHub Container Registry)?
How to configure AWS ECS Fargate Tasks/Cluster to access private Docker Container Registry (like GitHub Container Registry) with Pulumi?
我正在使用 Pulumi 进行 AWS Fargate 集群设置,我当前的程序已经成功创建了一个集群,包括。 运行 public 可访问容器映像的 Fargate 任务。我的镜像基于 Spring Boot (project code on 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;
一切正常,但现在我需要使用私有容器镜像 ghcr.io/jonashackt/microservice-api-spring-boot-private:latest
。切换我的代码以使用新图像,我的 Fargate 集群服务不停地停止和启动新的 Tasks/Containers。查看我的 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
那么如何使用 Pulumi 配置对私有 Container Registry(此处 GitHub Container Registry)的访问权限?
在 AWS 文档中有关于 how to grant ECS EC2 & Fargate launch type Tasks access to private Registries 的详细指南。由此推导出有 4 个步骤:
- 获取令牌或凭据以访问私有 Container Registry
- 将包含 Token/Creds 的 AWS Secrets Manager 秘密创建到私有注册表
- Craft 任务执行角色(使用 aws.iam.Role)包含用于私有 Container Registry 访问的 inlinePolicy
- 增强 awsx.ecs.FargateService 以在 repositoryCredentials
中使用我们的任务执行角色和秘密 ARN
0。获取令牌或凭据以访问私有 Container Registry
如果您还没有它们,则需要在我们的私有注册表中创建一个访问令牌或凭据,以便外部服务能够访问它。以 GitHub Container Registry 为例,我们需要至少使用 read:packages
范围创建个人访问令牌 (see docs here):
1.将包含 Token/Creds 的 AWS Secrets Manager 秘密创建到私有注册表
Now head over to the AWS Secrets Manager console at https://console.aws.amazon.com/secretsmanager/ 并通过 Store a new secret
按钮创建一个新的 Secret。在 GUI 中选择 Other type of secrets
和 Plaintext
- 然后将您的私有注册表凭据填写为 JSON:
{
"username": "yourGitHubUserNameHere",
"password": "yourGitHubPATHere"
}
Select Next
并提供一个秘密名称,例如 githubContainerRegistryAccess
。再次点击下一步并将 Disable automatic rotation
保留为默认值。再次点击 Store
以创建 Secret。最后将 Secret ARN 像 arn:aws:secretsmanager:awsRegionHere:yourAccountIdHere:secret:githubContainerRegistryAccess-randomNumberHere
一样复制到您的记事本或编辑器中以备后用。
2。工艺任务执行角色(使用 aws.iam.Role)包含用于私有 Container Registry 访问的 inlinePolicy
As the docs tell us we need to add the permission to access the Secrets Manager Secret as Inline Policy to the Fargate Tasks Execution Role. Now as the new awsx.ecs.FargateService
automatically creates such a Task Execution Role, but we can't access it afterwards really, we need to create the whole thing ourselves. To create the aws.iam.Role
we can have a look into the Pulumi docs about it。一个 Pulumi aws.iam.Role
由多个组件组成,我们需要其中的 3 个:
assumeRolePolicy
:我真的不想自己定义这个,但是没有它就无法创建aws.iam.Role
。选择 "sts:AssumeRole"
作为 Action
和 "ecs-tasks.amazonaws.com"
作为服务主体是至关重要的。
inlinePolicies
:这个数组将采用我们的 InlinePolicy,Task 需要它来访问 Secrets Manager Secret(也就是这里创建角色的全部要点)。它是 exactly the same as described in the AWS docs - 真正关注 Resources
中正确的 arn
名称。两者之一正是我们的 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"
]
});
3。增强 awsx.ecs.FargateService 以在 repositoryCredentials
中使用我们的任务执行角色和秘密 ARN
现在是最后一步了。我们需要使用我们创建的任务执行角色并使用 executionRole
参数将其附加到我们的 awsx.ecs.FargateService
。和 we also need to provide our Secrets Manager Secret ARN (again) as repositoryCredentials:credentialsParameter
to our 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,
});
现在 pulumi up
应该会按预期启动您的 Fargate 任务,因为它们现在能够从私有 GitHub 容器注册表中提取容器映像。在 AWS ECS 集群视图中,您应该会看到 运行 任务:
我正在使用 Pulumi 进行 AWS Fargate 集群设置,我当前的程序已经成功创建了一个集群,包括。 运行 public 可访问容器映像的 Fargate 任务。我的镜像基于 Spring Boot (project code on 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;
一切正常,但现在我需要使用私有容器镜像 ghcr.io/jonashackt/microservice-api-spring-boot-private:latest
。切换我的代码以使用新图像,我的 Fargate 集群服务不停地停止和启动新的 Tasks/Containers。查看我的 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
那么如何使用 Pulumi 配置对私有 Container Registry(此处 GitHub Container Registry)的访问权限?
在 AWS 文档中有关于 how to grant ECS EC2 & Fargate launch type Tasks access to private Registries 的详细指南。由此推导出有 4 个步骤:
- 获取令牌或凭据以访问私有 Container Registry
- 将包含 Token/Creds 的 AWS Secrets Manager 秘密创建到私有注册表
- Craft 任务执行角色(使用 aws.iam.Role)包含用于私有 Container Registry 访问的 inlinePolicy
- 增强 awsx.ecs.FargateService 以在 repositoryCredentials 中使用我们的任务执行角色和秘密 ARN
0。获取令牌或凭据以访问私有 Container Registry
如果您还没有它们,则需要在我们的私有注册表中创建一个访问令牌或凭据,以便外部服务能够访问它。以 GitHub Container Registry 为例,我们需要至少使用 read:packages
范围创建个人访问令牌 (see docs here):
1.将包含 Token/Creds 的 AWS Secrets Manager 秘密创建到私有注册表
Now head over to the AWS Secrets Manager console at https://console.aws.amazon.com/secretsmanager/ 并通过 Store a new secret
按钮创建一个新的 Secret。在 GUI 中选择 Other type of secrets
和 Plaintext
- 然后将您的私有注册表凭据填写为 JSON:
{
"username": "yourGitHubUserNameHere",
"password": "yourGitHubPATHere"
}
Select Next
并提供一个秘密名称,例如 githubContainerRegistryAccess
。再次点击下一步并将 Disable automatic rotation
保留为默认值。再次点击 Store
以创建 Secret。最后将 Secret ARN 像 arn:aws:secretsmanager:awsRegionHere:yourAccountIdHere:secret:githubContainerRegistryAccess-randomNumberHere
一样复制到您的记事本或编辑器中以备后用。
2。工艺任务执行角色(使用 aws.iam.Role)包含用于私有 Container Registry 访问的 inlinePolicy
As the docs tell us we need to add the permission to access the Secrets Manager Secret as Inline Policy to the Fargate Tasks Execution Role. Now as the new awsx.ecs.FargateService
automatically creates such a Task Execution Role, but we can't access it afterwards really, we need to create the whole thing ourselves. To create the aws.iam.Role
we can have a look into the Pulumi docs about it。一个 Pulumi aws.iam.Role
由多个组件组成,我们需要其中的 3 个:
assumeRolePolicy
:我真的不想自己定义这个,但是没有它就无法创建aws.iam.Role
。选择"sts:AssumeRole"
作为Action
和"ecs-tasks.amazonaws.com"
作为服务主体是至关重要的。inlinePolicies
:这个数组将采用我们的 InlinePolicy,Task 需要它来访问 Secrets Manager Secret(也就是这里创建角色的全部要点)。它是 exactly the same as described in the AWS docs - 真正关注Resources
中正确的arn
名称。两者之一正是我们的 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"
]
});
3。增强 awsx.ecs.FargateService 以在 repositoryCredentials
中使用我们的任务执行角色和秘密 ARN现在是最后一步了。我们需要使用我们创建的任务执行角色并使用 executionRole
参数将其附加到我们的 awsx.ecs.FargateService
。和 we also need to provide our Secrets Manager Secret ARN (again) as repositoryCredentials:credentialsParameter
to our 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,
});
现在 pulumi up
应该会按预期启动您的 Fargate 任务,因为它们现在能够从私有 GitHub 容器注册表中提取容器映像。在 AWS ECS 集群视图中,您应该会看到 运行 任务: