Skip to content

11 - 发布上线完整流程

一、发布流程全景

开发者日常工作                         发布流水线                              生产环境
───────────────                     ────────────                           ──────────

 feature 分支开发


 本地测试通过


 提交 PR → main          ┌──────────────────────────────────────┐
      │                   │            CI Pipeline               │
      ▼                   │                                      │
 Code Review              │  ① Lint (ruff/mypy/eslint)           │
      │                   │  ② Unit Test (pytest/jest)            │
      ▼                   │  ③ Integration Test                   │
 PR 合并到 main ─────────►│  ④ Docker Build (多阶段构建)           │
                          │  ⑤ Security Scan (Trivy)             │
                          │  ⑥ Push Image → ACR                  │
                          │  ⑦ 自动更新 Manifests Repo (staging)  │
                          └──────────────┬───────────────────────┘

                          ┌──────────────▼───────────────────────┐
                          │            CD Pipeline               │
                          │                                      │
                          │  ⑧ ArgoCD 检测到 Git 变更             │
                          │  ⑨ 自动同步 → Staging                 │
                          │  ⑩ Staging 验证                       │
                          │  ⑪ 提 PR 更新 Production overlay      │
                          │  ⑫ Tech Lead 审批 + Merge            │
                          │  ⑬ ArgoCD Sync → Production           │
                          │  ⑭ 灰度发布                           │────► 生产环境
                          │  ⑮ 监控观察 → 全量发布                  │
                          └──────────────────────────────────────┘

二、Dockerfile 在研发流程中的位置

Dockerfile 是什么阶段写的?

Dockerfile 在开发阶段编写,跟随业务代码一起维护在同一个代码仓库中。

开发阶段写 Dockerfile
─────────────────────

  项目仓库结构(每个服务一个 Dockerfile)
  ├── robotics-api/
  │   ├── src/              ← 业务代码
  │   ├── tests/            ← 测试代码
  │   ├── requirements.txt  ← Python 依赖
  │   ├── Dockerfile        ← 👈 开发者编写,跟代码一起提交
  │   └── .github/workflows/ci.yml

  ├── robotics-training/
  │   ├── src/
  │   ├── configs/
  │   ├── Dockerfile        ← 👈 训练镜像的 Dockerfile
  │   └── .github/workflows/ci.yml

  └── robotics-llm-server/
      ├── src/
      ├── Dockerfile        ← 👈 LLM 推理镜像的 Dockerfile
      └── .github/workflows/ci.yml

不同镜像的 Dockerfile 编写职责

镜像类型谁写什么时候写变更频率存放位置
基础镜像 (cuda-base, pytorch-base)DevOps/SRE项目初期搭建低(季度级)独立仓库 robotics-base/
训练镜像 (vision-train)算法工程师开发训练代码时中(周级)robotics-training/Dockerfile
API 服务镜像 (api-gateway)后端工程师开发 API 时中(周级)robotics-api/Dockerfile
LLM 推理镜像 (llm-server)算法 + 后端模型上线时robotics-llm-server/Dockerfile
前端镜像 (admin-web)前端工程师开发 Web 时robotics-admin-web/Dockerfile
工具镜像 (data-pipeline)数据工程师开发数据管道时robotics-data-pipeline/Dockerfile

Dockerfile 的生命周期

阶段 1: 开发编写
──────────────
  开发者在本地编写 Dockerfile

      ├── 基于基础镜像 (FROM robotics-base/pytorch-base:2.2.0)
      ├── 安装项目依赖 (COPY requirements.txt + pip install)
      ├── 复制业务代码 (COPY src/ /app/src/)
      ├── 配置启动命令 (CMD / ENTRYPOINT)
      └── 本地测试: docker build -t myapp:dev . && docker run myapp:dev

阶段 2: 代码审查
──────────────
  Dockerfile 随代码一起提交 PR

      ├── Reviewer 检查: 基础镜像版本、层缓存优化、安全性
      ├── 确认多阶段构建(减小镜像体积)
      └── 确认没有硬编码 Secret

阶段 3: CI 自动构建
───────────────
  PR 合并到 main → GitHub Actions 自动执行

      ├── docker build(用 Dockerfile 构建镜像)
      ├── Trivy 安全扫描
      ├── docker push → ACR(推送到镜像仓库)
      └── 生成镜像 tag: 20260315-abc1234

