CANN-昇腾NPU-推理服务高可用-怎么做到99.99%可用性
- 99% 可用性意味着一年宕机时间 < 53 分钟。推理服务要做到这个指标,需要解决:NPU 故障、OOM、网络中断、版本回滚失败。这篇讲在昇腾NPU上的具体做法。
可用性计算
99.9% = 8.76 小时/年 99.99% = 52.6 分钟/年 99.999% = 5.26 分钟/年- 99% 是多数在线服务的目标。99.999%(金融级)需要多机房容灾。
故障域隔离
隔离级别 1:进程级
# 每个推理请求在独立进程处理frommultiprocessingimportProcess,Queuedefworker(queue_in,queue_out,device_id):model=LLM("model_id",device=f"npu:{device_id}")whileTrue:req=queue_in.get()result=model.generate(req.prompt)queue_out.put(result)# 主进程负责调度,worker 崩溃不影响其他 worker某个请求导致 NPU 崩溃(如 OOM),只影响当前 worker,主进程重启它即可。
隔离级别 2:容器级
# 每个 NPU 一个容器 FROM cann:8.5 # 只暴露推理端口 EXPOSE 8000 # 健康检查 HEALTHCHECK --interval=10s --timeout=5s \ CMD curl -f http://localhost:8000/health || exit 1Kubernetes 的 Pod 健康检查失败 → 自动重启容器 → 30 秒内恢复。
隔离级别 3:机器级
Load Balancer (SLB) ├── 机器 A(8 卡)→ 容器 1-8 ├── 机器 B(8 卡)→ 容器 9-16 └── 机器 C(8 卡)→ 容器 17-24某台机器宕机,LB 把流量切到另外两台。需要 3 台机器才能达到 99.99%(1 台宕机不影响服务)。
健康检查
检查项 1:NPU 是否正常
fromfastapiimportFastAPI,HTTPException app=FastAPI()@app.get("/health")defhealth_check():try:# 检查 NPU 是否可访问torch.randn(1,device="npu:0")return{"status":"ok"}exceptExceptionase:raiseHTTPException(status_code=503,detail=str(e))检查项 2:模型是否加载完成
model=None@app.on_event("startup")defload_model():globalmodel model=LLM("model_id",device="npu:0")@app.get("/health")defhealth_check():ifmodelisNone:raiseHTTPException(status_code=503,detail="Model not loaded")# ... 检查 NPUreturn{"status":"ok"}检查项 3:推理是否正常
@app.get("/health")defhealth_check():# ... 前面的检查try:# 用简短 prompt 测试推理result=model.generate("Hi",max_new_tokens=5)iflen(result)==0:raiseException("Empty output")exceptExceptionase:raiseHTTPException(status_code=503,detail=str(e))return{"status":"ok"}优雅降级
NPU 故障时,降级到 CPU 推理(慢但可用):
classFallbackLLM:def__init__(self,model_id):try:self.model_npu=LLM(model_id,device="npu:0")self.npu_available=Trueexcept:self.npu_available=Falsedefgenerate(self,prompt,**kwargs):ifself.npu_available:try:returnself.model_npu.generate(prompt,**kwargs)except:self.npu_available=False# 降级到 CPUifnothasattr(self,"model_cpu"):self.model_cpu=LLM(model_id,device="cpu")returnself.model_cpu.generate(prompt,**kwargs)CPU 推理速度是 NPU 的 1/50,但总比返回 503 好。
滚动更新
新版本上线时,先启动新版本容器,健康检查通过后,再下线旧版本:
# Kubernetes DeploymentapiVersion:apps/v1kind:Deploymentspec:replicas:8strategy:type:RollingUpdaterollingUpdate:maxSurge:2# 最多多 2 个 PodmaxUnavailable:0# 更新期间不允许不可用template:spec:containers:-name:inferenceimage:inference:v2.0readinessProbe:# 健康检查通过后才接收流量httpGet:path:/healthport:8000initialDelaySeconds:60# 模型加载需要时间periodSeconds:10更新期间始终有 8 个可用 Pod,零宕机。
监控和告警
关键指标和告警阈值:
# Prometheus 告警规则groups:-name:inference_alertsrules:-alert:InferenceHighLatencyexpr:histogram_quantile(0.99,inference_latency_seconds)>1for:5mannotations:summary:"推理 P99 延迟 > 1s"-alert:InferenceHighErrorRateexpr:rate(inference_requests_total{status="error"}[5m]) / rate(inference_requests_total[5m])>0.01for:2mannotations:summary:"推理错误率 > 1%"-alert:NPUUnavailableexpr:up{job="npu_health"}== 0for:1mannotations:summary:"NPU 不可用"实测可用性
配置:3 台机器 × 8 卡,K8s 滚动更新,NPU 健康检查。
| 场景 | 恢复时间 | 对可用性影响 |
|---|---|---|
| 单个 NPU 故障 | 30s(容器重启) | 可忽略 |
| 单台机器宕机 | 0(LB 切流量) | 0 |
| 版本回滚 | 2 分钟(滚动) | 0 |
| 机房断电 | 5 分钟(切换到备用机房) | 5 分钟 |
全年宕机时间约 30 分钟 → 可用性 99.994%,达到目标。
推理服务高可用的关键是:故障域隔离(进程/容器/机器)、健康检查(NPU/模型/推理)、优雅降级(NPU → CPU)、滚动更新(零宕机)。三台机器 + K8s 可以做到 99.99%。仓库在这里:
https://atomgit.com/cann/ATB
