告别手动部署:在 Amazon EKS 上用 CodePipeline + Argo CD 搭建 GitOps CI/CD

告别手动部署:在 Amazon EKS 上用 CodePipeline + Argo CD 搭建 GitOps CI/CD

K8s 应用部署还在手写 kubectl apply 脚本?配置漂移查不出来?回滚得翻半天 Git log?

亚马逊云科技官博最近发了一篇实战文章:在中国区 EKS 上用 Code 家族(CodeCommit + CodePipeline + CodeBuild)+ Argo CD 搭一套完整的 GitOps CI/CD。代码一推,镜像自动构建,K8s 应用自动更新,全程不用手动敲命令。

这篇从痛点出发,走一遍完整搭建流程。

传统 CI/CD 的痛

先说为什么要 GitOps。传统 K8s 部署流程这几个问题你一定遇过:

  1. 手动脚本,出错难查deploy.sh 写了一堆 kubectl 命令,哪天参数写错了,排查半天
  2. 配置漂移:有人直接在集群里改了配置,Git 里的和实际跑的不一样,出问题了才发现
  3. 回滚困难:想回到上个版本,得找到上次的镜像 tag、对应的 YAML 文件,手动重新 apply
  4. 权限混乱:谁都能 kubectl 操作集群,改了什么没有审计记录

GitOps 的解法:Git 仓库是唯一真相来源。所有变更走 Git,Argo CD 自动同步到集群。

方案架构

复制代码
开发者 → CodeCommit(代码仓库)
         ↓ (代码推送触发)
      CodePipeline(流水线编排)
         ↓
      CodeBuild(构建镜像) → ECR(镜像仓库)
         ↓ (更新 manifest 仓库镜像版本)
      CodeCommit(清单仓库)
         ↓ (Argo CD 监控变更)
      Argo CD → EKS(自动部署/更新)

两个 Git 仓库分开管:

  • 代码仓库(cicd-test-app):业务代码 + Dockerfile + buildspec.yml
  • 清单仓库(cicd-test-manifests):K8s deployment.yaml

核心组件

组件 作用
CodeCommit 托管 Git 仓库,代码变更的入口
CodePipeline 流水线编排,串联 CI 各阶段
CodeBuild 构建容器镜像,推送到 ECR
ECR 私有镜像仓库
Argo CD GitOps CD 工具,监控清单仓库并同步到集群
Amazon EKS 托管 K8s 集群

搭建步骤

1. 创建 EKS 集群

bash 复制代码
eksctl create cluster \
  --name gitops-demo \
  --region cn-north-1 \
  --nodegroup-name workers \
  --node-type t3.medium \
  --nodes 2

2. 创建两个 CodeCommit 仓库

bash 复制代码
# 应用代码仓库
aws codecommit create-repository \
  --repository-name cicd-test-app

# K8s 清单仓库
aws codecommit create-repository \
  --repository-name cicd-test-manifests

3. 准备应用代码

示例用 Go 写一个简单 HTTP 服务:

go 复制代码
package main

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

const Version = "v1.0.0"

func handler(w http.ResponseWriter, r *http.Request) {
    hostname, _ := os.Hostname()
    fmt.Fprintf(w, "Hello from EKS! Version: %s | Host: %s\n",
        Version, hostname)
}

func main() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        fmt.Fprint(w, "OK")
    })
    log.Printf("Starting on :8080, version %s", Version)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Dockerfile(多阶段构建,最终镜像很小):

dockerfile 复制代码
FROM public.ecr.aws/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
COPY --from=builder /app/server /root/
EXPOSE 8080
CMD ["/root/server"]

4. 配置 CodeBuild(buildspec.yml)

yaml 复制代码
version: 0.2
phases:
  pre_build:
    commands:
      - echo Logging in to ECR...
      - ECR_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com.cn
      - aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_URI
      - VERSION=$(grep -oP 'const Version = "\K[^"]+' main.go)
  build:
    commands:
      - docker build -t $IMAGE_REPO_NAME:$VERSION .
      - docker tag $IMAGE_REPO_NAME:$VERSION $ECR_URI/$IMAGE_REPO_NAME:$VERSION
  post_build:
    commands:
      - docker push $ECR_URI/$IMAGE_REPO_NAME:$VERSION
      - echo Build completed, image tag $VERSION

5. 创建 CodePipeline

在控制台创建 Pipeline:

  • Source:关联 CodeCommit 的 cicd-test-app 仓库
  • Build:选择 CodeBuild 项目
  • 触发条件:代码推送到 main 分支自动触发

