生产环境 DevOps 实战 | 第 2 天:CI/CD 工具链全景对比——Jenkins、GitLab CI、Tekton、Argo CD、Harbor 怎么选

第 2/60 天

引言

昨天我们论证了「为什么选 Tekton + Argo CD + Harbor 三件套」,但很多团队在选型时最大的困惑不是「某个工具好不好」,而是「摆在面前这么多工具,到底怎么组合」。打开招聘网站,Jenkins、GitLab CI、GitHub Actions、Tekton、Argo CD、Harbor、Nexus、JFrog 琳琅满目,每个都有人吹、有人骂。

选型错误代价极高:一套 CI/CD 平台一旦跑起来,几百条流水线、几千个 Job 全都挂在上面,半年后再想换,迁移成本足以让团队望而却步。本文的目的不是告诉你「谁最强」,而是给你一套可复用的选型决策框架:先分清 CI、CD、制品仓库三个层面的职责边界,再按团队规模、基础设施形态、存量资产三个维度打分,最后给出不同场景下的推荐组合。这套方法论同样适用于 K8s 之外的技术栈。

核心概念

1. 先拆解:CI、CD、制品仓库是三个不同的问题

很多团队把「CI/CD 工具」当成一个筐,什么都往里装,导致选型时拿 Jenkins 和 Argo CD 直接对比——这就像拿「发动机」和「变速箱」比谁更厉害,没有意义。正确的做法是先分层:

层面 解决什么问题 典型工具 核心职责
CI(持续集成) 代码提交后自动构建、测试、产出制品 Jenkins、GitLab CI、GitHub Actions、Tekton 拉代码、编译、单测、静态检查、构建镜像
CD(持续交付/部署) 把制品部署到目标环境,且状态可收敛、可回滚 Argo CD、Flux、Spinnaker 声明式部署、同步、自愈、渐进式发布
制品仓库 安全存储、分发构建产物(镜像/Chart/包) Harbor、Nexus、JFrog Artifactory、Quay 镜像存储、访问控制、扫描、复制、不可变

关键认知:三件套方案 = Jenkins 的 CI 职责 + 脚本式部署的 CD 职责 + Docker Registry 的存储职责,分别由 Tekton、Argo CD、Harbor 三个专业组件承担,术语叫「最佳组合」(Best-of-Breed),而不是「全家桶」(All-in-One)。

2. CI 工具横向对比

维度 Jenkins GitLab CI GitHub Actions Tekton
架构形态 Master/Agent,需自维护 Runner 池,托管或自建 托管 SaaS Kubernetes 原生 CRD
流水线定义 Jenkinsfile(Groovy) .gitlab-ci.yml(YAML) workflow YAML Task/Pipeline CRD(YAML)
容器化支持 依赖插件(Kubernetes Plugin) 原生支持容器 Job 原生容器 天生容器化,每个 Step 一个容器
可移植性 一般,绑定 Jenkins 生态 绑定 GitLab 绑定 GitHub 完全云原生,跨厂商
高可用 Master 单点,需额外方案 平台托管 平台托管 无 Master,控制器多副本
学习曲线 中(Groovy 脚本) 中(K8s 概念门槛)
适用场景 存量企业、非容器环境 GitLab 重度用户 GitHub 托管项目 K8s 平台团队、PaaS 平台建设

3. 制品仓库对比

维度 裸 Docker Registry Harbor Nexus / JFrog
镜像存储 ✅ 基础
项目级权限隔离 ✅ 项目/成员/角色
Robot Account ✅ 机器凭证 部分
漏洞扫描 ✅ Trivy/Clair ✅ 需商业版
制品复制(异地) ✅ 复制规则
OCI 制品(Helm/SBOM) 部分
开源即可用程度 简单但裸 功能完整 社区版功能受限

4. CD 工具:为什么 GitOps 工具单独成一类

Jenkins 也能「部署」,它通过 SSH 到服务器执行脚本、或调用 kubectl 完成。但这属于命令式部署:执行完即结束,集群后续漂移了没人管。Argo CD 代表的是声明式 GitOps:Git 仓库是唯一事实来源,控制器持续对照「Git 里声明的状态」与「集群实际状态」,有偏差就自动收敛。这不是功能增强,而是运维模型的重构。

实战步骤

下面给出一个可落地的选型 + 验证流程:先打分,再在本地用 kind 起集群对候选工具做最小化验证。

1. 用 Python 脚本给工具链打分(选型决策数字化)

