Jenkins 遇见 Argo CD:构建可靠 GitOps 流水线的实战指南
Jenkins 可以说是 CI 领域的老牌 “瑞士军刀”,无数团队用它构建、测试、打包应用。但当部署环节还停留在kubectl apply脚本或 SSH 到服务器时,版本不可追踪、配置漂移、回滚困难这些痛点就会接踵而至。这时候,引入 Argo CD 实践 GitOps,让 Jenkins 与 Argo CD 各司其职,往往能让交付流水线瞬间变得优雅且可靠。本文将带你一步步拆解它们如何协同工作。
重新划分职责:CI 与 CD 彻底解耦
传统 Jenkins 流水线通常一头扎到底:拉代码 → 测试 → 构建镜像 → 直接部署到 Kubernetes。部署步骤里塞满了复杂的 Shell 命令和 if-else 判断,久而久之,流水线变成了难以维护的“面条代码”。
GitOps 的理念则要求我们有一个“声明式的单一事实来源”——Git 仓库。集群的期望状态全部用 YAML 描述,并由控制器自动同步。于是 Jenkins 和 Argo CD 的职责变得异常清晰:
Jenkins 负责 CI(持续集成):编译、测试、构建容器镜像、推送镜像,以及最关键的一步——把新镜像的标签写回 GitOps 仓库。
Argo CD 负责 CD(持续部署):监视 GitOps 仓库中的声明变更,自动(或手动批准后)将集群的实际状态调和为期望状态。
这种分工让每一环都专注本行:Jenkins 确保代码和镜像质量;Argo CD 确保集群与 Git 声明一致。部署逻辑不再深埋在流水线脚本里,而是透明地记录在 Git 提交历史中。
实战:构建一条 Jenkins → Argo CD 流水线
以下是一个典型的 GitOps 流水线设计,以微服务user-service为例。
仓库结构
我们使用两个独立的 Git 仓库(也可以合并在一个仓库不同目录,但分开更利于权限和职责隔离):
应用仓库(
app-user-service):存放服务源码、Dockerfile、Jenkinsfile。GitOps 仓库(
gitops-deployments):存放所有服务的 Kubernetes 部署清单,例如deployments/user-service/下包含 Deployment、Service 等 YAML,使用 Kustomize 或 Helm 编排。
Jenkins Pipeline:三步到位
Jenkins 在完成测试构建后,重点是优雅地更新 GitOps 仓库。下面是一段简化但完整的 Jenkinsfile 片段:
groovy
pipeline { agent any environment { IMAGE_TAG = "v${BUILD_NUMBER}" REGISTRY = "myregistry.io" APP_NAME = "user-service" GITOPS_REPO = "github.com/team/gitops-deployments.git" } stages { stage('Build & Push Image') { steps { sh "docker build -t ${REGISTRY}/${APP_NAME}:${IMAGE_TAG} ." sh "docker push ${REGISTRY}/${APP_NAME}:${IMAGE_TAG}" } } stage('Update GitOps Repo') { steps { // 检出 GitOps 仓库 git branch: 'main', url: "https://${GIT_CREDENTIALS}@${GITOPS_REPO}" // 用 Kustomize 修改镜像标签(也可以用 sed/yq 修改普通 YAML) dir("deployments/${APP_NAME}") { sh "kustomize edit set image ${REGISTRY}/${APP_NAME}:${IMAGE_TAG}" } // 提交变更并推送 sh ''' git config user.email "jenkins@team.com" git config user.name "Jenkins CI" git add . git commit -m "Update ${APP_NAME} image tag to ${IMAGE_TAG}" git push origin main ''' } } } }要点:
尽量使用Kustomize或Helm这类结构化工具修改清单,而不是粗暴的
sed替换,这能避免格式破坏。GitOps 仓库的 push 应设置严格的分支保护:要求 PR、代码审查、CI 检查,但这条流水线推送通常是自动的;如果要求审批,可以让 Jenkins 只创建一个 PR 分支,由人工合并,而不是直接推送 main。
Argo CD:自动同步集群
在集群中,我们为user-service定义一个 Argo CD Application:
yaml
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: user-service namespace: argocd spec: project: default source: repoURL: https://github.com/team/gitops-deployments.git targetRevision: main path: deployments/user-service destination: server: https://kubernetes.default.svc namespace: user-service syncPolicy: automated: prune: false # 谨慎开启 prune selfHeal: true # 自动修复手动修改
当 Jenkins 推送新镜像标签后,Argo CD 检测到 Git 仓库中 Kustomize 描述的 Deployment 镜像字段发生变化,如果开启了automated策略,它将自动执行kubectl apply,滚动更新 Pod。
如果你需要手动审批,可以关闭automated,只使用 Argo CD 的 UI/CLI 点击 “Sync” 按钮,或者通过 Webhook 触发特定审批流。
多环境管理:同样的流水线,不同的目标
很多团队需要管理开发、预发、生产环境。同样一套 Jenkins + Argo CD 组合可以灵活应对。
GitOps 仓库分支/路径策略:
例如,GitOps 仓库维护staging和production分支,或使用目录overlays/staging、overlays/production存放 Kustomize overlays。
Jenkins 根据构建分支或参数,更新对应环境的清单。例如,main分支构建触发更新 staging 目录,release分支触发更新 production 目录。Argo CD ApplicationSet:
利用 ApplicationSet 根据目录或集群自动为每个环境生成 Application,无需重复配置。
密钥处理:别把密码放在 Git 里
这是 Jenkins + Argo CD 协作中极易疏忽的一环。Secret 绝不能以明文形式保存在 GitOps 仓库中。推荐两种方案:
External Secrets Operator:存储密文在 Vault 或云密钥管理服务中,通过 ExternalSecret 资源从集群内同步,该资源可以安全地存放在 GitOps 仓库。
Sealed Secrets:Jenkins 或开发者在本地将 Secret 加密成 SealedSecret 后提交,集群控制器解密生成真正的 Secret。
无论如何,Jenkins 都不要在更新清单时写入明文密码,这是安全底线。
回滚:比以往任何时候都简单
过去你可能要跑另一个 Jenkins Job 执行一堆 kubectl 命令回滚。有了 GitOps,回滚变成了纯粹的 Git 操作:
方案一:在 GitOps 仓库中
git revert那个更新镜像标签的 commit,并推送。Argo CD 检测到变更后自动(或手动)同步回旧版本。这符合完整的审计记录。方案二:直接在 Argo CD UI 中使用 “History and Rollback” 功能,退回到之前的同步版本。但注意这是绕过 Git 的临时操作,应配合后续 Git 修正。
常见误区提醒(来自实践者的血泪)
把 Argo CD 当 CI 用:不要试图让 Argo CD 执行镜像构建,那个世界属于 Jenkins。
开启自动修剪 (
prune: true) 而不加思索:一旦 Git 目录误删,集群资源会被瞬间清除,生产环境可能迎来灾难。建议谨慎开启,或配合 Sync Windows 限制。Jenkins 直接推送 GitOps 仓库的 main 分支无保护:至少要求 CI 流水线自身通过后可合并,或使用 Git 钩子做基本校验。
忘记监控 Argo CD 自身:Argo CD 控制器宕机会让自动同步失效,务必对其健康状态进行监控。
Jenkins 触发 Argo CD 同步打破 Git 事实来源:有时团队喜欢在 Jenkins 更新完 Git 后立即调用 Argo CD API 强制同步,这并非不可,但会掩盖 Argo CD 自身的自动同步能力,并可能造成状态混乱。更纯粹的 GitOps 方式是让 Argo CD 按自己的节奏同步(或 webhook 触发)。
结语
Jenkins 与 Argo CD 的组合,不是对旧工具的抛弃,而是一次优雅的能力重新划分。Jenkins 继续擅长它最拿手的持续集成和自动化管道,而部署的“最后一公里”则交给 Argo CD,让它以声明式的方式守护集群的终态。这样一来,你的交付流水线既保留了 Jenkins 生态的灵活性,又获得了 GitOps 带来的可审计性、一致性和极速回滚能力。
现在,不妨检查一下你现有的 Jenkins 流水线,把那些复杂的部署脚本,迁移到 Git 仓库里,让 Argo CD 开始倾听 Git 的声音吧。这条融合之路,值得一试。