阶段 4: CD 部署
──────────────
  CI 更新 K8s manifests repo 中的 image tag

      └── ArgoCD 检测到变更 → 将新镜像部署到集群

典型 Dockerfile 示例

API 服务(Python,多阶段构建)

dockerfile
# ===== 构建阶段 =====
FROM python:3.11-slim AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

# ===== 运行阶段 =====
FROM python:3.11-slim
WORKDIR /app

COPY --from=builder /install /usr/local
COPY src/ ./src/

RUN useradd -r -s /bin/false appuser
USER appuser

EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz')" || exit 1

CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]

训练镜像(GPU,基于内部基础镜像)

dockerfile
FROM registry-vpc.cn-hangzhou.aliyuncs.com/robotics-base/pytorch-base:2.2.0-cuda12.1

WORKDIR /workspace

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY src/ ./src/
COPY configs/ ./configs/

CMD ["python", "-m", "torch.distributed.run", "src/train.py"]

前端服务(Node.js,多阶段构建)

dockerfile
# ===== 构建阶段 =====
FROM node:20-alpine AS builder
WORKDIR /build
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# ===== 运行阶段 =====
FROM nginx:alpine
COPY --from=builder /build/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

关键原则

  1. Dockerfile 跟业务代码在同一仓库 — 代码改了镜像自动重建
  2. 基础镜像单独管理 — 变更频率低,需要严格版本控制
  3. 开发者负责自己服务的 Dockerfile — 谁开发谁维护
  4. CI 负责构建和推送 — 开发者不手动 push 镜像到 ACR
  5. 多阶段构建 — 减小镜像体积,提高安全性(不包含构建工具)

三、发布前 Checklist

每次发布前,必须逐项检查:

代码质量

  • [ ] 所有 CI 检查通过(Lint、Test、Scan)
  • [ ] PR 经过至少 1 人 Code Review
  • [ ] 无 CRITICAL/HIGH 级别安全漏洞(Trivy 扫描)
  • [ ] 测试覆盖率不低于既有水平

配置确认

  • [ ] ConfigMap/Secret 变更已同步到目标环境
  • [ ] 环境变量无遗漏(对比 staging 与 production)
  • [ ] 资源 requests/limits 已设置且合理
  • [ ] Health probes(liveness/readiness/startup)已配置

依赖检查

  • [ ] 数据库 Migration 已执行(如有)
  • [ ] 上下游服务 API 兼容性已确认
  • [ ] 外部依赖(ACR 镜像、NAS 挂载、OSS Bucket)可访问

发布窗口

  • [ ] 选择低流量时段发布(如有)
  • [ ] 通知相关团队发布计划
  • [ ] 确认回滚方案可执行

四、发布策略详解

策略对比

策略原理适用场景回滚速度资源开销复杂度
Rolling Update逐步替换旧 Pod常规更新、无状态服务
Canary(灰度)少量流量验证新版本重要服务、用户敏感
Blue-Green新旧双副本一键切换关键服务、零停机最快高(双倍资源)
A/B Testing按条件路由不同版本功能验证、商业决策

策略 1:Rolling Update(K8s 原生)

最基本的发布方式,直接由 Deployment 控制。

yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-gateway
  namespace: production
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # 更新时最多多出 1 个 Pod
      maxUnavailable: 0    # 更新时不允许有 Pod 不可用(保证可用性)
  template:
    spec:
      containers:
      - name: api
        image: registry-vpc.cn-hangzhou.aliyuncs.com/robotics-serving/api-gateway:20260315-abc1234
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8000
          initialDelaySeconds: 10
          periodSeconds: 5
        resources:
          requests:
            cpu: 500m
            memory: 512Mi
          limits:
            cpu: "1"
            memory: 1Gi
      terminationGracePeriodSeconds: 30

更新过程

初始状态: [v1] [v1] [v1] [v1]     ← 4 个旧 Pod
                                   ↓ maxSurge=1, 多创建 1 个
Step 1:   [v1] [v1] [v1] [v1] [v2]  ← v2 创建中
                                   ↓ v2 Ready, 移除 1 个 v1
Step 2:   [v1] [v1] [v1] [v2]       ← 继续
                                   ↓ 重复
Step 3:   [v1] [v1] [v2] [v2]
Step 4:   [v1] [v2] [v2] [v2]
Step 5:   [v2] [v2] [v2] [v2]      ← 全量完成

关键参数说明