6. 准备 K8s 清单(deployment.yaml)

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cicd-demo
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cicd-demo
  template:
    metadata:
      labels:
        app: cicd-demo
    spec:
      containers:
      - name: app
        image: <ACCOUNT_ID>.dkr.ecr.cn-north-1.amazonaws.com.cn/cicd-test-app:v1.0.0
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: cicd-demo-svc
spec:
  type: LoadBalancer
  selector:
    app: cicd-demo
  ports:
  - port: 80
    targetPort: 8080

7. 部署 Argo CD

bash 复制代码
# 安装 Argo CD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 获取初始密码
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

# 暴露 UI
kubectl port-forward svc/argocd-server -n argocd 8080:443

8. 配置 Argo CD 应用

bash 复制代码
argocd app create cicd-demo \
  --repo https://git-codecommit.cn-north-1.amazonaws.com.cn/v1/repos/cicd-test-manifests \
  --path . \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace default \
  --sync-policy automated \
  --auto-prune \
  --self-heal

关键参数:

  • --sync-policy automated:检测到 Git 变更自动同步
  • --auto-prune:Git 里删了的资源,集群里也自动删
  • --self-heal:有人手动改了集群配置,自动恢复到 Git 定义的状态

实际工作流程

应用发新版本:

  1. 改 main.go 里的 Version = "v2.0.0"
  2. git push 到 CodeCommit
  3. CodePipeline 自动触发 → CodeBuild 构建 v2.0.0 镜像 → 推送到 ECR
  4. 更新清单仓库的 deployment.yaml 里的镜像 tag
  5. Argo CD 检测到清单变更 → 自动滚动更新 EKS 里的 Pod

回滚也简单:git revert 清单仓库到上个 commit,Argo CD 自动同步回旧版本。

这套方案好在哪

  1. 全自动化:代码推送到应用上线,分钟级完成,不用手动操作
  2. 配置不漂移--self-heal 确保集群状态永远和 Git 一致
  3. 回滚秒级:Git revert 一下就行,不用找旧镜像旧配置
  4. 审计完整:谁改了什么,Git log 里全有
  5. 权限收敛:开发者只需要 Git 权限,不需要直接访问 K8s 集群

踩坑提醒

  1. 中国区 ECR 域名 :是 .amazonaws.com.cn,不是 .amazonaws.com
  2. IRSA 权限:Argo CD 访问 CodeCommit 需要配 IRSA(IAM Roles for Service Accounts),别用明文密码
  3. 镜像版本更新:CodeBuild 构建完镜像后,还需要更新清单仓库的 tag。可以在 buildspec 里加个 git push 步骤,或者用 Argo CD Image Updater 自动检测新镜像
  4. Argo CD 同步频率:默认 3 分钟棁查一次 Git 变更,想更快可以配 webhook

亚马逊云科技官博原文:https://aws.amazon.com/cn/blogs/china/based-on-amazon-eks-using-code-argo-cd-build-gitops-cicd/

Amazon EKS:https://aws.amazon.com/cn/eks/

Argo CD:https://argo-cd.readthedocs.io/

CodePipeline:https://aws.amazon.com/cn/codepipeline/

相关推荐
Elastic 中国社区官方博客4 小时前
LINQ 到 ES|QL:使用 C# 查询 Elasticsearch
大数据·数据库·sql·elasticsearch·搜索引擎·全文检索·linq
清水白石0085 小时前
《Python 静态检查链:格式化、Lint、类型检查、安全扫描全攻略——CI 阻断策略与团队平衡实践》
python·安全·ci/cd
fengci.6 小时前
polar2026年春季个人挑战赛(WEB 困难部分)
java·大数据·elasticsearch
ACGkaka_7 小时前
ES 学习(六)设置账号密码(安全认证)
学习·安全·elasticsearch
Rabbit_QL8 小时前
【CI/CD】02_一次 git push 后发生了什么?CI 是怎么工作的
git·ci/cd
JoshRen8 小时前
springboot之集成Elasticsearch
spring boot·后端·elasticsearch
Elasticsearch8 小时前
使用 OpenTelemetry 和 Elastic 的 ML 和 AI Ops 可观测性
elasticsearch
终端行者8 小时前
记录一次ES索引迁移报错:1.两边索引参数不一致2.分析器与存储属性有冲突
elasticsearch
不会写DN9 小时前
Git 开发中最常用的命令与场景
大数据·git·elasticsearch