#!/usr/bin/env python3
"""工具链选型评分脚本:按团队实际情况加权打分"""
import json

WEIGHTS = {
    "k8s_native": 0.25,      # 与 K8s 平台融合度
    "维护成本": 0.20,        # 越低越好
    "生态成熟度": 0.20,
    "团队学习成本": 0.15,
    "可扩展性": 0.10,
    "合规与安全": 0.10,
}

SCORES = {
    "Jenkins":   {"k8s_native": 5, "维护成本": 5, "生态成熟度": 10, "团队学习成本": 7, "可扩展性": 8, "合规与安全": 7},
    "GitLabCI":  {"k8s_native": 6, "维护成本": 7, "生态成熟度": 8,  "团队学习成本": 9, "可扩展性": 7, "合规与安全": 8},
    "Tekton":    {"k8s_native": 10,"维护成本": 9, "生态成熟度": 8,  "团队学习成本": 6, "可扩展性": 10,"合规与安全": 9},
}

def total(name: str) -> float:
    return round(sum(SCORES[name][k] * v for k, v in WEIGHTS.items()), 2)

ranking = sorted(SCORES, key=total, reverse=True)
print(json.dumps({name: total(name) for name in ranking}, ensure_ascii=False, indent=2))
# 输出示例:Tekton 权重最高,说明 K8s 原生优势在加权后显现

2. 用 kind 快速起一个测试集群,验证 Tekton 的声明式 CI

选型不能只看 PPT,本地 5 分钟就能验证 Tekton 的「K8s 原生」体验:

# 安装 kind 并创建集群
brew install kind   # 或 curl -Lo kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
kind create cluster --name devops-test
kubectl cluster-info

# 安装 Tekton Pipelines
kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
kubectl wait --for=condition=Ready pods -n tekton-pipelines -l app=tekton-pipelines-controller --timeout=120s

注意观察:Tekton 安装完没有 Master、没有 Agent 池,全部是 CRD + Controller 部署在集群里,这是它与 Jenkins 最本质的架构差异。

3. 写一个最小 Tekton Pipeline,感受「流水线即代码」

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: build-test-pipeline
spec:
  tasks:
    - name: unit-test
      taskSpec:
        steps:
          - name: run-tests
            image: golang:1.22
            script: |
              go test ./...
    - name: build-image
      runAfter: [unit-test]
      taskSpec:
        steps:
          - name: build
            image: gcr.io/kaniko-project/executor:latest
            args:
              - --context=$(workspaces.src.path)
              - --destination=registry.example.com/app:v1.0.0
  workspaces:
    - name: src

对比 Jenkinsfile 的 Groovy 语法,Tekton 的 Pipeline 本身就是 K8s API 资源,可以用 kubectl get pipeline 查看、被 GitOps 管理、被 RBAC 控制——这是它能在平台工程中胜出的根本原因。

4. 用决策矩阵 JSON 记录最终选型结论

{
  "team": "某金融科技公司 DevOps 平台组",
  "infra": "自建 Kubernetes 1.28,多环境 dev/staging/prod",
  "git": "自建 GitLab(计划迁移 Gitea)",
  "decision": {
    "ci": "Tekton(K8s 原生,服务化给 20 个业务团队)",
    "cd": "Argo CD(GitOps,多集群统一管控)",
    "registry": "Harbor(二级制仓库 + 扫描 + Robot Account)",
    "rejected": {
      "Jenkins": "存量无 Jenkins,无需兼容历史资产",
      "GitLab CI": "团队不想绑定单一 Git 平台",
      "GitHub Actions": "代码不允许上公有云"
    }
  },
  "migration": "先以 Tekton + Argo CD 双轨运行 3 个月,再停旧流程"
}

5. 三件套与「裸 Registry」的最小对比验证

# 方案 A:裸 Docker Registry(只解决存储)
docker run -d -p 5000:5000 --name registry registry:2
curl http://localhost:5000/v2/_catalog   # 无认证、无扫描、无隔离

# 方案 B:Harbor(企业级制品仓库)
curl -sL https://raw.githubusercontent.com/goharbor/harbor/v2.10.0/harbor/harbor.yml.tmpl -o harbor.yml
sed -i 's|hostname: reg.mydomain.com|hostname: harbor.example.com|' harbor.yml
./install.sh --with-trivy

# 验证差异:Harbor 提供 /api/v2.0/projects 权限隔离 API,裸 Registry 没有
curl -u admin:xxx https://harbor.example.com/api/v2.0/projects

