3. CI/CD 流水线基础:Jenkins/GitLab CI/CD 流水线概念、阶段划分与触发方式
在 Kubernetes 发布流水线中,CI/CD 流水线是自动化安全扫描与回滚触发的执行载体。理解流水线的核心概念、阶段划分与触发机制,是构建可靠发布流程的前提。本章聚焦 Jenkins 与 GitLab CI/CD 两种主流工具,对比其流水线模型与阶段设计。
3.1 流水线核心概念
CI/CD 流水线将软件交付过程分解为一系列自动化阶段,每个阶段包含一个或多个任务。流水线的核心价值在于:
- 可重复性:每次执行使用相同的流程与配置,消除人为差异。
- 可观测性:每个阶段的状态、日志与产物清晰可见。
- 可控制性:支持手动审批、条件分支与失败回滚。
关键概念对照: Jenkins 使用 Pipeline(声明式/脚本式)定义流程;GitLab CI/CD 使用 .gitlab-ci.yml 文件定义流程。两者均支持阶段(stage)、任务(job)、触发条件(trigger)三大要素。
3.2 阶段划分模型
一个典型的 K8s 发布流水线通常包含以下阶段。下表对比了 Jenkins 与 GitLab CI/CD 的阶段定义方式:
| 阶段 | Jenkins 实现方式 | GitLab CI/CD 实现方式 | 典型任务 |
|---|---|---|---|
| 代码检出 | checkout scm |
stage: fetch + git clone |
拉取源码、子模块、LFS 文件 |
| 代码编译 | sh 'mvn compile' |
stage: build + script: mvn compile |
编译、依赖安装、静态资源构建 |
| 单元测试 | sh 'mvn test' |
stage: test + script: mvn test |
单元测试、代码覆盖率收集 |
| 安全扫描 | sh 'trivy image ...' |
stage: security + script: trivy image ... |
SAST、DAST、镜像漏洞扫描、依赖检查 |
| 镜像构建与推送 | sh 'docker build ...' + docker push |
stage: package + docker build + docker push |
Dockerfile 构建、镜像标签、推送至仓库 |
| 部署至 K8s | sh 'kubectl apply ...' |
stage: deploy + kubectl apply |
更新 Deployment、Service、ConfigMap |
| 健康检查与回滚 | sh 'kubectl rollout status ...' + 条件回滚 |
stage: verify + script: kubectl rollout status |
Pod 就绪检查、回滚至上一版本 |
阶段顺序注意: 安全扫描应放在镜像构建之前(对源码扫描)或镜像构建之后(对镜像扫描),但必须在部署之前完成。若安全扫描失败,应阻止后续阶段执行,避免有漏洞的镜像进入生产环境。
3.3 触发方式对比
流水线的触发方式决定了何时开始执行。Jenkins 与 GitLab CI/CD 均支持多种触发策略:
| 触发方式 | Jenkins | GitLab CI/CD | 适用场景 |
|---|---|---|---|
| 代码推送 | Webhook + Generic Webhook Trigger |
push 事件自动触发 |
开发分支、功能分支 |
| 合并请求 | Webhook + GitHub Pull Request Builder |
merge_request 事件 |
代码审查前验证 |
| 定时触发 | cron 语法配置 |
schedule 关键字 |
夜间安全扫描、定期依赖更新 |
| 手动触发 | build 按钮 + 参数化构建 |
when: manual 关键字 |
生产环境部署、紧急回滚 |
| 上游流水线完成 | Build after other projects |
needs + trigger 关键字 |
多项目依赖、微服务链式发布 |
3.4 流水线结构示意图
下图展示了一个包含安全扫描与回滚触发的 K8s 发布流水线阶段流程:
3.5 触发条件配置示例
以下展示 GitLab CI/CD 中基于分支与标签的触发配置,以及 Jenkins 中基于 Webhook 的参数化触发:
GitLab CI/CD 触发配置(.gitlab-ci.yml 片段)
stages:
- fetch
- build
- security
- package
- deploy
- verify
variables:
DOCKER_IMAGE: "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
when: always
- when: never
security-scan:
stage: security
script:
- trivy image --severity HIGH,CRITICAL --exit-code 1 ${DOCKER_IMAGE}
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: on_success
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
when: on_success
deploy-k8s:
stage: deploy
script:
- kubectl apply -f k8s/deployment.yaml
environment:
name: production
rules:
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
when: manual
allow_failure: false
Jenkins 声明式 Pipeline 触发配置
pipeline {
agent any
triggers {
// 代码推送触发(需安装 Generic Webhook Trigger 插件)
GenericTrigger(
genericVariables: [
[key: 'REF', value: '$.ref']
],
: 'my-secret-',
causeString: 'Triggered by push to $REF',
printContributedVariables: true,
printPostContent: true
)
// 定时触发:每天凌晨 2 点执行安全扫描
cron('0 2 * * *')
}
stages {
stage('Security Scan') {
when {
expression { return env.BRANCH_NAME == 'main' || env.TAG_NAME =~ /^v\d+\.\d+\.\d+$/ }
}
steps {
sh 'trivy image --severity HIGH,CRITICAL --exit-code 1 ${DOCKER_IMAGE}'
}
}
stage('Deploy to K8s') {
when {
expression { return env.TAG_NAME =~ /^v\d+\.\d+\.\d+$/ }
}
input {
message "确认部署至生产环境?"
ok "确认部署"
}
steps {
sh 'kubectl apply -f k8s/deployment.yaml'
}
}
}
}
实践要点:
- 安全扫描阶段应设置为 阻断性阶段:扫描失败时流水线立即终止,不执行后续部署。
- 生产环境部署建议使用 手动触发(Jenkins 的
input或 GitLab 的when: manual),增加人工审核环节。 - 回滚触发逻辑通常放在健康检查阶段之后,通过条件判断(如
kubectl rollout status返回非零)自动执行kubectl rollout undo。 - 定时触发适合执行全量安全扫描或依赖更新,避免在每次代码提交时重复执行耗时任务。
3.6 阶段划分最佳实践
根据团队规模与发布频率,阶段划分可灵活调整。以下推荐两种常见模式:
| 模式 | 阶段数量 | 特点 | 适用场景 |
|---|---|---|---|
| 精简模式 | 4-5 个 | 编译 → 安全扫描 → 镜像构建 → 部署 → 验证 | 小型团队、快速迭代、低风险项目 |
| 完整模式 | 7-9 个 | 代码检出 → 编译 → 单元测试 → 安全扫描 → 镜像构建 → 集成测试 → 部署 → 健康检查 → 回滚 | 中大型团队、合规要求高、生产环境严格 |
阶段命名规范: 建议使用动词+名词的格式(如
build-app、scan-image、deploy-k8s),便于在流水线可视化界面中快速识别。避免使用模糊名称如 step1、job2。