参数含义推荐值说明
maxSurge超过 replicas 的额外 Pod 数25% 或 1越大更新越快,资源消耗越多
maxUnavailable允许不可用的 Pod 数0设为 0 保证零停机
terminationGracePeriodSecondsPod 优雅关闭等待时间30s让进行中的请求处理完毕

手动操作

bash
# 触发更新(修改镜像 tag)
kubectl set image deployment/api-gateway api=registry-vpc.cn-hangzhou.aliyuncs.com/robotics-serving/api-gateway:20260316-def5678 -n production

# 观察更新进度
kubectl rollout status deployment/api-gateway -n production

# 查看更新历史
kubectl rollout history deployment/api-gateway -n production

# 回滚到上一个版本
kubectl rollout undo deployment/api-gateway -n production

# 回滚到指定版本
kubectl rollout undo deployment/api-gateway --to-revision=3 -n production

# 暂停/恢复更新
kubectl rollout pause deployment/api-gateway -n production
kubectl rollout resume deployment/api-gateway -n production

策略 2:Canary 灰度发布(Argo Rollouts)

灰度发布是生产环境最推荐的方式。需要安装 Argo Rollouts。

安装 Argo Rollouts

bash
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

# 安装 kubectl 插件
# macOS
brew install argoproj/tap/kubectl-argo-rollouts

# 验证
kubectl argo rollouts version

Canary Rollout 定义

yaml
# rollout-api-gateway.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: api-gateway
  namespace: production
spec:
  replicas: 5
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: api-gateway
  template:
    metadata:
      labels:
        app: api-gateway
    spec:
      containers:
      - name: api
        image: registry-vpc.cn-hangzhou.aliyuncs.com/robotics-serving/api-gateway:v3.1.0
        ports:
        - containerPort: 8000
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8000
          initialDelaySeconds: 10
          periodSeconds: 5
        resources:
          requests:
            cpu: 500m
            memory: 512Mi
          limits:
            cpu: "1"
            memory: 1Gi
  strategy:
    canary:
      maxSurge: "25%"
      maxUnavailable: 0
      steps:
      # Step 1: 10% 流量给新版本
      - setWeight: 10
      # Step 2: 暂停,人工观察 5 分钟
      - pause: {duration: 5m}
      # Step 3: 扩大到 30%
      - setWeight: 30
      # Step 4: 暂停,观察 + 可选人工确认
      - pause: {duration: 10m}
      # Step 5: 扩大到 60%
      - setWeight: 60
      # Step 6: 暂停,继续观察
      - pause: {duration: 10m}
      # Step 7: 全量发布
      - setWeight: 100

灰度发布过程

          流量分配
          ──────
Step 1:   ██░░░░░░░░  10% → v2  (90% v1)    观察 5 分钟
Step 2:   ███░░░░░░░  30% → v2  (70% v1)    观察 10 分钟
Step 3:   ██████░░░░  60% → v2  (40% v1)    观察 10 分钟
Step 4:   ██████████ 100% → v2               全量完成

操作命令

bash
# 触发灰度发布(更新镜像)
kubectl argo rollouts set image api-gateway api=registry-vpc.cn-hangzhou.aliyuncs.com/robotics-serving/api-gateway:v3.2.0 -n production

# 实时观察灰度进度(带 Watch)
kubectl argo rollouts get rollout api-gateway -n production -w

# 手动推进到下一步(如果 pause 没设 duration)
kubectl argo rollouts promote api-gateway -n production

# 跳过所有步骤直接全量
kubectl argo rollouts promote api-gateway --full -n production

# 灰度过程中发现问题 → 立即中止回滚
kubectl argo rollouts abort api-gateway -n production

# 中止后重试
kubectl argo rollouts retry rollout api-gateway -n production

灰度 + 自动分析(推荐)

结合 Prometheus 指标自动判断是否继续灰度:

yaml
# analysis-template.yaml
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
  namespace: production
spec:
  metrics:
  - name: success-rate
    interval: 60s
    # 成功率必须 > 99%
    successCondition: result[0] >= 0.99
    failureLimit: 3
    provider:
      prometheus:
        address: http://prometheus.monitoring:9090
        query: |
          sum(rate(http_requests_total{service="{{args.service-name}}", status=~"2.."}[5m]))
          /
          sum(rate(http_requests_total{service="{{args.service-name}}"}[5m]))
  args:
  - name: service-name
