亚马逊AWS官方博客

基于Amazon中国区EKS使用Code家族和 Argo CD 构建GitOps CICD流程

摘要:本文聚集现在企业应用交付对效率、稳定性和可追溯性的要求持续提升需求及传统的 CI/CD 流程的核心痛点,提出了基于Amazon的 托管服务和 Argo CD 结合的解决方案。该方案基于Amazon 中国区 EKS 构建了一套完整的 GitOps CI/CD 流程,整合 CodeCommit、CodePipeline、CodeBuild、ECR 与 Argo CD 等组件,实现从代码提交到应用部署、更新的全流程自动化,让企业应用交付更高效、更稳定、更易管控。


一、背景介绍

在云原生技术普及的当下,企业应用交付对效率、稳定性和可追溯性的要求持续提升,传统的 CI/CD 流程已难以适配云原生应用的部署管理需求。

[图1]

核心痛点:

  • 依赖人工编写脚本和手动执行部署操作,易因人为失误导致交付不一致,存在跨环境部署时配置漂移问题;
  • 应用变更缺乏统一的审计和追溯入口,出现故障时难以快速定位问题版本、实现精准回滚;
  • 权限管理与流程管控脱节,资源访问和操作缺乏细粒度约束,存在安全风险;
  • 自动化程度低,从代码提交到应用上线的链路冗长,交付效率无法匹配业务快速迭代的需求。

GitOps 作为云原生时代的声明式持续交付理念,以 Git 仓库作为应用配置和部署状态的唯一事实来源,将所有应用变更、配置修改都通过 Git 提交实现,结合自动化工具完成部署流程的执行和校验,从根源上解决了传统CI/CD 的痛点。本文基于 Amazon EKS构建一套完整的 GitOps CI/CD 流程,整合 CodeCommit、CodePipeline、CodeBuild、ECR 与 Argo CD 等组件,实现从代码提交到应用部署、更新的全流程自动化,让企业应用交付更高效、更稳定、更易管控。

二、方案简介

[图2]

本方案基于 Amazon云服务生态与 K8S原生能力,打造 GitOps 声明式 CI/CD流程,实现代码、配置、部署状态的一体化管理,同时充分利用 Amazon云服务的托管特性,降低基础设施和工具链的运维成本。

2.1 核心组件及功能

方案核心组件及功能如下:

  • CodeCommit:Amazon 托管的 Git 代码仓库,作为整个体系的核心数据源,分仓存储应用业务代码和K8S 资源清单文件,所有变更均通过 Git 提交、审核、合并,实现可追溯、可审计;
  • CodePipeline:Amazon 托管的 CI 流程编排工具,负责触发自动化流水线、串联各阶段任务,实现从代码源变更到镜像构建的全流程自动化触发和调度;
  • CodeBuild:Amazon托管的构建服务,无需自建构建环境,实现容器镜像的自动化构建、打标,并将镜像推送到私有镜像仓库;
  • ECR:Amazon托管的容器镜像仓库,用于安全存储、管理应用构建后的容器镜像,提供镜像版本管理、访问权限控制等能力;
  • Argo CD:开源 GitOps CD 工具,部署在 EKS 集群内部,持续监控 CodeCommit 中的 K8S 清单仓库,实现清单与集群中应用实际状态的校验、同步,完成应用的自动化部署和更新;
  • Amazon EKS:Amazon托管的 K8S 集群,作为应用的运行载体,提供稳定、可扩展的容器运行环境,兼容 K8S 原生的部署、滚动更新、服务发现等能力。

2.2 方案工作原理

