3. 环境准备篇:CI/CD流水线配置,从代码提交到自动部署的常见断点与修复策略
CI/CD 流水线,说白了就是一条从代码到生产的自动化传送带。很多团队搭完流水线就觉得万事大吉了,结果一跑就卡住。我见过太多案例——开发说“我提交了”,运维说“没部署啊”,最后发现是流水线在某个环节悄悄断了。
这一章,我把常见的断点按阶段拆开讲。每个断点我都踩过,修复策略也是真金白银换来的。
3.1 代码提交阶段的断点
代码提交是流水线的起点。起点断了,后面全是空的。
断点:分支过滤配置错误
很多团队在流水线里写死了分支名,比如只监听 main 分支。结果开发往 release/2.0 推了代码,流水线没反应。我遇到过更离谱的——正则写错了,所有分支都触发了,生产环境被误部署了三次。
断点:Webhook 未生效
GitLab 或 GitHub 的 Webhook 配置了,但流水线就是不触发。原因通常是:
- Webhook URL 写错了(少了个斜杠)
- Secret token 不匹配
- 防火墙拦了出站请求
我曾经排查过一个 Webhook 问题,查了三天才发现是 CI 服务器的 IP 变了,但 GitLab 那边没更新白名单。
3.2 代码检查阶段的断点
代码检查阶段,说白了就是跑 lint、单元测试、安全扫描。这个阶段最容易出问题的是依赖安装。
断点:依赖安装超时
npm install 或 pip install 跑到一半卡住了,流水线超时失败。原因很常见:
- 某个依赖包被删了或下架了
- 网络波动,连不上 registry
- 依赖版本冲突,解析花了太长时间
我个人习惯在流水线里加一个 timeout 参数,比如 npm install 设置 5 分钟超时。超时后自动重试一次,还不行就发告警。
# 示例:GitLab CI 中设置依赖安装超时
install_deps:
script:
- npm ci --prefer-offline
timeout: 5m
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
断点:测试环境与本地不一致
开发本地测试全过,CI 上一跑就挂。为什么?因为 CI 的 Node.js 版本是 18,开发本地是 20。或者 CI 没装某个系统依赖库。
你想想看,这种问题多冤。修复方法就一个:用 Docker 镜像统一环境。CI 里跑的测试环境,必须和开发本地完全一致。
3.3 构建打包阶段的断点
构建阶段,说白了就是把代码编译成可运行的产物。这个阶段最头疼的是缓存问题。
断点:缓存失效导致构建变慢
第一次构建花了 10 分钟,第二次因为缓存还在,只花了 2 分钟。但某天缓存被清了,构建又回到 10 分钟。如果流水线超时设了 5 分钟,那就直接失败了。
我建议的做法是:
- 明确缓存策略:哪些目录可以缓存,哪些不能
- 设置缓存 key 包含依赖锁文件的 hash
- 给构建阶段留足时间余量,别卡着超时线
# 示例:GitLab CI 缓存配置
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .npm/
policy: pull-push
build:
script:
- npm run build
timeout: 15m
断点:资源耗尽
构建时内存爆了,或者磁盘满了。尤其是前端项目,webpack 打包时内存消耗很大。我遇到过 CI Runner 只有 2GB 内存,构建一个大型 React 项目直接 OOM。
--max-old-space-size=2048。
3.4 镜像推送阶段的断点
构建完要推镜像到仓库。这个阶段看似简单,坑却不少。
断点:认证过期
Docker 登录用的 token 或密码过期了,推送失败。我见过一个团队,每次 token 过期都要手动更新,结果周末没人值班,流水线卡了一整天。
修复方法:用短生命周期的 token + 自动刷新机制。或者用 OIDC 集成,让 CI 自动获取临时凭证。
断点:镜像仓库满了
私有镜像仓库没设置清理策略,磁盘满了。新镜像推不上去,部署自然就停了。
我个人习惯在流水线里加一个步骤:推送前检查仓库剩余空间,低于阈值就触发清理任务。
3.5 部署发布阶段的断点
部署阶段是流水线的最后一公里。这里出问题,前面的努力全白费。
断点:K8s 资源冲突
部署时提示 AlreadyExists 或 Conflict。原因通常是:
- 同一个命名空间下有同名资源
- 之前的部署没清理干净
- 多个流水线同时部署同一个应用
修复策略:用 kubectl apply 而不是 kubectl create。apply 是声明式的,不会因为资源已存在而报错。
断点:健康检查不通过
Pod 启动起来了,但 readiness probe 一直失败。流水线等了几分钟,超时回滚。
为什么会这样?最常见的原因是:
- 应用启动慢,但 probe 的 initialDelaySeconds 设得太短
- 依赖的服务(比如数据库)还没就绪
- 配置项写错了,应用启动后报错
3.6 流水线修复的通用策略
上面讲了各个阶段的断点,这里总结几个通用的修复策略。
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 重试机制 | 对偶发失败自动重试 1-2 次 | 网络波动、依赖安装超时 |
| 超时控制 | 每个阶段设置合理超时时间 | 构建卡住、测试死循环 |
| 幂等性 | 重复执行流水线结果一致 | 部署、镜像推送 |
| 可观测性 | 每个阶段输出日志和指标 | 排查失败原因 |
| 回滚能力 | 失败时自动回滚到上一版本 | 部署失败、健康检查不通过 |
嗯,这里要注意一点:重试不是万能的。如果同一个任务重试了 3 次还失败,就别再重试了。发告警,让人介入。否则只会浪费资源和时间。