Press "Enter" to skip to content

使用ArgoCD解决跨多环境的图像推广挑战

在设计云环境时,通常建议设置多个账户。虽然这种方法提供了资源独立性、隔离性、更好的安全性、访问权限和计费边界,但同时也带来了一系列问题。其中一个挑战是在不同环境之间高效地推广和跟踪应用程序。

GitOps方法以及ArgoCD和Kustomize等工具简化了跟踪和推广的过程。但是,“镜像推广”经常被忽视。许多企业采用共享镜像注册表,但很快就会积累许多未使用的版本。

本文探讨了最近的一次旅程,我们在这次旅程中研究了推广镜像的问题以及采用的创新解决方案,同时遵循GitOps的原则。

挑战

最近,一个公司正在考虑将共享的ECR注册表迁移到单独的ECR注册表,以实现成本效益、更好的治理和简化的生命周期管理。

以下是现有基础设施和流水线的状态:

Source: Image by the author.
  • 每个环境都有一个专用的AWS账户,拥有自己的集群和ArgoCD安装。
  • Kustomize用于管理不同环境之间的配置差异。
├── infra  │   ├── charts/  └── overlays      ├── dev      │   ├── patch-image.yaml      └── production          ├── patch-image.yaml          └── patch-replicas.yaml
  • Jenkins用于在开发环境中持续构建新的镜像。

然而,这些工具都没有直接支持在ECR注册表之间推广镜像,因此需要探索创新解决方案。

考虑因素:

  • 选择性推广:公司的应用程序包括多个模块和团队,具有不同的时间表。因此,需要支持每个发布中仅针对所选模块的镜像推广。
  • 优化存储:生产等环境只需要存储推广的镜像版本,减少杂乱并优化资源使用。
  • 镜像标签和摘要复制:在ECR注册表之间复制镜像标签和摘要对于安全性和可追溯性至关重要。

潜在解决方案

首先,提出了两种潜在解决方案:

  1. ECR跨账户复制: AWS的ECR原生支持在两个账户之间复制镜像。然而,目前还没有办法根据任何条件过滤要复制的镜像。作为替代方案,AWS建议基于标签命名规范选择性地复制镜像。然而,由于我们不知道哪些版本将被推广,这就需要在推广之前进行额外的重新标记。
  2. Jenkins推广流水线:一个Jenkins流水线,用于解析Kustomize Overlays中的镜像标签并以程序方式复制它们。

这两个选项都是可行的,但它们为推广过程引入了额外的复杂性。另外,您需要确保在更新Kustomize Overlays之前推广镜像。

成功策略:ArgoCD PreSync Job

在这种情况下,客户已经在使用ArgoCD进行应用程序更改的持续部署。因此,我们决定将将镜像的交付责任也交给ArgoCD,以交付到目标环境集群。

ArgoCD支持钩子,允许您在部署或同步过程之前或之后运行自定义脚本。

Source: Image by the author.

1. ECR Repository Permission: 为Docker镜像授权跨账户拉取访问权限

为了使ArgoCD能够从源ECR拉取镜像,我们需要向我们的仓库添加基于资源的策略。

// cross-account-ecr-read-policy.json{  "Version": "2012-10-17",  "Statement": [    {      "Sid": "AllowPull",      "Effect": "Allow",      "Principal": {        "AWS": "arn:aws:iam::{DESTINATION_ACCOUNT}:root" // 请替换为您的目标账号      },      "Action": [        "ecr:BatchCheckLayerAvailability",        "ecr:BatchGetImage",        "ecr:GetDownloadUrlForLayer"      ]    }  ]}

将策略应用于 ECR 仓库:

aws ecr set-repository-policy --repository-name example --policy-text "file://cross-account-ecr-read-policy.json"// 对于多个仓库:aws ecr describe-repositories --query "repositories[].[repositoryName]" | xargs -I {} aws ecr set-repository-policy --repository-name {} --policy-text "file://cross-account-ecr-read-policy.json"

2. PreSync Hook 任务:在账号之间复制镜像

  • 我们使用 Crane 在不改变标签和摘要的情况下复制镜像。
  • PreSync Hook 任务与其他应用程序清单一起存储在 git 中,并由 ArgoCD 监控。ArgoCD 在同步更改之前运行该任务。
  • 源账号是将要拉取镜像的开发或 DevOps 账号。
  • 目标账号是需要复制镜像的生产环境或目标环境。
// Helm 模板示例apiVersion: batch/v1kind: Jobmetadata:  generateName: argo-presync-promote-image-  annotations:    argocd.argoproj.io/hook: PreSyncspec:  template:    spec:      volumes:        - name: creds          emptyDir: {}      initContainers:        - name: aws-creds          image: public.ecr.aws/aws-cli/aws-cli          command:            - sh            - -c            - |              aws ecr get-login-password > /creds/ecr          volumeMounts:            - name: creds              mountPath: /creds      containers:        // 为了简洁起见,我假设所有 Helm 值都可在根目录下获取。        - name: promote-image          image: gcr.io/go-containerregistry/crane:debug          command:            - sh            - -c            - |              // 登录到两个 ECR 注册表              cat /creds/ecr | crane auth login {{.Values.sourceAccount}}.dkr.ecr.us-east-1.amazonaws.com -u AWS --password-stdin              cat /creds/ecr | crane auth login {{.Values.destinationAccount}}.dkr.ecr.us-east-1.amazonaws.com -u AWS --password-stdin              // 从源账号复制镜像到目标账号              crane copy {{.Values.image | replace .Values.destinationAccount .Values.sourceAccount}} {{.Values.image}}          volumeMounts:            - name: creds              mountPath: /creds      restartPolicy: Never  backoffLimit: 2

结论

总之,团队能够通过使用 PreSync Hook 来按需推广镜像。这使得生产推广成为更新 Kustomize 叠加的单个步骤。

我很想听听您采用的其他选项。例如,另一种方法可能是使用 Kubernetes 动态准入控制来拦截和按需拉取缺失的镜像。

Leave a Reply

Your email address will not be published. Required fields are marked *