---
# rollout 中引用 analysis
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: api-gateway
  namespace: production
spec:
  strategy:
    canary:
      analysis:
        templates:
        - templateName: success-rate
        startingStep: 1    # 从第 2 步开始分析
        args:
        - name: service-name
          value: api-gateway
      steps:
      - setWeight: 10
      - pause: {duration: 5m}
      - setWeight: 30
      - pause: {duration: 10m}
      - setWeight: 60
      - pause: {duration: 10m}
      - setWeight: 100

自动分析判定逻辑

灰度期间持续采集 Prometheus 指标

    ├── 成功率 ≥ 99%  → 继续推进
    ├── 成功率 < 99% 但失败次数 < 3  → 继续观察
    └── 连续失败 ≥ 3 次  → 自动回滚

策略 3:Blue-Green 蓝绿部署(Argo Rollouts)

yaml
# rollout-bluegreen.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: llm-server
  namespace: production
spec:
  replicas: 3
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: llm-server
  template:
    metadata:
      labels:
        app: llm-server
    spec:
      containers:
      - name: llm
        image: registry-vpc.cn-hangzhou.aliyuncs.com/robotics-serving/llm-server:v2.0.0
        ports:
        - containerPort: 8080
        resources:
          requests:
            nvidia.com/gpu: "1"
          limits:
            nvidia.com/gpu: "1"
  strategy:
    blueGreen:
      activeService: llm-server-active       # 当前生产流量
      previewService: llm-server-preview     # 预览流量(内部测试)
      autoPromotionEnabled: false            # 不自动切换,需人工确认
      prePromotionAnalysis:                  # 切换前自动检查
        templates:
        - templateName: llm-health-check
      scaleDownDelaySeconds: 300             # 切换后旧版本保留 5 分钟再缩容
---
apiVersion: v1
kind: Service
metadata:
  name: llm-server-active
  namespace: production
spec:
  selector:
    app: llm-server
  ports:
  - port: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: llm-server-preview
  namespace: production
spec:
  selector:
    app: llm-server
  ports:
  - port: 8080

Blue-Green 流程

状态 1(初始):
  Active Service  ──► [v1] [v1] [v1]  ← 处理全部生产流量
  Preview Service ──► (空)

状态 2(部署新版本):
  Active Service  ──► [v1] [v1] [v1]  ← 仍然处理生产流量
  Preview Service ──► [v2] [v2] [v2]  ← 内部测试访问

状态 3(验证通过,执行切换):
  Active Service  ──► [v2] [v2] [v2]  ← 一键切换到新版本
  Preview Service ──► [v1] [v1] [v1]  ← 旧版本保留 5 分钟

状态 4(确认无问题,清理):
  Active Service  ──► [v2] [v2] [v2]  ← 正式运行
  Preview Service ──► (缩容清理)

操作

bash
# 内部验证 preview 版本
kubectl port-forward svc/llm-server-preview 8080:8080 -n production
curl http://localhost:8080/v1/health

# 确认切换
kubectl argo rollouts promote llm-server -n production

# 发现问题回滚(立即切回旧版本)
kubectl argo rollouts undo llm-server -n production

策略选型建议(AI 公司场景)

服务类型推荐策略原因
API GatewayCanary(灰度)直接面向用户,需要渐进验证
LLM 推理服务Blue-GreenGPU 资源昂贵,需要快速切换和回滚
管理后台 WebRolling Update内部系统,风险低
数据处理 PipelineRolling Update后台任务,无实时流量
训练镜像不走 CD,手动/Arena 提交训练是一次性 Job,非长驻服务

五、完整发布 SOP(标准操作流程)

4.1 常规服务发布

Day 0 (发布前一天)
────────────────
  ① 开发完成,PR 合并到 main
  ② CI 全部通过,镜像已推送到 ACR
  ③ 发布通知:"明天 XX:XX 计划发布 api-gateway v3.2.0"
  ④ 确认回滚方案(上一个稳定镜像 tag)


