流水线设计与部署策略
流水线设计原则
标准流水线阶段
设计原则
| 原则 | 说明 |
|---|---|
| 快速反馈 | Lint 和单元测试放在最前面,5 分钟内给出结果 |
| 并行执行 | 无依赖的 Job 并行运行(lint ∥ test ∥ security scan) |
| 缓存复用 | 依赖缓存(node_modules、.m2)、Docker 层缓存 |
| 制品不可变 | 构建一次镜像,在 staging → production 之间只改配置 |
| 环境一致 | 所有环境使用相同的 Docker 镜像和 Helm Chart |
| 门禁机制 | PR 必须通过 CI 才能合并,生产部署需要审批 |
PR 门禁示例
GitHub Actions PR 门禁
on:
pull_request:
branches: [main]
jobs:
gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pnpm install --frozen-lockfile
- run: pnpm lint # 代码规范
- run: pnpm type-check # 类型检查
- run: pnpm test -- --coverage # 测试覆盖率
- run: pnpm build # 构建验证
# 覆盖率门禁
- uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true
部署策略详解
滚动更新(Rolling Update)
K8s 默认策略,逐步替换旧 Pod。
Deployment 滚动更新
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多多 1 个 Pod
maxUnavailable: 1 # 最多少 1 个 Pod
优点:资源开销小,K8s 原生支持。 缺点:新旧版本共存期间可能有兼容性问题。
蓝绿部署(Blue-Green)
同时运行两套完整环境,通过 Service 切换流量。
蓝绿部署 - Service 切流量
# Blue(当前线上)
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-blue
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: blue
---
# Green(新版本)
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-green
spec:
replicas: 3
selector:
matchLabels:
app: myapp
version: green
---
# Service 指向 Blue → 切换到 Green
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
spec:
selector:
app: myapp
version: blue # 切换时改为 green
# 切换流量:将 Service 指向 Green
kubectl patch svc myapp-svc -p '{"spec":{"selector":{"version":"green"}}}'
# 回滚:切回 Blue
kubectl patch svc myapp-svc -p '{"spec":{"selector":{"version":"blue"}}}'
优点:回滚极快(切换 Service),无新旧版本共存。 缺点:需要双倍资源。
金丝雀发布(Canary)
先将少量流量导到新版本,观察无异常后逐步扩大。
基于 Nginx Ingress 的金丝雀
# 主 Ingress(v1,100% 流量)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-main
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-v1
port:
number: 80
---
# Canary Ingress(v2,5% 流量)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "5" # 5% 流量
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-v2
port:
number: 80
渐进式交付工具
手动管理金丝雀很繁琐,推荐使用自动化工具:
- Argo Rollouts:K8s 原生的渐进式交付控制器
- Flagger:配合 Istio/Nginx 自动金丝雀发布
- Istio:通过 VirtualService 精确控制流量分配
策略选型
| 场景 | 推荐策略 |
|---|---|
| 日常发布,容忍短暂新旧共存 | 滚动更新 |
| 数据库迁移等需要原子切换 | 蓝绿部署 |
| 核心服务,需要灰度验证 | 金丝雀发布 |
| 需要按用户分流对比 | A/B 测试(需要 Istio) |
多环境管理
| 环境 | 用途 | 部署方式 | 数据 |
|---|---|---|---|
| Dev | 开发自测 | 自动(push 触发) | Mock 数据 |
| Staging | 预发布验证 | 自动(main 分支) | 脱敏数据 |
| Production | 用户访问 | 手动审批 | 真实数据 |
| Review | MR 预览 | 自动(MR 触发) | Mock 数据 |
常见面试问题
Q1: 蓝绿部署和金丝雀发布的区别?
答案:
| 维度 | 蓝绿部署 | 金丝雀发布 |
|---|---|---|
| 流量切换 | 一次性 100% 切换 | 逐步从 5% → 100% |
| 新旧共存 | 不共存(原子切换) | 共存(观察期) |
| 资源 | 需要双倍资源 | 只需少量额外资源 |
| 回滚 | 极快(切回旧版本) | 快(关闭金丝雀) |
| 风险 | 切换时全量影响 | 风险可控(只影响小流量) |
| 适用 | 需要原子发布 | 需要灰度验证 |
Q2: 如何设计一条生产级 CI/CD 流水线?
答案:
- PR 阶段:Lint → 单元测试 → 构建验证 → 安全扫描(SAST)
- 合并 main:构建 Docker 镜像 → 推送 Registry → 自动部署 Staging
- Staging:集成测试 → 冒烟测试 → 性能测试
- Production:手动审批 → 金丝雀发布(5% → 25% → 100%) → 自动回滚(错误率增高时)
关键原则:制品不可变、快速反馈、门禁机制、自动回滚。
Q3: CI 流水线太慢怎么优化?
答案:
- 缓存:依赖缓存(node_modules / .m2)、Docker 层缓存
- 并行:lint / test / security-scan 并行执行
- 增量:路径过滤(只测试变更的模块)、增量构建
- 资源:self-hosted runner 提升性能,K8s Agent 弹性伸缩
- 精简镜像:多阶段构建减小镜像体积,加速推送