第 13 章:CI/CD 流水线
第 13 章:CI/CD 流水线
微服务的核心优势之一是独立部署。没有自动化的 CI/CD,这个优势就无法发挥。
13.1 微服务 CI/CD 的特殊性
13.1.1 单体 vs 微服务 CI/CD
单体 CI/CD:
┌─────────────────────────────────────────────┐
│ 单体代码仓库 │
│ │
│ 代码变更 ──▶ 构建(慢) ──▶ 测试(全量) ──▶ 部署│
│ │
│ 问题: │
│ • 一个功能变更,需要构建整个应用 │
│ • 回归测试范围大 │
│ • 部署影响所有人 │
└─────────────────────────────────────────────┘
微服务 CI/CD:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 服务 A │ │ 服务 B │ │ 服务 C │
│ 独立仓库 │ │ 独立仓库 │ │ 独立仓库 │
│ 独立流水线│ │ 独立流水线│ │ 独立流水线│
│ 独立部署 │ │ 独立部署 │ │ 独立部署 │
└──────────┘ └──────────┘ └──────────┘
优势:
• 只构建变更的服务
• 只跑该服务的测试
• 独立发布,不影响其他服务
13.1.2 微服务 CI/CD 基本要求
| 要求 | 说明 |
|---|
| 每个服务独立流水线 | 代码变更只触发对应服务的流水线 |
| 自动化一切 | 构建、测试、部署全部自动化 |
| 容器化交付 | 统一交付物:Docker 镜像 |
| 版本化管理 | 语义化版本号(SemVer) |
| 环境一致性 | Dev/Staging/Prod 环境一致 |
| 快速反馈 | 流水线 < 15 分钟完成 |
13.2 CI/CD 流水线设计
13.2.1 标准流水线
┌──────────────────────────────────────────────────────────────────┐
│ 微服务 CI/CD 流水线 │
├──────────────────────────────────────────────────────────────────┤
│ │
│ CI 阶段 (Continuous Integration) │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ 代码 │─▶│ 构建 │─▶│ 单元 │─▶│ 契约 │─▶│ 镜像 │ │
│ │ 提交 │ │ 编译 │ │ 测试 │ │ 测试 │ │ 构建 │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │
│ ~0s ~30s ~60s ~30s ~60s │
│ │
│ CD 阶段 (Continuous Delivery/Deployment) │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ 镜像 │─▶│ 部署 │─▶│ 集成 │─▶│ 部署 │─▶│ 部署 │ │
│ │ 推送 │ │ Dev │ │ 测试 │ │ Staging│ │ Prod │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │
│ ~20s ~30s ~120s ~30s ~60s(灰度) │
│ │
│ 总时间:< 10 分钟 │
└──────────────────────────────────────────────────────────────────┘
13.2.2 GitHub Actions 示例
# .github/workflows/order-service.yml
name: Order Service CI/CD
on:
push:
branches: [main]
paths:
- 'order-service/**' # 只在该服务代码变更时触发
pull_request:
branches: [main]
paths:
- 'order-service/**'
env:
REGISTRY: ghcr.io
IMAGE_NAME: order-service
jobs:
# ========== CI 阶段 ==========
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Build and Test
run: |
cd order-service
./mvnw clean verify
- name: Contract Tests
run: |
cd order-service
./mvnw pact:verify
- name: Build Docker Image
run: |
cd order-service
docker build -t $REGISTRY/$IMAGE_NAME:${{ github.sha }} .
- name: Push Docker Image
if: github.ref == 'refs/heads/main'
run: |
echo ${{ secrets.GITHUB_TOKEN }} | docker login $REGISTRY -u ${{ github.actor }} --password-stdin
docker push $REGISTRY/$IMAGE_NAME:${{ github.sha }}
docker tag $REGISTRY/$IMAGE_NAME:${{ github.sha }} $REGISTRY/$IMAGE_NAME:latest
docker push $REGISTRY/$IMAGE_NAME:latest
# ========== CD 阶段 ==========
deploy-dev:
needs: build-and-test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to Dev
run: |
kubectl set image deployment/order-service \
order-service=$REGISTRY/$IMAGE_NAME:${{ github.sha }} \
-n dev
integration-test:
needs: deploy-dev
runs-on: ubuntu-latest
steps:
- name: Run Integration Tests
run: |
cd order-service
./mvnw verify -Pintegration-test \
-Dtest.base-url=http://dev.example.com
deploy-staging:
needs: integration-test
runs-on: ubuntu-latest
steps:
- name: Deploy to Staging
run: |
kubectl set image deployment/order-service \
order-service=$REGISTRY/$IMAGE_NAME:${{ github.sha }} \
-n staging
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production # 需要手动审批
steps:
- name: Deploy to Production (Canary)
run: |
# 金丝雀部署:先部署 10% 流量
kubectl apply -f k8s/canary-deployment.yaml
13.3 部署策略
13.3.1 策略总览
| 策略 | 停机时间 | 风险 | 资源需求 | 回滚速度 |
|---|
| 滚动更新 | 零 | 低 | 低 | 中 |
| 蓝绿部署 | 零 | 低 | 2 倍 | 极快 |
| 金丝雀发布 | 零 | 极低 | 少量额外 | 快 |
| A/B 测试 | 零 | 低 | 少量额外 | 快 |
| 重建部署 | 有 | 高 | 低 | 慢 |
13.3.2 滚动更新(Rolling Update)
滚动更新过程(ReplicaSet = 4):
时间 ──────────────────────────────────────▶
Step 1: [v1] [v1] [v1] [v1] (全部 v1)
Step 2: [v1] [v1] [v1] [v2-new] (启动 1 个 v2)
Step 3: [v1] [v1] [v2] [v2-new] (v2 就绪,终止 1 个 v1)
Step 4: [v1] [v2] [v2] [v2-new] (继续滚动)
Step 5: [v2] [v2] [v2] [v2] (全部 v2)
K8s 配置:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多多出 1 个 Pod
maxUnavailable: 0 # 不允许不可用
13.3.3 蓝绿部署(Blue-Green Deployment)
蓝绿部署:
┌─────────────────────────────────────────────────┐
│ │
│ 负载均衡器 / Ingress │
│ ┌─────────────────────────────────┐ │
│ │ 路由规则 │ │
│ └──────────┬──────────────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 蓝环境 │ │ 绿环境 │ │
│ │ (v1) │ │ (v2) │ │
│ │ [v1][v1] │ │ [v2][v2] │ │
│ │ [v1][v1] │ │ [v2][v2] │ │
│ └──────────┘ └──────────┘ │
│ 当前活跃 ✅ 待验证 │
│ │
│ 切换流量(瞬间完成): │
│ 蓝 (v1) ──▶ 不活跃 绿 (v2) ──▶ 活跃 ✅ │
│ │
│ 回滚(瞬间完成): │
│ 蓝 (v1) ──▶ 活跃 ✅ 绿 (v2) ──▶ 不活跃 │
└─────────────────────────────────────────────────┘
13.3.4 金丝雀发布(Canary Deployment)
金丝雀发布过程:
阶段1:10% 流量到新版本
─────────────────────────────
用户流量 ──▶ [Ingress]
├── 90% ──▶ [v1] [v1] [v1] [v1] [v1]
└── 10% ──▶ [v2]
阶段2:验证无异常,增加到 30%
─────────────────────────────
用户流量 ──▶ [Ingress]
├── 70% ──▶ [v1] [v1] [v1]
└── 30% ──▶ [v2] [v2]
阶段3:验证无异常,增加到 100%
─────────────────────────────
用户流量 ──▶ [Ingress]
└── 100% ──▶ [v2] [v2] [v2] [v2] [v2]
自动回滚条件(任一触发):
• 错误率 > 5%
• P99 延迟 > 1s
• 5xx 错误数突增
13.3.5 Argo Rollouts 金丝雀配置
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: order-service
spec:
replicas: 5
strategy:
canary:
steps:
- setWeight: 10 # 10% 流量
- pause: {duration: 5m} # 观察 5 分钟
- setWeight: 30 # 30% 流量
- pause: {duration: 5m} # 观察 5 分钟
- setWeight: 60 # 60% 流量
- pause: {duration: 5m} # 观察 5 分钟
- setWeight: 100 # 全量
analysis:
templates:
- templateName: success-rate
startingStep: 1
args:
- name: service-name
value: order-service
---
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 1m
successCondition: result[0] >= 0.99
failureLimit: 3
provider:
prometheus:
address: http://prometheus:9090
query: |
sum(rate(http_requests_total{service="{{args.service-name}}",status=~"2.."}[5m]))
/
sum(rate(http_requests_total{service="{{args.service-name}}"}[5m]))
13.4 GitOps
13.4.1 GitOps 原则
┌──────────────────────────────────────────────────────────────┐
│ GitOps 工作流 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 开发者 Git 仓库 K8s 集群 │
│ ┌──────┐ ┌──────────┐ ┌─────────┐ │
│ │ │ push code │ │ 同步 │ │ │
│ │ 代码 │───────────────▶│ 应用代码 │ │ │ │
│ │ 变更 │ │ │ │ │ │
│ └──────┘ └────┬─────┘ │ │ │
│ │ CI │ │ │
│ ▼ │ │ │
│ ┌──────────┐ │ │ │
│ │ 构建镜像 │ │ │ │
│ │ 更新配置 │ │ │ │
│ └────┬─────┘ │ │ │
│ │ │ │ │
│ ▼ │ │ │
│ ┌──────────┐ │ │ │
│ │ 配置仓库 │◄─────────│ ArgoCD │ │
│ │ (K8s YAML)│ 监听 │ │ │
│ │ │─────────▶│ 部署 │ │
│ └──────────┘ └─────────┘ │
│ │
│ 核心原则: │
│ 1. Git 是唯一事实来源 │
│ 2. 声明式配置(K8s YAML / Helm) │
│ 3. 自动同步(ArgoCD / Flux 监听变更) │
│ 4. 可审计(Git 提交历史就是变更历史) │
│ 5. 可回滚(Git revert 就是回滚) │
└──────────────────────────────────────────────────────────────┘
13.4.2 ArgoCD 配置
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: order-service
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/k8s-configs.git
targetRevision: HEAD
path: production/order-service
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # 自动删除不存在的资源
selfHeal: true # 自动修复手动修改
syncOptions:
- CreateNamespace=true
13.5 多仓库管理
13.5.1 单仓库 vs 多仓库
| 维度 | 单仓库 (Monorepo) | 多仓库 (Polyrepo) |
|---|
| 代码共享 | 容易 | 需要包管理 |
| CI 配置 | 需要路径过滤 | 独立流水线 |
| 权限控制 | 粗粒度 | 细粒度 |
| 依赖管理 | 简单 | 需要版本管理 |
| 推荐场景 | 初期/小团队 | 成熟/大团队 |
13.5.2 多仓库的版本管理
服务间版本兼容性矩阵:
订单服务版本 商品服务版本 是否兼容
───────────── ───────────── ────────
v2.1.0 v3.2.0 ✅
v2.1.0 v3.3.0 ✅
v2.1.0 v4.0.0 ❌ (API 不兼容)
v2.2.0 v3.2.0 ✅
管理方式:
1. 契约测试保证兼容性
2. API 版本号管理(v1/v2 共存)
3. 语义化版本号(SemVer)
13.6 业务场景:电商 CI/CD 全景
┌──────────────────────────────────────────────────────────────┐
│ 电商 CI/CD 全景架构 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 代码层 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │用户服务 │ │订单服务 │ │商品服务 │ │支付服务 │ │
│ │ Git Repo │ │ Git Repo │ │ Git Repo │ │ Git Repo │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ └─────────────┼─────────────┼─────────────┘ │
│ ▼ │
│ CI 层 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ GitHub Actions / GitLab CI │ │
│ │ • 构建 → 测试 → 镜像 → 推送 │ │
│ │ • 每个服务独立流水线 │ │
│ └───────────────────────┬──────────────────────────────┘ │
│ ▼ │
│ CD 层 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ ArgoCD (GitOps) │ │
│ │ • 监听配置仓库变更 │ │
│ │ • 自动同步到 K8s │ │
│ │ • 支持蓝绿/金丝雀 │ │
│ └───────────────────────┬──────────────────────────────┘ │
│ ▼ │
│ 运行层 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Kubernetes 集群 │ │
│ │ • Dev → Staging → Production │ │
│ │ • Argo Rollouts (金丝雀) │ │
│ │ • Prometheus + Grafana (监控) │ │
│ └──────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
⚠️ 注意事项
- 流水线速度——CI 流水线超过 15 分钟会严重影响开发效率
- 数据库迁移——Schema 变更需要与代码部署协调
- 配置管理——敏感信息使用 Secret 管理,不要提交到 Git
- 回滚策略——每次部署都要有回滚方案
- 环境一致性——Dev/Staging/Prod 使用相同的 K8s 配置
📖 扩展阅读
- ArgoCD Documentation (argoproj.github.io) — GitOps 持续部署
- Argo Rollouts — 渐进式交付
- Flux CD — CNCF GitOps 工具
- GitHub Actions Documentation — CI/CD 自动化
- Continuous Delivery — Jez Humble — 持续交付经典著作
本章小结
| 部署策略 | 停机 | 风险 | 适用场景 |
|---|
| 滚动更新 | 零 | 低 | 常规更新 |
| 蓝绿部署 | 零 | 低 | 需要快速回滚 |
| 金丝雀发布 | 零 | 极低 | 高风险变更 |
| GitOps | — | — | 配置管理最佳实践 |
📌 下一章:第 14 章:安全架构 — 零信任、mTLS、JWT、OAuth2。