Day 1 (发布日)
────────────────
  准备阶段 (T-30min)
  ├── 确认 Staging 验证通过
  ├── 确认 Grafana 当前基线指标(错误率、延迟、QPS)
  ├── 打开 Grafana 发布仪表盘
  └── 在群里通知:"发布开始"

  执行阶段 (T=0)
  ├── 提交 PR:更新 production overlay 的 image tag
  ├── Tech Lead 审批 Merge
  ├── ArgoCD 开始同步
  └── 观察 Rollout 状态

  灰度阶段
  ├── 10% 流量:观察 5 分钟
  │   └── 检查:5xx 错误率、P99 延迟、Pod 状态
  ├── 30% 流量:观察 10 分钟
  │   └── 检查同上 + 业务指标
  ├── 60% 流量:观察 10 分钟
  └── 100% 全量:继续观察 30 分钟

  验收阶段 (T+1h)
  ├── 确认所有监控指标正常
  ├── 确认无用户反馈异常
  ├── 在群里通知:"发布完成,一切正常"
  └── 更新发布记录

4.2 LLM 推理服务发布

LLM 服务因为 GPU 资源和模型加载的特殊性,流程有所不同:

LLM 推理服务发布 (Blue-Green)
─────────────────────────────

  准备阶段
  ├── 新模型已上传到 CPFS/OSS
  ├── 新镜像已构建并扫描
  └── GPU 节点有足够空闲资源(同时运行新旧两组)

  部署预览版
  ├── 更新 Rollout 镜像 tag
  ├── 等待新 Pod 启动(GPU 服务通常需要 3-10 分钟加载模型)
  │   └── kubectl argo rollouts get rollout llm-server -n production -w
  ├── 通过 preview Service 内部测试
  │   ├── 功能测试:关键 prompt 测试
  │   ├── 性能测试:吞吐量和延迟对比
  │   └── 质量测试:输出质量抽检
  └── 测试通过

  执行切换
  ├── kubectl argo rollouts promote llm-server -n production
  ├── 流量瞬间切换到新版本(毫秒级)
  ├── 监控 30 分钟
  │   ├── GPU 利用率
  │   ├── 推理延迟 P50/P99
  │   ├── 吞吐量(tokens/s)
  │   └── OOM / CUDA 错误
  └── 旧版本 5 分钟后自动缩容

  异常处理
  └── 发现问题 → kubectl argo rollouts undo llm-server -n production
      └── 立即切回旧版本(秒级回滚)

4.3 训练任务发布

训练任务不是长驻服务,使用 Job 方式发布:

训练任务发布流程
────────────────

  ① 训练代码推送到 main → CI 自动构建训练镜像
  ② 镜像 tag:registry.cn-hangzhou.aliyuncs.com/robotics-training/vision-train:20260315-abc1234

  ③ 算法工程师修改训练配置
     └── 修改 PyTorchJob YAML 中的:
         - image tag(指向新镜像)
         - 训练参数(epochs, batch_size, lr)
         - 资源配置(GPU 数量、节点数)

  ④ 提交到 manifests repo → 或者用 Arena 命令行提交
     # Arena 方式
     arena submit pytorchjob \
       --name=resnet50-train-v3 \
       --gpus=8 \
       --workers=4 \
       --image=registry-vpc.cn-hangzhou.aliyuncs.com/robotics-training/vision-train:20260315-abc1234 \
       --data=training-cpfs:/data \
       "python train.py --config /data/configs/resnet50.yaml"

  ⑤ 监控训练任务
     arena get resnet50-train-v3
     arena logs resnet50-train-v3

  ⑥ 训练完成 → 模型文件保存到 CPFS/OSS

六、Ingress 灰度(无 Argo Rollouts 的方案)

如果暂时没有引入 Argo Rollouts,可以用 Nginx Ingress 注解实现基于 Header 或权重的灰度:

基于权重的灰度

yaml
# 生产 Ingress(主流量)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-gateway-main
  namespace: production
spec:
  ingressClassName: nginx
  rules:
  - host: api.robotics.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-gateway-stable
            port:
              number: 8000
---
# 灰度 Ingress(部分流量到新版本)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-gateway-canary
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"    # 10% 流量到新版本
spec:
  ingressClassName: nginx
  rules:
  - host: api.robotics.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-gateway-canary
            port:
              number: 8000

基于 Header 的灰度(内部测试)

yaml
# 只有带特定 Header 的请求走新版本
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-gateway-canary
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "X-Canary"
    nginx.ingress.kubernetes.io/canary-by-header-value: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: api.robotics.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-gateway-canary
            port:
              number: 8000
bash
# 内部测试新版本
curl -H "X-Canary: true" https://api.robotics.com/v1/health

# 普通请求仍走旧版本
curl https://api.robotics.com/v1/health

灰度调整流程

