环境搭建:CI 服务器(Jenkins / GitLab CI)配置
这一章,我们聊聊 CI 服务器的配置。说白了,就是给回滚分层找个“跑道”。你想想,如果没有一个稳定、清晰的 CI 环境,后面那些分层策略根本跑不起来。我个人习惯把 CI 服务器当成整个回滚体系的“调度中心”——它不光要跑构建、跑测试,还得能快速生成可回滚的版本。
我先说说 Jenkins,再说 GitLab CI。这两种我都用过,各有千秋。Jenkins 我用了快八年,GitLab CI 最近三年才开始深度接触。说实话,如果你团队小、代码托管已经用了 GitLab,那直接上 GitLab CI 最省事;但如果你们要搞复杂的流程编排,Jenkins 的 Pipeline 依然是老大哥。
4.1 Jenkins 配置要点
上一家公司,我接手过一套 Jenkins 集群。那个项目有十几个微服务,回滚要求特别高。我记得一开始大家配置的方式特别“野”——每个人在 Jenkins 上手动点构建,参数乱填,经常出现构建产物对不上版本。后来我推了一套标准化配置,才算稳下来。
关键配置项有这几个:
- Pipeline 脚本(Jenkinsfile):必须包含回滚阶段的钩子。我习惯在 post 块里加一个
rollback条件。 - 参数化构建:
CHOICE参数选择回滚到的版本号,STRING参数指定环境。 - 凭据管理:把 Docker Registry、K8s 的 kubeconfig 都放进 Jenkins 的 Credential Store,别写死。
- Agent 标签:按业务分组,比如
java-build、k8s-deploy,避免资源争抢。
一个典型的 Jenkinsfile 片段:
pipeline {
agent { label 'k8s-deploy' }
parameters {
choice(name: 'ROLLBACK_VERSION', choices: ['v1.0.0', 'v1.1.0', 'v1.2.0'], description: '回滚到的版本')
string(name: 'TARGET_ENV', defaultValue: 'staging', description: '目标环境')
}
stages {
stage('Build') {
steps {
sh 'docker build -t myapp:${ROLLBACK_VERSION} .'
}
}
stage('Deploy') {
steps {
sh 'kubectl set image deployment/myapp myapp=myapp:${ROLLBACK_VERSION} -n ${TARGET_ENV}'
}
}
}
post {
success {
emailext subject: "部署成功: ${ROLLBACK_VERSION} to ${TARGET_ENV}"
}
failure {
// 自动触发回滚机制
}
}
}
小技巧: Jenkins 的 Job 建议用 Multibranch Pipeline,这样每个分支自动扫描,省去手动建 Job。我在实战中发现,只要分支名规范(比如 release/v* 打回滚基线),扫描策略就设成“定期 + webhook”,效率很高。
4.2 GitLab CI 配置要点
GitLab CI 的配置核心是 .gitlab-ci.yml。这个文件必须放在仓库根目录,而且 CI/CD 变量的管理比 Jenkins 更整洁。我个人特别喜欢它的“环境”管理和“手动操作”按钮——用在回滚场景太合适了。
比如,你想让某个 job 只在手动触发时才执行,那就加 when: manual。结合 environment 里的 action: rollback,完美。
示例配置:
stages:
- build
- test
- deploy
- rollback
variables:
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
build:
stage: build
script:
- docker build -t $DOCKER_IMAGE .
- docker push $DOCKER_IMAGE
only:
- tags
rollback:
stage: rollback
environment:
name: production
action: rollback
script:
- kubectl set image deployment/myapp myapp=$DOCKER_IMAGE
when: manual
only:
- tags
这里有个坑:回滚 job 必须和原始部署 job 共享同一个 environment 名称,否则 GitLab 的环境页面不会关联历史。我以前踩过这个坑,回滚后环境页面上显示两行记录,运维同事以为出了问题,紧张了半天。
警告: GitLab CI 的 Runner 如果串行执行,回滚 job 可能被其他 job 阻塞。建议给回滚专用 Runner 打标签 rollback,并在 runner 配置里设置 concurrent = 1 + check_interval = 0,保证回滚操作独占资源。
4.3 两种 CI 的对比选型
你可能会问:“那我究竟选 Jenkins 还是 GitLab CI?” 没有答案,我列个表帮你决策:
| 维度 | Jenkins | GitLab CI |
|---|---|---|
| 配置方式 | Jenkinsfile(Groovy) | .gitlab-ci.yml(YAML) |
| 学习成本 | 中高(Pipeline 语法复杂) | 低(YAML 直观) |
| 回滚支持 | 需手动写条件 / 插件 | 原生 environment + manual |
| Agent 扩展 | 灵活,可动态扩展 | 依赖 GitLab Runner |
| UI 友好度 | 传统,稍显笨重 | 简洁,环境追踪清晰 |
| 多分支管理 | Multibranch Pipeline | 原生分支管道 |
我个人建议:如果你的 CI 链条需要大量插件(比如 SonarQube、OWASP)、或者要跟团队外的系统集成,Jenkins 更稳;如果你们团队小、链路轻,GitLab CI 完全够用。 我自己现在的项目就是用 GitLab CI + Helm,回滚一条命令搞定。
4.4 CI 服务器配置的核心流程
无论你选哪种,CI 服务器的配置逻辑都跑不出下面这个图。这个我画了很多遍——毕竟要讲给团队新人听,得让他们一图看懂。
这张图里,每到一个环节,你都要问自己:“如果这一步失败了,回滚怎么做?” 比如制品归档这一步,我经历过一次因为镜像标签覆盖导致的回滚失败——之前我图省事用了 latest,结果回滚时拿到的镜像根本不是之前上线的版本。从那以后,我强制要求每次构建必须打明确的版本标签(比如 v1.2.3-build20250314)。
4.5 回滚场景下的特殊配置
不论用 Jenkins 还是 GitLab CI,有几点是共通的,我单独拿出来强调:
- 构建产物保留策略:Jenkins 里设置
buildDiscarder保留最近 10 个构建产物;GitLab CI 用artifacts:expire_in设为1 week,但回滚专用的 tag 构建产物设为never。 - 环境变量管理:敏感信息(K8s 的 、DB 密码)一定走 CI 的 secret 变量。Jenkins 用 Credential Binding 插件,GitLab 直接走 CI/CD Settings > Variables。
- 测试阶段的回滚拦截:如果单元测试通过率低于阈值,自动阻断流水线。我在 Jenkins Pipeline 里加过
junit分析,失败率 > 1% 直接error。GitLab 可以用allow_failure: false+coverage规则。 - 回滚操作的可观测性:每个回滚操作都要记录到日志系统(Elasticsearch 或者 Datadog),包括谁发起的、哪个版本、执行结果。Jenkins 可以配合
post块发送 JSON 到 webhook;GitLab CI 可以直接调 API 写日志。
我曾经踩过的一个坑: 有次 GitLab CI 配置里忘了给回滚 job 加 resource_group,结果同时触发了两次回滚操作,导致 K8s 端出现资源竞争,Pod 状态变成 CrashLoopBackOff。后来我在每个 job 里加了 resource_group: production_rollback,保证同一时间只有一个回滚 job 在跑。
配置 CI 服务器这件事,看着简单,但每一个细节都可能影响回滚的成败。我的建议是:先跑通最简单的“构建->部署->回滚”链路,然后再逐步添加测试、通知、安全扫描这些层。别一上来就搞大而全,容易翻车。