在AI服务日益普及的今天,越来越多团队选择将模型推理服务部署在Kubernetes(K8s)上。然而,一个常见却令人头疼的问题反复上演:服务刚启动,还没加载完模型,流量就涌了进来——结果就是一波又一波的503错误

用户看到的是“服务不可用”,运维看到的是“刚启动就崩”,而开发者则一头雾水:“我本地跑得好好的啊?”

其实,这并不是代码的问题,而是你忽略了Kubernetes中一个关键机制——就绪探针(Readiness Probe)

今天,我们就来深入浅出地讲清楚:为什么AI服务不能一启动就接流量?就绪探针是如何拯救“刚启动就503”的?以及如何正确配置它,让AI服务优雅上线


一、为什么模型加载时不能立即接收流量?

想象一下这个场景:

你部署了一个基于BERT的大语言模型服务。容器启动后,第一步是加载几GB的模型参数到内存中,这个过程可能需要 30秒甚至更久

但Kubernetes默认认为:容器启动成功 = 服务可用。于是,只要Pod的容器运行起来了,K8s就会立刻把Service的Endpoint更新,将这个Pod加入负载均衡池。

结果就是:模型还在加载,请求已经打进来,服务无法响应,返回503 Service Unavailable

这不是服务写得不好,而是服务还没准备好

📌 核心问题:“运行中”不等于“就绪”


二、就绪探针(Readiness Probe)是什么?

就绪探针是Kubernetes提供的一种机制,用于判断一个Pod是否已经准备好接收流量

与存活探针(Liveness Probe)不同,就绪探针不决定Pod是否重启,而是决定:

✅ 这个Pod能不能加入Service的Endpoint列表?
❌ 如果没就绪,就暂时不分配流量,直到它准备就绪。

就绪探针的工作逻辑:
graph TD
    A[Pod启动] --> B[容器运行]
    B --> C{就绪探针检查}
    C -->|失败| D[不加入Endpoint, 不接收流量]
    C -->|成功| E[加入Endpoint, 开始接收流量]
    D --> F[继续检查]
    F --> C
    E --> G[正常处理请求]

只有当就绪探针连续多次检查成功后,K8s才会把这个Pod视为“可服务状态”,并开始转发请求。


三、就绪探针怎么配置?以AI服务为例

假设你用Flask或FastAPI部署了一个模型服务,启动时会执行:

model = load_model("bert-large")

你可以提供一个HTTP接口来报告加载状态:

@app.route("/ready")
def ready():
    if model is not None:
        return {"status": "ready"}, 200
    else:
        return {"status": "loading"}, 500

然后在Kubernetes的Deployment中配置就绪探针:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ai-model-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: model-service
  template:
    metadata:
      labels:
        app: model-service
    spec:
      containers:
      - name: model-server
        image: my-ai-service:v1
        ports:
        - containerPort: 8000
        readinessProbe:
          httpGet:
            path: /ready
            port: 8000
          initialDelaySeconds: 10    # 容器启动后等待10秒再开始检查
          periodSeconds: 5           # 每5秒检查一次
          timeoutSeconds: 3          # 每次请求超时3秒
          successThreshold: 1        # 1次成功即视为就绪
          failureThreshold: 3        # 连续3次失败仍为未就绪
        resources:
          limits:
            memory: "4Gi"
            cpu: "2"
关键参数解释:
  • initialDelaySeconds: 给模型加载留出时间,避免探针过早失败。
  • periodSeconds: 检查频率,不宜太频繁。
  • failureThreshold: 允许一定次数失败,避免短暂卡顿导致误判。

四、避免“刚启动就503”的最佳实践

  1. 必须配置就绪探针
    所有AI服务,尤其是加载大模型的,必须配置就绪探针,否则等于裸奔。
  2. 就绪接口要真实反映状态
    不要返回固定的200,要检查模型、Tokenizer、GPU资源等关键组件是否已初始化。
  3. initialDelaySeconds 设置合理
    根据模型加载时间设置,比如实测加载需25秒,则设为30秒。
  4. 不要用存活探针代替就绪探针
    存活探针(livenessProbe)用于重启异常Pod,如果配置不当,可能导致“正在加载模型 → 探针失败 → 被重启 → 无限循环”。
  5. 结合启动探针(Startup Probe)更稳妥(K8s 1.20+)
    对于启动特别慢的服务,可以使用启动探针,它会暂停其他探针,直到服务真正启动完成
startupProbe:
  httpGet:
    path: /ready
    port: 8000
  failureThreshold: 30   # 最多容忍30次失败
  periodSeconds: 10      # 每10秒一次,总共可撑5分钟

五、总结:让AI服务优雅上线

AI服务不同于普通Web服务,它的“启动”是一个重量级过程。Kubernetes默认的“容器运行即就绪”策略,在AI场景下极易导致服务未准备好就接收流量,引发大量错误。

就绪探针,正是解决这一问题的钥匙。它让Kubernetes学会“等待”,直到服务真正准备好,才将流量导过来。

✅ 正确使用就绪探针 = 减少503错误 + 提升用户体验 + 避免无效报警


附:完整流程图回顾

graph LR
    Start[Pod创建] --> Run[容器启动]
    Run --> Load[加载模型中...]
    Load --> Check{就绪探针检查 /ready}
    Check -->|返回200| Ready[标记为就绪]
    Check -->|返回非200| NotReady[保持未就绪]
    NotReady --> Retry[等待下次检查]
    Retry --> Check
    Ready --> Add[加入Service Endpoint]
    Add --> Serve[开始接收流量]

结语
在云原生时代,部署AI服务不仅是“跑起来”,更要“稳起来”。就绪探针虽小,却是保障服务可用性的关键一环。别再让“刚启动就503”困扰你的上线发布会了。

从今天起,给你的AI服务加上就绪探针,让它优雅地迎接第一波请求。


如果你对 AI 服务开发感兴趣,欢迎关注我的公众号【一只鱼丸yo】,我会持续分享 AI + 后端融合的技术经验。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