bash
# 调整灰度权重:10% → 30% → 60% → 100%
kubectl annotate ingress api-gateway-canary \
  nginx.ingress.kubernetes.io/canary-weight="30" \
  --overwrite -n production

# 全量发布后:删除灰度 Ingress,更新主 Deployment
kubectl delete ingress api-gateway-canary -n production
kubectl set image deployment/api-gateway-stable api=<new-image> -n production

七、发布监控与告警

发布期间 Grafana 仪表盘核心指标

┌─────────────────────────────────────────────────────┐
│              发布监控仪表盘                            │
│                                                     │
│  ┌───────────────────┐  ┌───────────────────────┐  │
│  │ HTTP 5xx 错误率    │  │ 响应延迟 P50/P99       │  │
│  │ ≤ 0.1% ✅         │  │ P99 < 500ms ✅        │  │
│  │ > 1%   🔴 回滚!   │  │ P99 > 2s   🔴 回滚!  │  │
│  └───────────────────┘  └───────────────────────┘  │
│                                                     │
│  ┌───────────────────┐  ┌───────────────────────┐  │
│  │ Pod 重启次数       │  │ CPU/内存使用率         │  │
│  │ = 0    ✅         │  │ < 80%   ✅            │  │
│  │ ≥ 1   🟡 关注    │  │ > 90%   🔴 排查       │  │
│  └───────────────────┘  └───────────────────────┘  │
│                                                     │
│  ┌───────────────────────────────────────────────┐  │
│  │ 业务指标(根据服务类型)                          │  │
│  │ API: QPS、成功率                               │  │
│  │ LLM: tokens/s、推理延迟、GPU 利用率             │  │
│  └───────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────┘

Prometheus 告警规则(发布期间增强)

yaml
# prometheus-release-alerts.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: release-alerts
  namespace: monitoring
spec:
  groups:
  - name: release-canary
    rules:
    - alert: CanaryHighErrorRate
      expr: |
        sum(rate(http_requests_total{status=~"5..", canary="true"}[2m]))
        /
        sum(rate(http_requests_total{canary="true"}[2m]))
        > 0.01
      for: 1m
      labels:
        severity: critical
      annotations:
        summary: "灰度版本错误率超过 1%,请立即检查"
        runbook: "执行回滚:kubectl argo rollouts abort <rollout-name>"

    - alert: CanaryHighLatency
      expr: |
        histogram_quantile(0.99,
          sum(rate(http_request_duration_seconds_bucket{canary="true"}[2m])) by (le)
        ) > 2
      for: 2m
      labels:
        severity: warning
      annotations:
        summary: "灰度版本 P99 延迟超过 2 秒"

    - alert: PodCrashDuringRelease
      expr: |
        increase(kube_pod_container_status_restarts_total[5m]) > 0
      for: 0m
      labels:
        severity: critical
      annotations:
        summary: "发布期间 Pod 发生重启"

八、回滚操作手册

回滚决策树

发布后发现异常

      ├── 5xx 错误率 > 1%? ──► 是 → 立即回滚

      ├── P99 延迟恶化 > 100%? ──► 是 → 立即回滚

      ├── Pod CrashLoopBackOff? ──► 是 → 立即回滚

      ├── 功能异常但不影响核心链路? ──► 是 → 暂停灰度,排查
      │                                        │
      │                                        ├── 能快速修复 → hotfix 分支
      │                                        └── 不能 → 回滚

      └── 指标正常 → 继续推进

回滚命令速查

bash
# ==================== Argo Rollouts 回滚 ====================

# 灰度发布中止(灰度阶段)
kubectl argo rollouts abort api-gateway -n production

# 蓝绿部署回滚(已切换后)
kubectl argo rollouts undo llm-server -n production

# ==================== 原生 Deployment 回滚 ====================

# 回滚到上一版本
kubectl rollout undo deployment/api-gateway -n production

# 查看历史版本
kubectl rollout history deployment/api-gateway -n production

# 回滚到指定版本
kubectl rollout undo deployment/api-gateway --to-revision=5 -n production

# ==================== GitOps 回滚(最推荐) ====================

# 在 manifests repo 中 revert commit
cd robotics-k8s-manifests
git revert HEAD     # 撤销最新的 image tag 变更
git push            # ArgoCD 自动同步回旧版本

# ==================== 紧急回滚(绕过 GitOps) ====================
# 仅在极端情况下使用,事后必须同步 Git