本方案遵循 GitOps 核心原则,将Git 作为唯一的操作入口和状态源,所有应用的部署、更新、配置修改,均需通过修改 Git 仓库中的代码或清单文件实现,再由自动化工具完成后续流程,整体工作原理为:“源变更触发 – 自动化构建 – 状态同步部署”,具体链路如下:

  1. 开发者在本地完成应用代码开发,通过 Git 将代码推送到 CodeCommit 应用代码仓库;
  2. CodeCommit 感知到代码源变更后,自动触发关联的 CodePipeline 流水线,启动自动化 CI 流程;
  3. CodePipeline 调用 CodeBuild 服务,拉取最新的应用代码,根据预设的构建规则(Dockerfile、buildspec.yml)构建容器镜像,完成镜像打标后推送到 ECR 镜像仓库;
  4. 若为应用版本更新,需手动或通过自动化工具更新 CodeCommit 清单仓库中的镜像版本号(可通过 Argo CD Image Updater 实现自动更新);
  5. Argo CD 以固定频率监控 CodeCommit 清单仓库的变更,将仓库中的声明式配置与 EKS 集群中应用的实际运行状态进行对比;
  6. 当发现清单配置与集群实际状态不一致时,Argo CD 自动执行同步操作,按照清单中的定义在 EKS 集群中完成应用的部署、更新或回滚,确保集群状态与 Git 仓库中的声明式配置保持一致。

2.3 方案优势

  1. 声明式管理: 以 Git 为唯一事实来源实现声明式管理,变更可追溯、易回滚;
  2. 自动化部署: 实现从代码提交到镜像构建、应用部署的全链路自动化,无需人工介入,将应用交付的周期从小时级缩短至分钟级,匹配业务快速迭代需求;
  3. 安全可靠: 使用 IRSA 实现细粒度权限控制,无需手动管理凭证,兼顾安全与便捷;
  4. 易于扩展: 方案基于 EKS 构建,天然支持应用的弹性扩缩容,兼容 K8S原生的滚动更新、金丝雀发布等能力,可灵活适配微服务多应用、多环境部署场景。

三、环境部署

3.1 操作终端准备

3.1.1 创建Linux实例

在控制台中创建一台Linux实例,用作操作终端,该终端要求如下:

  • AMI:Amazon Linux 2023 kernel-6.1 AMI
  • 实例类型:t3.medium
  • 配置存储:20GB

[图3]

3.1.2 安装相关工具

使用如下命令在操作终端上安装Git:

sudo yum update -y
sudo yum install -y git

安装与配置 Amazon cli工具,参考链接

验证是否安装成功:

[图4]

3.2 创建 CodeCommit 代码库

3.2.1 创建代码库

通过控制台创建两个 CodeCommit 代码库:

  • cicd-test-app
  • cicd-test-manifests

[图5]

3.2.2 创建代码库凭证

  1. 创建并下载凭证,以供后续使用,参考链接

[图6]

3.2.3 配置操作终端可访问代码库

[图7]

3.3 创建示例应用代码

1、代码结构

cicd-test-app/	# 应用变更的唯一事实来源
├─ main.go 		# Go 应用主程序
├─ Dockerfile 		# 容器镜像构建文件
└─ buildspec.yml 		# CodeBuild 构建配置
cicd-test-manifests /	# 应用部署状态的唯一事实来源
└── deployment.yaml	# 部署和服务定义

2、创建 main.go

package main

import (
        "fmt"
        "log"
        "net/http"
        "os"
)

const Version = "v2.0.0"

func handler(w http.ResponseWriter, r *http.Request) {
        hostname, _ := os.Hostname()
        response := fmt.Sprintf("Hello from EKS CI/CD Demo! Version: %s | Hostname: %s | Updated!\n", Version, hostname)
        fmt.Fprint(w, response)
        log.Printf("Request from %s", r.RemoteAddr)
}

func healthHandler(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        fmt.Fprint(w, "OK")
}

func main() {
        http.HandleFunc("/", handler)
        http.HandleFunc("/health", healthHandler)

        port := "8080"
        log.Printf("Starting server on port %s, version %s", port, Version)
        if err := http.ListenAndServe(":"+port, nil); err != nil {
                log.Fatal(err)
        }
}

3、创建Dockerfile

