- 文档/教程
【免费下载链接】90DaysOfDevOps
This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.
本篇是 90DaysOfDevOps 挑战 Day 70 的技术解读,围绕现代 DevOps 环境的支柱——CI/CD(持续集成/持续部署)管道展开:从软件开发生命周期(SDLC)的无限循环讲起,深入 CI 的自动化构建与测试、CD 的环境部署与制品交付,并结合本仓库中真实的 Jenkins Helm 部署清单、Kubernetes 权限配置与声明式 Jenkinsfile 流水线,给出可落地、可复现的实践路径。
为什么说 CI/CD 是现代 DevOps 环境的支柱
CI/CD(Continuous Integration / Continuous Deployment)管道通过自动化应用的构建(Build)、测试(Test)与部署(Deploy),从根本上弥合了开发(Dev)与运维(Ops)之间的鸿沟。正如本仓库 Day 70 英文原稿 与 韩文翻译版 所强调的:这不是一个可选项,而是现代 DevOps 环境的"支柱"(backbone)。
- 快速高效地交付软件:把从代码提交到生产上线的过程压缩到分钟级甚至秒级。
- 加速产品上市:通过有效的流程,让应用以最快速度触达市场。
- 持续交付增量价值:无需等待数月甚至数年的版本发布周期,缺陷修复和新功能可以像"流水线"一样源源不断地流出。
它的核心价值在于:让开发者能够频繁地做出小而关键(small impactful changes)的变更,从而获得更快的修复速度和更高的功能产出速度。
软件开发生命周期(SDLC):永不停歇的无限循环
在深入 CI/CD 之前,先回到 DevOps 的理论基础。本仓库在 Day 5 的 DevOps 理论讲解 中已经系统性地介绍了这些概念,Day 70 则站在"更深入学习"的视角,重新强调 SDLC 中与 CI/CD 直接相关的关键环节。
软件开发生命周期(Software Development Life Cycle, SDLC)是一个永远重复的循环,因此通常被画在"无限循环"(infinity loop)中:
- 代码(Code):开发者编写代码;
- 构建(Build):代码被编译、整合在一起;
- 测试(Test):对代码进行缺陷检测;
- 部署(Deploy)/ 运营(Operate):发布到生产环境,供终端用户或客户使用;
- 监控(Monitor):收集反馈与运行指标;
- 计划(Plan):围绕反馈规划改进,然后"冲洗、重复"(rinse and repeat)。
CI 与 CD 恰好覆盖了这个循环中最容易出错的三个环节——构建、测试与部署,并把它们从"人工操作"变成"自动触发的流水线"。
深入 CI:持续集成的原理与工作流
持续集成的定义
持续集成(Continuous Integration)是一种现代软件开发实践,要求开发者每天多次将代码变更集成(integrate)到一个共享仓库中。其核心逻辑是:
- 增量式代码变更,频率更高、更可靠;
- 由 CI 触发的自动化构建与测试工作流步骤,确保合并进仓库的代码变更是可信赖的。
代码编写完成并 push 到 GitHub 或 GitLab 这样的代码仓库之后,"魔法"便开始了:自动化构建对代码进行验证,让团队或项目所有者尽早发现问题。
三类核心自动化测试
代码被分析后,会接受一系列自动化测试,其中最常见的三类是:
| 测试类型 | 作用 |
|---|---|
| 单元测试(Unit Testing) | 测试源代码的单个独立单元(函数、方法、模块) |
| 验证测试(Validation Testing) | 确认软件满足或适配预期用途 |
| 格式测试(Format Testing) | 检查语法及其它格式错误 |
测试以 Workflow 形式存在,随 push 触发
这些测试被组织成Workflow,并配置为每次向 master 分支 push 时自动执行。这也是为什么几乎所有主流开发团队都会搭建某种形式的 CI/CD workflow——因为在全球化协作的开发团队里,来自不同时区、不同项目的开发者随时都可能提交新代码,构建一套自动化测试工作流、在代码被接受之前确保"所有人都在同一页面上",远比每次由人工执行高效得多。
测试全部通过并成功后,就可以将代码编译并推送到制品仓库——例如 Docker Hub。这个制品仓库中的镜像,将在后续 CD 阶段被消费和部署:
可以看到,CI 阶段本身与软件开发的日常节奏高度一致:创建应用、添加/修复缺陷、更新源代码管理、做版本管理,同时持续测试。
一个值得关注的行业趋势
原作者在文档中特别指出一个趋势:越来越多的商业软件(off-the-shelf software)开始以"制品"形式交付。比如从 Oracle、Microsoft 等供应商获取软件时,很可能是从 Docker Hub 类型的制品仓库中"消费"镜像,然后再用自己的 CD 管道把这些软件部署到自身环境中。这意味着 CD 能力将逐渐成为每个团队的基础设施级能力。
深入 CD:持续部署与环境的制品交付
持续部署的定义
当 CI 阶段产出了测试通过的代码版本,就进入持续部署(Continuous Deployment,CD)阶段:把代码发布到目标环境。这里的"环境"不仅指生产环境,通常还包括**暂存(staging)**等其它环境。
软件供应商会完整走通这个阶段,而原作者相信:未来我们所有人都将以这种方式部署所需的商业软件——即从制品仓库消费镜像,再通过 CD 管道投放至自己的环境。
CD 的关键:正确代码 + 正确配置 → 正确环境
在软件部署的第一天(v1 首版),下一步要确保的是:把正确的代码基座(code base)拉取到正确的环境。
- 制品可能来自软件仓库(如 Docker Hub)——拉取最新发布版本;
- 与此同时,还很可能从另一个代码仓库(Git 仓库)拉取应用配置;
- 这些工作由CD 工具统一执行,把所有内容推送到目标环境。
需要特别强调的是:软件与配置的部署通常不会同时进行。更常见的做法是:
- 先进入暂存环境,携带新配置运行,验证一切正确;
- 这一步可以是人工测试步骤,也可以再次自动化(推荐自动化);
- 验证通过后,才允许代码被部署到生产环境。
当应用发布v2时,流程重复:将"应用 + 配置"部署到暂存,确认无误,再部署到生产。这种"暂存先行、生产随后"的分阶段推进,是降低发布风险的核心手段。
为什么必须使用 CI/CD
自动化与小问题的早期拦截
CI/CD 的价值在于把原本必须手动完成的工作自动化,并在小问题悄悄溜进主代码库之前将其拦截。可以想象,如果把坏代码直接推到客户面前,后果将不堪设想。
防止技术债(Technical Debt)
CI/CD 还有助于防止"技术债"的累积。技术债的概念是:主代码仓库会随时间不断被构建叠加,第一天采取的"捷径式修复",几年后会变成指数级昂贵的修复——因为当初那块"创可贴"式的修复,已经深深地交织、烘焙进所有代码库与业务逻辑之中。持续集成让每次变更都被即时验证,避免坏味道长期潜伏在代码库深处。
工具选型:Jenkins、ArgoCD 与 GitHub Actions
进入实战环节前,先明确一个关键认知:并非所有工具都必须同时承担 CI 与 CD 两种职责。
- Jenkins:成熟的 CI/CD 平台,可跨多种平台工作,既能做 CI 也能做 CD;
- ArgoCD:专注于CD 元素,尤其擅长把软件部署到Kubernetes 集群,是 GitOps 理念的代表实现;
- GitHub Actions:与 GitHub 仓库深度集成的自动化工作流平台,workflow 以 YAML 文件"即代码"形式存在。
原文档在"资料(Resources)"一节为以上三款工具附有一批官方文档与入门视频资源,可直接在仓库的 day70.md(英文版见 day70.md)中查看。
实战佐证 1:用 Helm 在 Kubernetes 上部署 Jenkins
本仓库的 2022/Days/CICD/Jenkins/ 目录保存了 Day 71 起 Jenkins 实战的完整部署材料,其中 steps.md 记录了端到端部署步骤。下面结合仓库中的真实清单文件逐段讲解:
第一步:准备本地 Kubernetes 环境与命名空间
minikube start kubectl create namespace jenkins # 或者使用仓库中的声明式清单: kubectl create -f 2022/Days/CICD/Jenkins/jenkins-namespace.yml kubectl get namespacesjenkins-namespace.yml 非常简单,只声明了一个名为jenkins的 Namespace,作为 Jenkins 控制器的隔离空间。
第二步:添加官方 Helm 仓库
helm repo list helm repo add jenkinsci https://charts.jenkins.io helm repo update第三步:创建持久卷(PV)与 ServiceAccount(RBAC)
kubectl apply -f 2022/Days/CICD/Jenkins/jenkins-volume.yml kubectl apply -f 2022/Days/CICD/Jenkins/jenkins-sa.ymljenkins-volume.yml 定义了一个hostPath类型的 PersistentVolume:
storageClassName: jenkins-pv:与 Helm values 中persistence.storageClass对应;capacity.storage: 20Gi:分配 20Gi 容量;accessModes: ReadWriteOnce:单节点读写;persistentVolumeReclaimPolicy: Retain:PV 释放后保留数据,防止误删 Jenkins 数据;hostPath.path: /data/jenkins-volume/:宿主机上的数据落盘目录。
jenkins-sa.yml 则一次性创建了三个 RBAC 对象:
- ServiceAccount
jenkins(位于 jenkins 命名空间):供 Jenkins 控制器 Pod 使用; - ClusterRole
jenkins:授予对statefulsets、services、replicasets、pods、pods/log、pods/exec、persistentvolumes、persistentvolumeclaims、deployments、configmaps、secrets、events等资源执行create/get/watch/delete/list/patch/update的权限,也覆盖nodes的读取类权限——这是 Jenkins 以 Kubernetes 为云(cloud)动态调度代理 Pod 的基础; - ClusterRoleBinding
jenkins:将上述 ClusterRole 绑定到system:serviceaccounts:jenkins组,使 jenkins 命名空间下的所有 ServiceAccount 都具备该权限。
第四步:通过 Helm 安装 Jenkins 控制器
chart=jenkinsci/jenkins helm install jenkins -n jenkins -f 2022/Days/CICD/Jenkins/jenkins-values.yml $chartjenkins-values.yml 是本次安装的核心配置,几个关键项值得展开:
controller.image: "jenkins/jenkins"+tagLabel: jdk11:使用官方镜像的 jdk11 变体;adminUser: "admin"+adminSecret: true:启用 Chart 内置管理员账户,初始密码由 Helm 自动生成(见下文获取方式);servicePort: 8080+serviceType: ClusterIP:控制器服务端口;minikube 环境可改用 NodePort,生产环境可用 LoadBalancer 或配合 Ingress;healthProbes: true:启用 startup/liveness/readiness 三类探针,对/login端点做 HTTP 探测,配合failureThreshold、periodSeconds等参数保障控制器在插件重启等场景下的健康恢复;installPlugins:预装四个关键插件——kubernetes:1.31.3(Kubernetes 云/动态代理)、workflow-aggregator:2.6(Pipeline 流水线)、git:4.10.2(Git 源码管理)、configuration-as-code:1.55.1(JCasC 配置即代码);JCasC.securityRealm:以"配置即代码"方式声明本地安全域,使用${chart-admin-username}/${chart-admin-password}占位符注入管理员凭据,并设置allowsSignup: false(禁止匿名注册)、enableCaptcha: false;authorizationStrategy采用loggedInUsersCanDoAnything(登录用户可操作、禁止匿名读取);agent:默认代理镜像jenkins/inbound-agent:4.11.2-4,containerCap: 10限制最多并发 10 个代理 Pod,podRetention: "Never"表示构建完成后立即回收代理 Pod;persistence.enabled: true+storageClass: jenkins-pv+size: 8Gi:控制器数据持久化到前述 PV 对应的存储类。
第五步:修正 PV 目录权限并重启控制器
minikube ssh sudo chown -R 1000:1000 /data/jenkins-volume kubectl delete pod jenkins-0 -n jenkins kubectl get pods -n jenkins -wJenkins 官方镜像以 UID1000(jenkins 用户)运行,而hostPath卷的宿主机目录默认属主可能是 root,因此需要将/data/jenkins-volume递归授权给1000:1000,随后删除jenkins-0Pod 让其以正确权限重建。
第六步:获取管理员密码并登录
kubectl exec --namespace jenkins -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/chart-admin-password && echo kubectl --namespace jenkins port-forward svc/jenkins 8080:8080打开浏览器访问http://localhost:8080,用admin与上面取出的密码登录,然后执行插件更新即可开始使用。
实战佐证 2:声明式 Jenkinsfile —— 容器化流水线的完整结构
仓库中的 Pipeline/Jenkinsfile 展示了一条完整的声明式(Declarative)Pipeline,是"CI 验证 → 镜像构建 → 镜像推送"这条自动化链路的直接落地:
podTemplate:用内联 YAML 定义一个一次性运行 Pod,包含两个容器——maven:3.8.1-jdk-8(构建/测试容器,sleep 99d保持存活)和gcr.io/kaniko-project/executor:debug(镜像构建容器,挂载名为kaniko-secret的 Secret 到/kaniko/.docker,即把 Docker 凭据以config.json形式提供给 kaniko 使用);stage('Clone Repository'):在流水线节点上git clone示例应用仓库的main分支(对应源码托管仓库中的 HelloWorld 演示项目);stage('Build Image'):进入maven容器执行构建(示例中以echo "Tests passed"模拟测试通过的验证步骤);stage('Test Image'):进入kaniko容器执行/kaniko/executor --context \pwd` --destination <镜像名>: `,在无需 Docker Daemon 的情况下完成镜像构建并推送到制品仓库——这正是文档中所描述的"测试通过后编译并推送制品仓库"的真实实现。
配套的 Pipeline/Dockerfile 则是最小可运行应用的构建配方:
FROM busybox:latest ENV PORT=8000 ADD index.html /www/index.html # 健康检查(原文指令,需结合具体环境修正后使用) HEALTHCHECK nc -z localhost $PORT # 启动内置 httpd,监听 $PORT,服务 /www 目录,直至容器被停止 echo "httpd started" && trap "exit 0;" TERM INT; httpd -v -p $PORT -h /www -f & wait该镜像将index.html放入/www,用 busybox 内置的httpd启动一个静态 Web 服务——这正是 CD 阶段将要被拉取、部署到目标环境的最小制品样本。
小结与下一步
Day 70 从理论到工具为 CI/CD 画出了一张完整的"全景图":CI 负责把每天多次的代码集成变成自动化的构建与测试,CD 负责把测试通过的制品连同配置安全地推进到暂存与生产环境,而自动化带来的即时反馈与对技术债的遏制,是这套体系长期运转的根本动力。
在工具层面,本仓库已经为接下来的动手环节准备好了完整的 Jenkins 落地素材(CICD 目录),后续将依次深入 Jenkins 的更多细节、ArgoCD 在 Kubernetes 上的 GitOps 式持续部署,以及 GitHub Actions 的 workflow 编写。下一站是 Day 71。
- 文档/教程
【免费下载链接】90DaysOfDevOps
This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.
相关推荐
90DaysOfDevOps 第 70 天:CI/CD 流水线全景——从持续集成到持续部署的完整认知
90DaysOfDevOps 第 70 天:CI/CD 流水线全景——从持续集成到持续部署的完整认知 导读:本文是 90DaysOfDevOps 挑战计划中第
文档/教程90DaysOfDevOps:CI/CD 管道全景——从持续集成到持续部署的完整闭环
90DaysOfDevOps:CI/CD 管道全景——从持续集成到持续部署的完整闭环 导读 本文是 90DaysOfDevOps 挑战第 70 天的核心内容(
文档/教程Materialize持续集成/持续部署(CI/CD)实践
Materialize持续集成/持续部署 CI/CD 实践 你是否还在为前端框架的测试部署流程繁琐而烦恼?Materialize作为基于Google Mater
前端UI组件设计系统
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考