同样是「存镜像」,两者能力差距巨大:Harbor 提供项目隔离、Robot Account、漏洞扫描、复制规则、审计日志,而这些正是生产环境合规审计的硬性要求。

6. 快速验证 Argo CD 的 GitOps 部署闭环

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 创建 Application:声明期望状态来自 Git
cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: demo-app
  namespace: argocd
spec:
  destination:
    server: https://kubernetes.default.svc
    namespace: demo
  source:
    repoURL: https://git.example.com/team-a/demo-app.git
    path: manifests
    targetRevision: main
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
EOF

kubectl -n argocd get application demo-app   # 状态变为 Synced

把 Git 仓库里 manifests/ 目录的副本数从 2 改成 3,几秒后 Argo CD 会自动把集群收敛到 Git 声明的状态——这就是「自愈」,Jenkins 式的脚本部署永远做不到。

常见问题

Q1:Jenkins 和 Tekton 能共存吗?
能,而且这是很多团队的过渡策略。可以把 Jenkins 的构建产物推到 Harbor,再用 Tekton 逐步替换高频流水线;或反过来,用 Jenkins 兼容历史 Job、Tekton 承担所有新建 K8s 相关流水线。双轨运行 2-3 个月再彻底切换,风险最低。

Q2:Argo CD 和 Jenkins 的「部署步骤」有什么区别?
Jenkins 的部署是命令式的:执行 kubectl apply 或 ssh 脚本,执行完就完事,集群状态之后漂移没人管。Argo CD 是声明式的:Git 是唯一事实来源,控制器持续比对并收敛,任何手动改动都会被自动修复。前者是「动作」,后者是「状态管理」。

Q3:项目不大,必须用 Harbor 吗?裸 Docker Registry 不行吗?
如果只是个人学习、单机环境,裸 Registry 够用。但只要涉及多人协作或生产环境,就建议用 Harbor:Robot Account 让 CI 免交互推送、项目级隔离防止团队间误操作、Trivy 扫描防止带漏洞镜像上线,这些是安全审计的底线。Harbor 本身也开源,没有商业版锁死问题。

Q4:Tekton 上手是不是特别难?
门槛不在 Tekton 本身,而在 Kubernetes。如果一个团队已经有 K8s 运维能力(会写 Deployment、懂 RBAC),Tekton 的学习曲线其实比 Jenkins 平滑——因为不用学 Groovy,全是 YAML。反过来,如果团队完全没有 K8s 基础,Tekton 会显得陡峭,此时 GitLab CI 或 Jenkins 更合适作为第一步。

Q5:GitLab CI 自带 Registry 和 Kubernetes 部署能力,为什么还要三件套?
GitLab 的 K8s 集成是「平台帮你做」,灵活度受限:流水线跑在 Runner 上而非集群内、部署能力依赖 agent 和专用 API、制品仓库功能(扫描/复制/Robot Account)不如 Harbor 完整。三件套的价值是解耦:任何组件都可替换,不绑定 Git 平台、不绑定云厂商,适合平台工程导向的中大型团队。

总结

  1. 选型先分层:CI、CD、制品仓库是三个独立问题,别拿 Engine 和 Gearbox 直接对比。「Jenkins vs Argo CD」这类问题是伪命题。
  2. 三件套的本质是 Best-of-Breed:Tekton 管构建、Harbor 管制品、Argo CD 管部署,每个环节用最专业的组件,且全部 K8s 原生、全部开源、全部可替换。
  3. 决策要数字化:用加权评分(K8s 融合度、维护成本、生态、学习成本)把「感觉」变成分数,再用 kind 本地验证,避免 PPT 选型。
  4. 迁移讲节奏:不必一刀切。Jenkins/存量系统可以双轨运行,先让新项目跑三件套,成熟后再迁移旧流水线。
  5. 记住主线:整套方案的护城河不是某个工具,而是「声明式」——Pipeline 是声明式、部署状态是声明式、制品策略是声明式,这决定了它可审计、可回滚、可规模化的上限。

下期预告

第 3 天:生产环境 DevOps 架构设计——从代码提交到上线的全链路蓝图

下一篇我们将从「工具选型」上升到「架构设计」:画出一张从 Git 提交 → Tekton 构建 → Harbor 存储 → Argo CD 部署 → 生产环境的完整链路图,并拆解每个环节的命名空间规划、凭据流转、网络拓扑与安全边界,为后续 57 天的实战打下骨架。


📚 系列目录(持续更新中)

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容