跳到主要内容

容灾与降级

LLM 推理服务的容灾不只是"备用服务器",还涉及 GPU 硬件故障、模型权重损坏、显存泄漏等特有风险,需要分层次的防御体系。

核心概念(含架构图)

故障场景全景分析

部署视角

GPU 故障处理(Xid Error 检测与自动隔离)

Xid Error 类型

Xid含义严重性处理方式
13Graphics Engine Exception重启 CUDA 上下文
31GPU Memory Page Fault重启进程
43GPU Stopped ProcessingPod 重建
63ECC Page Uncorrectable Error极高隔离 GPU,换卡
79GPU Has Fallen Off Bus极高节点隔离,报修

自动检测与隔离流程

# 自动化脚本:Xid Error 检测 + 节点隔离
import subprocess
import json

def check_gpu_health():
"""通过 DCGM 检查 GPU 健康状态"""
result = subprocess.run(
['dcgmi', 'diag', '-r', '1', '-j'],
capture_output=True, text=True
)
diagnostics = json.loads(result.stdout)

for gpu_id, diag in diagnostics.items():
if diag.get('error_count', 0) > 0:
xid_errors = diag.get('xid_errors', [])
for err in xid_errors:
if err['xid'] in [13, 31, 43, 63, 79]:
isolate_gpu(gpu_id, err['xid'])

def isolate_gpu(gpu_id, xid):
"""隔离故障 GPU 所在节点"""
node = get_node_for_gpu(gpu_id)
# 1. 标记节点不可调度
subprocess.run(['kubectl', 'cordon', node])
# 2. 排空 Pod
subprocess.run(['kubectl', 'drain', node,
'--ignore-daemonsets',
'--delete-emptydir-data',
'--grace-period=120'])
# 3. 发送告警
send_alert(f"GPU {gpu_id} on {node} Xid={xid}, node cordoned")

Kubernetes 侧实现(Node Problem Detector + 自动恢复)

# Node Problem Detector:自动将不健康的 GPU 节点标记为 NotReady
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-problem-detector
namespace: kube-system
spec:
template:
spec:
containers:
- name: node-problem-detector
image: registry.k8s.io/node-problem-detector/node-problem-detector:v0.8.14
env:
- name: CUSTOM_PLUGINS
value: |
# 自定义 GPU 健康检查插件
# 当检测到 Xid Error 时,向 K8s 报告 Condition
---
# 自动恢复:GPU 故障后 Pod 自动调度到健康节点
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
# 容忍短暂的 NotReady 状态,给节点恢复时间
tolerations:
- key: "node.kubernetes.io/not-ready"
operator: "Exists"
effect: "NoExecute"
timeoutSeconds: 60 # 60 秒后 K8s 自动迁移 Pod
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["vllm"]
topologyKey: "kubernetes.io/hostname"

容灾策略:多 AZ 部署

多 AZ 部署要点

维度配置说明
流量分配80/20 或 50/50取决于成本和延迟要求
故障切换< 30 秒DNS TTL + 健康检查
模型同步S3 Cross-Region Replication保证模型权重一致
数据一致性只读模型 + 主区域更新避免脑裂
# Pod 拓扑分布约束:确保跨 AZ 均匀分布
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: vllm

降级策略详解

各级降级详细说明

第 1 级:降低 Batch Size

# 通过 ConfigMap 热更新 vLLM 配置
# max-num-seqs: 256 → 64
# 效果:单请求延迟降低,总吞吐下降
# 适用:延迟升高但 GPU 仍有能力

第 2 级:切换小模型

# API Gateway 降级路由
# 正常路由
- match: { prefix: "/v1/chat/completions" }
route: { cluster: vllm-70b }
# 降级路由(通过 feature flag 切换)
# - match: { prefix: "/v1/chat/completions" }
# route: { cluster: vllm-7b }

第 3 级:限流 + 排队

# Token Bucket 限流(API Gateway 层)
# 核心用户:100 req/min
# 普通用户:10 req/min
# 降级期间:核心用户 50 req/min, 普通用户 2 req/min

# 排队响应
{
"status": "queued",
"position": 15,
"estimated_wait_seconds": 45,
"task_id": "task-xyz789",
"poll_url": "/v1/tasks/task-xyz789/status"
}

数据恢复与模型回滚

模型权重备份策略

关键措施

措施频率RPO说明
S3 版本控制实时0每次上传自动生成新版本
跨区域复制实时< 1 分钟防单区域故障
本地快照每日24 小时MinIO snapshot
离线备份每周7 天冷存储(Glacier)

模型回滚流程

# 回滚命令(K8s 原生支持)
kubectl rollout undo deployment/vllm-llm --to-revision=2
# 回滚到第 2 个版本(即上一版本)

# 回滚验证
# 1. 检查新 Pod 状态: kubectl get pods -l app=vllm
# 2. 验证健康: curl http://vllm-service/health
# 3. 冒烟测试: 发几个标准 prompt 验证输出
# 4. 监控 SLO: 确认延迟恢复正常

面试视角

面试题:GPU 故障导致 Pod 崩溃,如何自动恢复?

标准答案

完整自动恢复链

  1. 检测(0-15 秒):DCGM Exporter 每 15 秒 scrape 一次 Xid Error 指标
  2. 告警(15-30 秒):Prometheus 告警规则 increase(DCGM_FI_DEV_XID_ERRORS[5m]) > 0 触发
  3. 隔离(30-60 秒):AlertManager Webhook 调用脚本执行 kubectl cordon + drain
  4. 迁移(60-120 秒):K8s Deployment 自动在健康节点重建 Pod
  5. 恢复(120-180 秒):新 Pod 加载模型完成,通过 Readiness Probe

如果只有有限 GPU 资源无法调度怎么办?

  1. 优先保障:通过 PriorityClass,核心业务优先调度
  2. 降级运行:自动切换到小模型部署(7B 只需 1 张 A100,70B 需要 4 张)
  3. 排队等待:请求进入队列,待资源释放后自动处理
  4. 弹性扩容:触发 Cluster Autoscaler 申请新 GPU 实例(云厂商,5-15 分钟)

常见追问

Q: GPU 显存泄漏如何检测和处理?

A:

  • 检测:监控 DCGM_FI_DEV_FB_USED 的趋势,正常情况下 Pod 重启后显存应该完全释放。如果发现显存使用量随时间线性增长(Pod 不重启也不释放),说明存在泄漏
  • 处理:设置定期 Pod 滚动重启(maxSurge: 1 保证不停机);在 vLLM 层面检查是否有未释放的 CUDA 上下文
  • 预防:使用 nvidia-smi 定期检查进程 - 显存映射,确保每个进程退出后显存完全释放

Q: 多 AZ 部署时模型权重如何保证一致性?

A:

  1. S3 跨区域复制(CRR)保证模型文件的最终一致性
  2. 每次部署前校验模型 hash(SHA256)
  3. Pod 启动时从本地缓存加载,不实时依赖 S3
  4. 更新时滚动发布:先更新 AZ-a 验证通过,再更新 AZ-b

Q: 如何避免降级期间的"降级雪崩"(小模型也被压垮)?

A:

  1. 小模型部署保持独立的资源池(不被 70B 挤占)
  2. 降级时同步收紧限流策略(70B 的限流 > 7B 的限流)
  3. 监控小模型的 GPU 利用率,如果也在升高,触发第 3 级降级
  4. 保留最低限度的规则引擎兜底(完全不依赖 GPU)

下一节:多租户与平台化