kubectl set image deployment/api-gateway \
  api=registry-vpc.cn-hangzhou.aliyuncs.com/robotics-serving/api-gateway:v3.1.0 \
  -n production

回滚后处理

回滚执行完毕

    ├── ① 确认服务恢复正常(监控指标回到基线)
    ├── ② 通知团队:"已回滚到 v3.1.0,服务恢复正常"
    ├── ③ 创建 Issue 记录回滚原因
    ├── ④ 排查根因(查日志、查监控、复现问题)
    ├── ⑤ 修复 → 走完整 CI/CD 流程重新发布
    └── ⑥ 复盘会议(如果是 P0/P1 级别事故)

九、发布记录模板

每次发布都应记录,建议在团队 Wiki 或 Git 中维护:

markdown
## 发布记录

### 2026-03-15 api-gateway v3.2.0

| 项目 | 内容 |
|------|------|
| **服务** | api-gateway |
| **版本** | v3.1.0 → v3.2.0 |
| **镜像** | robotics-serving/api-gateway:20260315-abc1234 |
| **发布策略** | Canary 灰度(10% → 30% → 60% → 100%) |
| **发布人** | @darren |
| **审批人** | @tech-lead |
| **开始时间** | 2026-03-15 14:00 |
| **全量时间** | 2026-03-15 14:45 |
| **主要变更** | 新增 XX 接口、优化 YY 性能 |
| **关联 PR** | #123, #125 |
| **发布结果** | ✅ 成功 |
| **异常记录** | 无 |

十、不同团队角色的发布职责

┌─────────────────────────────────────────────────────────────┐
│                      发布流程中的角色                          │
│                                                             │
│  开发工程师                                                  │
│  ├── 编写代码,提交 PR                                       │
│  ├── Code Review                                            │
│  └── 确认 Staging 验证通过                                   │
│                                                             │
│  Tech Lead / 发布负责人                                      │
│  ├── 审批 Production PR                                     │
│  ├── 监控灰度指标                                            │
│  ├── 决定是否推进/回滚                                       │
│  └── 异常时协调排查                                          │
│                                                             │
│  SRE / DevOps                                               │
│  ├── 维护 CI/CD 基础设施                                     │
│  ├── 维护 ArgoCD、监控告警                                   │
│  ├── 紧急回滚操作                                            │
│  └── 发布后事故复盘                                          │
│                                                             │
│  算法工程师(AI 场景)                                       │
│  ├── 训练任务提交                                            │
│  ├── 模型质量验证                                            │
│  └── LLM 推理服务的 preview 测试                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

十一、发布成熟度演进路线

根据团队阶段选择合适的发布方式:

阶段 1(起步期)
├── 手动 kubectl apply
├── 简单 Rolling Update
├── 人工观察 kubectl get pods
└── 适合:团队 < 5 人,服务 < 5 个

    ↓ 团队和服务增长

阶段 2(标准化)
├── GitHub Actions CI + ACR
├── ArgoCD 自动同步
├── Kustomize 管理多环境
├── Grafana 基础监控
└── 适合:团队 5-15 人,服务 5-20 个

    ↓ 需要更高发布质量

阶段 3(成熟期)
├── Argo Rollouts 灰度发布
├── 自动分析(Prometheus 指标驱动)
├── 完善的告警 + 自动回滚
├── 发布 SOP + 记录
└── 适合:团队 15+ 人,核心业务服务

    ↓ 追求极致

阶段 4(卓越期)
├── 全自动 Progressive Delivery
├── Chaos Engineering 验证
├── SLO 驱动的发布决策
├── Feature Flag + A/B Testing
└── 适合:大规模生产系统

对你们 AI 机器人公司的建议

当前阶段建议: 阶段 2 → 阶段 3 过渡

近期目标(1-2 个月):
├── ✅ GitHub Actions CI(已规划)
├── ✅ ArgoCD + Kustomize(已规划)
├── ⬜ 部署 Grafana 发布监控仪表盘
└── ⬜ 制定发布 SOP 文档

中期目标(3-6 个月):
├── ⬜ 引入 Argo Rollouts(API Gateway 先试点)
├── ⬜ LLM 推理服务 Blue-Green 部署
├── ⬜ 配置自动分析(AnalysisTemplate)
└── ⬜ 建立发布记录和复盘机制

下一步

12 - AI 机器人公司基础设施全景规划