一、手动发布的代价:一次"小改小上线"要 40 分钟
小陈向老周演示一次"普通发布":
云间书店的"手动发布"流程:
① 开发改代码 → 本地测试
② 手动 docker build → 构建镜像(几分钟)
③ 手动 docker push → 推到 Harbor(几分钟)
④ SSH 登录生产服务器 → 敲 kubectl set image(几分钟)
⑤ 盯着滚动更新 → 直到全部 Pod 替换完
⑥ 手动验证 → curl 健康检查
一次发布 ≈ 40 分钟,全是手工活,而且:
- 人容易忘步骤(少 push 一次?)
- 人容易敲错命令(镜像版本号手滑?)
- 没人记录"这次发的是什么"
- 半夜发布?睡意朦胧更容易错
"40 分钟不长,但每周发 3 次,一年下来就是 100 小时的手工活,还带着出错风险。"老周说,"容器时代的答案:CI/CD——让流水线替人干这些活。"
二、什么是 CI/CD:从提交到上线的"自动流水线"
老周画了一条流水线:
CI/CD 流水线(Pipeline):
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ 提交 │ → │ 自动 │ → │ 自动 │ → │ 自动 │ → │ 自动 │
│ 代码 │ │ 测试 │ │ 构建 │ │ 推送 │ │ 部署 │
└──────┘ └──────┘ └──────┘ └──────┘ └──────┘
git push pytest docker docker kubectl
(单元测试) build push apply
CI(持续集成 Continuous Integration):
每次提交代码 → 自动测试 + 自动构建镜像
(代码提交即验证,坏代码当场报警)
CD(持续交付/部署 Continuous Delivery/Deployment):
构建好的镜像 → 自动推到仓库 → 自动部署到环境
(发布从"手动操作"变成"流水线自动跑")
"CI/CD 的意义:把'人肉发布'变成'流水线发布'——提交代码之后,剩下的事机器全包了。 人只负责写代码和看结果。"
三、GitLab CI 实战:云间书店的第一条流水线
老周选用了 GitLab CI(和云间书店用的 Git 仓库配套):
# .gitlab-ci.yml —— 云间书店 API 服务的流水线
stages: # 定义阶段(按顺序执行)
- test # 1. 测试
- build # 2. 构建镜像
- deploy # 3. 部署
# 阶段1:测试
test:
stage: test
image: python:3.11-slim
script:
- pip install -r requirements.txt
- pytest tests/ -q # 跑单元测试
# 阶段2:构建并推送镜像
build:
stage: build
image: docker:24
services:
- docker:dind
script:
- docker build -t harbor.yunjian.com/library/api:$CI_COMMIT_TAG .
- docker login harbor.yunjian.com -u $REGISTRY_USER -p $REGISTRY_PASS
- docker push harbor.yunjian.com/library/api:$CI_COMMIT_TAG
# 阶段3:部署到 K8s
deploy:
stage: deploy
image: bitnami/kubectl
script:
- kubectl set image deploy/api-deploy api=harbor.yunjian.com/library/api:$CI_COMMIT_TAG
environment: production
only:
- tags # 只有打 tag(发版)才部署生产
流水线怎么跑:
开发打 tag(如 v1.4.0)→ GitLab 自动触发流水线
→ 测试阶段:跑全部单元测试(挂了?流水线红,不部署)
→ 构建阶段:build 镜像 + push 到 Harbor
→ 部署阶段:kubectl 滚动更新生产
→ 全部绿:上线完成!开发者只做了一件事:打 tag
安全(凭据管理):
$REGISTRY_USER / $REGISTRY_PASS 存在 GitLab 的 CI 变量里
→ 不写死在代码里(还记得第七章 .env 的教训吗)
"注意 only: tags——生产部署只在'打 tag'时触发。 这就是版本管理和自动化的结合:发版 = 打个 tag,其余全自动。"
四、多环境流水线:测试→预发布→生产
"光有生产流水线不够,要'分环境'部署。"老周画:
多环境流水线(环境即关卡):
提交代码(feature 分支)
│
▼
开发环境(自动部署,天天变) ← 开发者自测
│ 合并到 develop 分支
▼
测试环境(自动部署) ← 测试同学验收
│ 打 tag v1.4.0
▼
预发布环境(自动部署,跑冒烟测试) ← 上线前最后把关
│ 人工确认
▼
生产环境(自动部署,滚动更新) ← 正式上线
环境管理原则:
每个环境有自己的 K8s Namespace(命名空间):
dev / test / staging / prod
配置用 ConfigMap/Secret 区分环境(不同数据库地址等)
生产环境:人工确认这一步不能省(guard 保护)
好处:代码改动层层验证,坏代码到不了生产
"多环境 = 多道关卡:代码每通过一关,离用户近一步,出错风险降一截。 生产发布前那一脚'人工确认',是留给人的最后一道闸门——机器跑得再快,也要有人踩刹车。"
五、容器化 CI/CD 的三大收益
老周总结容器化交付带来的改变:
① 快:发布从 40 分钟 → 10 分钟(全程自动)
频率从每周 3 次 → 每天数次(想发就发)
② 稳:每次发布流程一模一样(机器不会手滑)
坏代码在测试阶段就被拦住(不会带病上线)
③ 可回溯:每次发布都有记录(谁、什么版本、什么时候)
回滚 = 一句话(kubectl rollout undo)
云间书店发布方式进化:
阶段1(VMware 季):人肉部署,一次 2 小时
阶段2(手动容器):docker 命令部署,40 分钟
阶段3(CI/CD) :打 tag 全自动,10 分钟
→ 发布终于成了"日常小事"而不是"大工程"
"容器 + CI/CD 是绝配:镜像让'构建产物'标准化(走到哪都一样),流水线让'发布过程'自动化(不用人盯着)。 这就是云原生交付的核心。"
六、章末:老周的第十层总结
第十层:CI/CD 容器化交付
├── CI(持续集成):提交→自动测试→自动构建镜像
├── CD(持续交付):镜像→自动推送→自动部署
├── 流水线:test → build → deploy(GitLab CI 等)
├── 凭据管理:密码存 CI 变量,不写死在代码
├── 多环境:dev → test → staging → prod(层层把关)
└── 收益:发布 40 分钟→10 分钟,稳定、可回溯、可回滚
"小陈,你的流水线跑起来了:代码提交 → 自动测试 → 自动构建 → 自动部署到 K8s。这套东西,就是业界常说的'云原生'的骨架。"
"但是——"老周话锋一转,"容器和自动化的世界跑得越快,安全问题就越致命。一个镜像漏洞,可能顺着流水线直接进生产;一个配置错误,可能把数据库端口暴露到公网。容器时代的安全,比传统时代更需要'主动防护'。 下一章,我们讲容器安全的实战,以及容器技术未来的方向——云原生生态。"