FROM public.ecr.Amazon/docker/library/golang:1.22-alpine AS builder
WORKDIR /app
COPY main.go .
RUN go build -o server main.go
FROM public.ecr.aws/docker/library/alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]

4、创建 buildspec.yml

version: 0.2
phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - ECR_REPOSITORY_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com.cn
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ECR_REPOSITORY_URI
      - VERSION=$(grep -oP 'const Version = "\K[^"]+' main.go)
      - echo Image tag is $IMAGE_TAG
  build:
    commands:
      - echo Build started on `date`
      - docker build -t $IMAGE_REPO_NAME .
      - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $ECR_REPOSITORY_URI/$IMAGE_REPO_NAME:$IMAGE_TAG
  post_build:
    commands:
      - echo Pushing Docker image...
      - docker push $ECR_REPOSITORY_URI/$IMAGE_REPO_NAME:$IMAGE_TAG
      - echo Build completed on `date`

5、创建deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cicd-eks-demo
  annotations:
    argocd-image-updater.argoproj.io/image-list: app=<您的Amazon 账号ID>.dkr.ecr.cn-north-1.amazonaws.com.cn/cicd-test-app
    argocd-image-updater.argoproj.io/app.update-strategy: latest
    argocd-image-updater.argoproj.io/app.allow-tags: regexp:^[a-f0-9]{7}$
    argocd-image-updater.argoproj.io/write-back-method: git
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cicd-eks-demo
  template:
    metadata:
      labels:
        app: cicd-eks-demo
        version: V3.0.0
    spec:
      containers:
      - name: app
        image: <您的 Amazon 账号ID>.dkr.ecr.cn-north-1.amazonaws.com.cn/cicd-test-app:latest
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
  name: cicd-eks-demo
spec:
  type: LoadBalancer
  selector:
    app: cicd-eks-demo
  ports:
  - port: 80
    targetPort: 8080

6、提交代码到 CodeCommit 仓库。

3.4 创建ECR镜像仓库

通过控制台或命令行创建 ECR 镜像仓库,提供对镜像的版本管理能力:

Amazon ecr create-repository --repository-name cicd-test-app --region cn-north-1

3.5 CodeBuild中创建构建项目

  1. 构建项目按照如下配置创建:
    • 项目名称:cicd-build-project
    • 源提供商:Amazon CodeCommit,存储库:cicd-test-app

[图8]

    • 构建环境,选择托管镜像:Amazon Linux 2 Standard

[图9]

    • 服务角色,选择“新服务角色”,需要注意:该角色需要额外添加ECR访问策略,否则构建时会报错:

[图10]

[图11]

    • 其他配置,参考下图完成:

[图12]

    • 构建规范,选择“使用buildspec文件”

[图13]

    • 构件类型,选择“无构件”;其他保持默认。

构建项目创建完成:

[图14]

3.6 CodePipeline创建流水线

CodePipeline 流水线实现应用程序的自动化构建。

1.选择流水线设置,执行模式选择“已排队”:

[图15]

2.源阶段配置,选择CodeCommit中已创建的仓库:

[图16]

3.构建阶段配置,选择CodeBuild中已创建的项目:

[图17]

4.测试阶段和部署阶段,选择跳过;

5.最后创建管道成功,可以看到管道会自动执行构建:

[图18]

6.构建过程可以查看日志,如果报错也会在日志中显示出来:

[图19]

3.7 创建 EKS 集群

如无已创建 EKS 集群,可通过以下步骤创建 EKS 集群。

1. 安装 eksctl 工具,参考链接;

2. 创建 cluster-config.yaml 文件:

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: cicd-eks 
  region: cn-north-1
  version: "1.34"
autoModeConfig:
  enabled: false
managedNodeGroups:
  - name: cicd-test
    instanceType: t3.medium
    minSize: 1
    maxSize: 3
    desiredCapacity: 1
    volumeSize: 20

3. 使用 cluster-config.yaml 创建 EKS 集群:

eksctl create cluster -f cluster-config.yaml

4. 查看集群状态:

[图20]

5. 在操作终端上配置 kubectl 工具,参考链接

3.8 Argo CD

Argo CD 将清单仓库作为唯一事实来源实现应用程序的自动化部署。

1.通过 Helm 部署 Argo CD,Helm客户端安装,参考链接。

# 添加 Helm 的 Argo 仓库
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
# 创建 Argo CD 专属命名空间
kubectl create namespace argocd
# 安装 Argo CD
helm install argocd argo/argo-cd \
  -n argocd \
  --set server.service.type=LoadBalancer \
--set serviceAccount.annotations."eks\.amazonAmazon\.com/role-arn"="arn:Amazon-cn:iam::<您的AMAZON账号ID>:role/argocd-image-updater-role" \
  --wait

2.配置 IRSA

IRSA(IAM Roles for Service Accounts),是亚马逊云科技为 Amazon EKS设计的细粒度权限管控方案,核心作用是为 EKS 集群内的 K8s ServiceAccount绑定 IAM 角色,让集群内的 Pod 能通过关联的 ServiceAccount,以最小权限原则安全访问云服务(如 ECR、S3、CodeCommit、DynamoDB 等),彻底替代了传统将密钥硬编码到 Pod 配置、环境变量的不安全方式。

# 创建 IAM OIDC 身份提供商
eksctl utils associate-iam-oidc-provider --cluster cicd-eks --approve
# 获取  OIDC provider
OIDC_PROVIDER=$(Amazon eks describe-cluster --name cicd-eks --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
# 创建信任策略文件 /tmp/trust-policy.json
cat > /tmp/trust-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Federated": "arn:Amazon-cn:iam::<您的AMAZON账号ID>:oidc-provider/${OIDC_PROVIDER}"
    },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringEquals": {
        "${OIDC_PROVIDER}:sub": "system:serviceaccount:argocd:argocd-image-updater"
      }
    }
  }]
}
EOF
# 创建角色并附加策略
Amazon iam create-role \
  --role-name argocd-image-updater-role \
  --assume-role-policy-document file:///tmp/trust-policy.json

3.通过命令或是控制台给 argocd-image-updater-role 角色添加如下权限策略:

[图21]

4.配置 Argo CD

# 获取 Argo CD 登录密码
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo

使用获取的密码登录 Argo CD:

[图22]

配置代码库:

[图23]

创建应用:

[图24]

[图25]

同步应用:

[图26]

测试应用程序:

[图27]

四、流程测试

4.1 修改应用代码

1.修改 main.go 文件,并提交到 CodeCommit 代码库;

# 修改 main.go 文件里的 Version 变量
const Version = "v3.0.0"

2.CodePipeline 自动触发执行;

[图28]

3.查看 ECR 库,镜像已更新;

[图29]

4.2 修改清单文件

  1. 修改 deployment.yaml 文件,并提交到 CodeCommit 代码库:
  2. [图30]

  3. Argo CD 自动触发新版本部署:、

[图31]

4.3 验证

测试应用程序,版本已更新:

[图32]

五、 总结

本文基于 Amazon EKS 集群,落地了一套完整的 GitOps CI/CD 解决方案,整合 CodeCommit、CodePipeline、CodeBuild、ECR 与 Argo CD,实现从代码提交到应用部署的全流程自动化。后续可通过配置Argo CD Image Updater 实现自动更新清单仓库、集成测试安全扫描、完善监控报警等功能,进一步提升交付流程的效率、安全性与可观测性。

➡️ 下一步行动:

相关产品:

相关文章:

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

董文新

西云数据解决方案架构师。13年+ 软件研发和架构经验,深耕分发网络、即时通讯、大数据领域。

戴涛

西云数据解决方案架构师。13年+ IT专业服务经验,云计算项目经验丰富,擅长系统架构、容器/云原生领域。


AWS 架构师中心:云端创新的引领者

探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用