Skip to content

Kubernetes Startup、Readiness、Liveness探针全过程

容器主进程存在,只能证明PID还在,不代表应用已经完成初始化、能接收新流量或能够从内部死锁中恢复。Kubernetes通过startupProbe、readinessProbe和livenessProbe,让kubelet周期判断容器处于启动、就绪还是需要重启的状态。

探针配置错误同样会制造事故:慢启动Java服务被liveness反复杀死、数据库抖动让所有Pod同时重启、Readiness过于敏感让Endpoint全部消失、固定返回200又把已经线程池耗尽的实例持续暴露。本页从kubelet执行机制讲到Service流量和容器重启结果。

学习目标

学完后应能:

  1. 区分Container Running、Started、Ready、Live和业务端到端可用。
  2. 解释探针由Node上的kubelet执行,而不是Deployment或Service执行。
  3. 解释startupProbe如何门控readiness/liveness。
  4. 计算initialDelay、period、timeout、failureThreshold和successThreshold的时间边界。
  5. 解释Readiness失败怎样写回Pod Condition并异步影响EndpointSlice。
  6. 解释Liveness/Startup失败怎样让kubelet重启单个容器,而不是迁移Pod。
  7. 区分HTTP、TCP、gRPC和Exec探测能证明与不能证明什么。
  8. 为Spring Boot设计不产生级联重启的Liveness/Readiness契约。
  9. 解释主端口与独立Management端口的可观测性取舍。
  10. 设计慢启动、线程池耗尽、依赖抖动和优雅终止场景。
  11. 根据Event、ContainerStatus、Restart Count和EndpointSlice排查误杀/摘流。
  12. 区分Kubernetes Probe、Docker Healthcheck、外部合成监控和业务Smoke。

一、先区分五个状态

状态回答的问题常见证据
Running容器进程是否已经启动且当前未终止Container State
Started应用启动阶段是否通过startupProbeContainerStatus.started
Ready是否应该作为Service正常新流量后端Container Ready、Pod Condition
Live是否需要通过重启容器尝试恢复livenessProbe结果
业务可用用户完整业务是否成功SLI、合成测试、业务指标
text
Running=true

仍可能发生:

  • Spring Context还在初始化。
  • 数据库连接池未建立。
  • 主线程/请求线程池死锁。
  • Readiness失败。
  • Service没有Ready Endpoint。
  • Ingress/DNS/TLS故障。
  • 下单核心链路失败。

二、三种探针的职责边界

探针核心问题失败达到阈值后的动作不应该承担
startupProbe本次容器是否完成启动kubelet终止并按策略重启容器日常依赖抖动监控
readinessProbe当前是否适合接收新流量Ready=False,端点异步摘除自动重启修复
livenessProbe当前容器是否陷入只能重启恢复的状态kubelet终止并重启该容器检查共享数据库是否可用

三个Probe不是“同一个健康接口复制三份配置”。它们对应不同决策,健康条件应分别设计。

三、是谁执行探针

探针由运行Pod所在Node的kubelet负责调度和执行。Deployment Controller不发HTTP健康请求,Service也不主动探测应用。

mermaid
flowchart TD
    A["API Server保存PodSpec中的Probe"] --> B["Pod被Scheduler绑定Node"]
    B --> C["Node kubelet创建容器"]
    C --> D["kubelet按配置执行Probe"]
    D --> E["结果更新Container/Pod状态"]
    E --> F{"Probe类型和结果"}
    F -- "Readiness失败" --> G["Ready=False并更新Endpoint条件"]
    F -- "Liveness/Startup失败达阈值" --> H["kubelet终止并重启容器"]

HTTP/TCP/gRPC探针通常从Node网络访问Pod IP;Exec探针通过容器运行时在容器内执行命令。这意味着探针成功不证明公网DNS、Ingress、TLS和Service ClusterIP正常。

四、容器启动后的探针状态机

mermaid
flowchart TD
    A["容器进程启动"] --> B{"是否配置startupProbe"}
    B -- "是" --> C["只执行startupProbe"]
    C --> D{"是否成功"}
    D -- "未达失败阈值" --> C
    D -- "失败达阈值" --> E["重启容器并重新开始"]
    D -- "成功" --> F["容器标记Started"]
    B -- "否" --> F
    F --> G["启动readiness和liveness检查"]
    G --> H{"Readiness是否成功"}
    H -- "否" --> I["Ready=False,不接正常新流量"]
    H -- "是" --> J["Ready=True,可进入Endpoint"]
    G --> K{"Liveness是否连续失败达阈值"}
    K -- "是" --> E
    K -- "否" --> G

配置startupProbe后,成功之前readiness和liveness不会正常接管,避免慢启动期间被liveness误杀。startupProbe一旦成功,一般不再继续执行,后续存活交给liveness。

五、Probe结果:Success、Failure和Unknown

kubelet内部会把单次探测归类为:

  • Success:探测成功。
  • Failure:明确失败、非成功状态、连接失败或超时。
  • Unknown:执行本身无法得到有效结论等异常边界。

最终状态还要结合连续阈值,而不是一次失败就必然重启/摘除。具体Unknown处理和Event表现受实现/版本影响,应在目标集群故障注入验证。

六、六个时间参数

字段常见默认值含义
initialDelaySeconds0容器启动后首次执行前等待
periodSeconds10常规探测周期
timeoutSeconds1单次探测允许时间
failureThreshold3连续失败多少次判失败
successThreshold1连续成功多少次恢复成功
terminationGracePeriodSeconds继承Pod或Probe级配置探针失败后容器终止宽限期,版本支持有边界

默认 timeoutSeconds: 1 对高负载Java服务可能太激进;不能依赖默认值而不压测。

Probe级 terminationGracePeriodSeconds 主要适用于Startup/Liveness失败触发的容器终止,不能配置为Readiness“摘流量等待时间”;字段可用版本、最小值和继承行为必须在目标集群验证。

6.1 Liveness和Startup的successThreshold

Liveness和Startup的 successThreshold 必须为1;Readiness可以大于1,用于避免依赖刚恢复时立即反复接流量。

6.2 Readiness可能比period更积极

当容器NotReady时,kubelet可能在某些情况下比常规period更快执行Readiness,以便尽快恢复Ready。不能把period当严格定时任务SLA,准确行为按版本验证。

七、怎样估算Startup最大等待窗口

示例:

yaml
startupProbe:
  httpGet:
    path: /actuator/health/liveness
    port: 8080
  periodSeconds: 5
  timeoutSeconds: 2
  failureThreshold: 24

粗略可理解为最多约:

text
24 × 5秒 = 120秒级启动窗口

但实际时间还受首次调度、单次Probe执行耗时、kubelet负载和边界取整影响。若每次探测都跑满timeout,不能机械把所有字段相加当绝对精确时刻。

设计依据应来自:

  • 冷启动P99。
  • 镜像/类加载。
  • Spring Bean初始化。
  • 数据库迁移和缓存预热边界。
  • CPU Limit/Throttle。
  • 节点压力。

窗口过短会误杀;过长会让永远启动失败的版本占用资源很久并拖慢Rollout失败发现。

八、initialDelay不能替代startupProbe

只配置:

yaml
livenessProbe:
  initialDelaySeconds: 120

有两个问题:

  • 快启动应用也要固定等120秒才开始存活保护。
  • 慢于120秒时仍被误杀。

startupProbe根据实际成功结束启动保护:快则提前进入正常探针,慢则在有界窗口等待,更符合状态机语义。

九、Readiness失败后的完整链路

mermaid
flowchart TD
    A["kubelet执行readinessProbe"] --> B["连续失败达到failureThreshold"]
    B --> C["该Container Ready=False"]
    C --> D["Pod ContainersReady/Ready Condition变化"]
    D --> E["状态写回API Server"]
    E --> F["EndpointSlice Controller观察变化"]
    F --> G["Endpoint ready条件更新"]
    G --> H["kube-proxy/Ingress等数据面异步更新"]
    H --> I["正常新连接不再选择该Pod"]

这不是全局原子操作:

  • 状态写回有延迟。
  • EndpointSlice和数据面更新有延迟。
  • 已建立Keep-Alive/gRPC/WebSocket连接不会自动迁移。
  • 直接访问Pod IP不经过Service选择。

Readiness是流量准入信号,不是瞬时断网开关。

十、Readiness恢复怎样重新接流量

连续成功达到 successThreshold 后:

text
Container Ready=True
→ Pod Ready可能变True
→ EndpointSlice Ready更新
→ 数据面重新加入后端

若依赖在好/坏之间抖动,Pod会反复进出Endpoint,造成连接重置和流量集中。可使用合理success/failureThreshold、依赖熔断和恢复稳定窗口,不能只把period调得很大掩盖。

十一、Liveness失败后的完整链路

mermaid
flowchart TD
    A["liveness连续失败达阈值"] --> B["kubelet按容器终止流程执行"]
    B --> C["执行preStop并发送SIGTERM"]
    C --> D{"宽限期内是否退出"}
    D -- "否" --> E["SIGKILL"]
    D -- "是" --> F["容器结束"]
    E --> F
    F --> G["按restartPolicy创建同Pod内新容器实例"]
    G --> H["Restart Count增加,重新经历Startup"]

重要边界:

  • 默认是重启失败的容器,不是Scheduler把Pod迁移到另一个Node。
  • Pod名称和UID通常不变,Container ID变化。
  • 多容器Pod中,目标容器重启不等于所有Sidecar一起重启。
  • 重启不能修复Node网络、共享数据库故障和错误配置。
  • 反复失败会进入容器重启退避,表现为CrashLoopBackOff。

十二、探针失败与restartPolicy

长期服务通常使用Pod默认 restartPolicy: Always。Liveness/Startup失败导致容器终止后,kubelet按策略重启。

Job常使用Never或OnFailure。探针配置在Job中需要特别谨慎:批任务正常长时间计算不代表死锁,错误Liveness可能让同一任务重复执行并产生副作用。

十三、HTTP GET Probe执行原理

yaml
readinessProbe:
  httpGet:
    scheme: HTTP
    path: /actuator/health/readiness
    port: http

kubelet通常从Node侧向Pod IP和指定端口发起HTTP请求。HTTP状态码200到399通常视为成功,其他状态或连接/超时视为失败。

它通常不经过:

  • Service ClusterIP。
  • Ingress Controller。
  • 公网DNS。
  • 外部LoadBalancer。

所以即使Probe成功,Service targetPort、Ingress Host、TLS证书仍可能错误。

13.1 scheme

HTTPHTTPS决定kubelet怎样连接。Kubernetes的HTTPS Probe通常跳过服务端证书校验,因此证书过期、SAN错误或链不完整时Probe仍可能成功;不要把它当外部TLS合成测试。公网证书必须通过带正确SNI、CA校验的独立监控验证。

13.2 host与Host Header

一般不要把 httpGet.host 写成Service域名;kubelet应直接访问Pod IP。需要虚拟Host时,使用 httpHeaders设置Host更符合意图:

yaml
httpHeaders:
  - name: Host
    value: internal-health.example

但健康接口最好不依赖复杂虚拟主机和认证链。

13.3 Redirect边界

健康路径不应返回重定向。kubelet对同Host重定向有有限处理和警告边界,跨Host/过多重定向行为可能被视为成功或失败且随版本变化。最安全是直接返回明确200/503。

十四、TCP Socket Probe

yaml
livenessProbe:
  tcpSocket:
    port: 3306

kubelet只尝试建立TCP连接。成功只能证明端口接受连接,不能证明:

  • MySQL认证成功。
  • SQL可执行。
  • 数据未损坏。
  • 应用线程池能处理请求。
  • 协议响应正确。

适合没有标准健康协议、且“端口无法连接”足以判定局部故障的场景。若进程只accept但不处理,TCP Probe会假阳性。

十五、gRPC Probe

内置gRPC Probe使用gRPC Health Checking Protocol:

yaml
livenessProbe:
  grpc:
    port: 9090
    service: order-api-liveness
  periodSeconds: 10
  timeoutSeconds: 2

边界:

  • 应用必须实现标准gRPC Health服务。
  • service可区分liveness/readiness语义。
  • 通常使用数字端口,不支持命名端口。
  • 不提供任意认证/TLS参数,复杂安全链需其他方案。
  • 内置gRPC Probe的稳定版本和timeout行为受Kubernetes版本/Feature Gate影响。
  • 错误端口、未实现服务、超时都会失败。

不要在镜像中额外塞一个不受控 grpc-health-probe 二进制而不管理版本和供应链;现代版本优先评估内置能力。

十六、Exec Probe

yaml
readinessProbe:
  exec:
    command:
      - /app/bin/check-readiness
      - --timeout-ms=500
  timeoutSeconds: 1

kubelet通过Runtime在容器内执行新进程,退出码0成功,非0失败。

重要:

  • command数组默认不是Shell,不会自动解释管道、重定向和&&
  • 需要Shell时必须显式 sh -c,但Distroless镜像可能没有Shell。
  • 每次Probe启动进程,有CPU、PID和IO开销。
  • 脚本若Fork后台进程或超时清理不当,可能泄漏进程。
  • 脚本依赖外部命令,而精简镜像可能没有curl、grep、ps。
  • Exec timeout执行边界受Runtime和Feature Gate历史影响,必须在目标版本故障注入。

高频Exec Probe执行Java命令或复杂SQL,可能反过来压垮容器。

十七、四种Probe方式对比

方式能证明不能证明主要风险
HTTP应用HTTP处理路径在本Pod可响应Service/Ingress/完整业务同线程池拥塞、错误重定向
TCP端口能建立连接协议和业务正确accept假健康
gRPC标准Health RPC可响应外部网关和业务RPC版本、端口和安全限制
Exec自定义命令退出码外部流量路径进程/资源开销、脚本依赖

选择最简单且能支持决策的探针,避免把完整业务交易塞进kubelet高频执行。

十八、参数怎样按故障预算设计

例如Readiness:

yaml
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
successThreshold: 2

粗略语义:

  • 连续约3次失败后摘流量,故障检测约10到15秒级,加单次执行/传播时间。
  • 恢复后需要连续2次成功,约5到10秒级重新接流量。

这不是精确SLA。需考虑:

  • 探测首次时间。
  • 每次Probe耗时。
  • kubelet调度延迟。
  • 状态写回和Endpoint传播。
  • Controller/数据面同步。

参数来自业务可容忍错误窗口、连接Drain和依赖恢复特征,而不是复制网上固定值。

十九、Liveness到底应该检查什么

Liveness只检查“重启当前容器是否有较大概率恢复”的本地不可恢复状态,例如:

  • 事件循环/关键处理线程永久卡死。
  • 应用内部状态机不可恢复。
  • 主HTTP处理端口完全失去响应且重启可恢复。

不建议直接检查:

  • 共享数据库。
  • Redis集群。
  • 外部支付接口。
  • DNS上游。
  • 全局配置中心。

因为依赖故障影响所有副本,若Liveness包含它:

text
数据库抖动
→ 所有Pod liveness失败
→ 全部容器重启
→ 连接风暴/冷启动
→ 数据库压力更大
→ 故障放大

二十、Readiness应该检查哪些依赖

Readiness表示“这个实例现在接新流量是否比不接更安全”。可考虑:

  • 应用初始化完成。
  • 必需配置已加载。
  • 关键本地资源可用。
  • 必需连接池已建立到最低容量。
  • 该实例无法处理任何请求的关键依赖状态。

但不能把所有下游都无脑加入:

  • 某个非核心推荐服务故障时,订单API可能仍可降级。
  • 所有Pod共享数据库,全部摘除会让入口直接503,可能比应用返回可解释降级更差。
  • 每5秒从每个Pod对每个依赖做真实调用会形成探针流量风暴。

按功能分级:核心不可降级依赖、可降级依赖和仅告警依赖。

二十一、Spring Boot Availability State

Spring Boot Actuator提供:

  • LivenessState:应用内部存活状态。
  • ReadinessState:是否接受流量。

常见路径:

text
/actuator/health/liveness
/actuator/health/readiness

配置示意:

yaml
management:
  endpoint:
    health:
      probes:
        enabled: true
      show-details: never
  endpoints:
    web:
      exposure:
        include: health,prometheus

不要在公网暴露全部Actuator端点。健康响应不应包含数据库URL、用户名、磁盘路径、异常堆栈和Secret。

二十二、Spring Boot主端口还是Management端口

主业务端口

优点:能证明主Web Server、端口和部分请求处理链可用。缺点:业务线程池拥塞时健康也失败,Liveness可能重启形成风暴。

独立Management端口

优点:健康和指标不受主端口部分拥塞影响。缺点:Management端口健康时,主业务端口可能已经死锁/不监听,产生Liveness假阳性。

生产折中:

  • Readiness/Liveness需要覆盖主服务是否能处理最小请求。
  • 健康逻辑本身保持轻量、有界。
  • 用应用指标/线程池饱和和外部合成监控补充。
  • 对独立Management端口设置NetworkPolicy,不公网暴露。

二十三、完整Spring Boot商业Demo

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-api
  namespace: commerce
spec:
  replicas: 3
  minReadySeconds: 10
  progressDeadlineSeconds: 300
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: order-api
  template:
    metadata:
      labels:
        app: order-api
    spec:
      terminationGracePeriodSeconds: 45
      containers:
        - name: order-api
          image: registry.example.com/order-api@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
          ports:
            - name: http
              containerPort: 8080
          startupProbe:
            httpGet:
              path: /actuator/health/liveness
              port: http
            periodSeconds: 5
            timeoutSeconds: 2
            failureThreshold: 24
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: http
            periodSeconds: 5
            timeoutSeconds: 2
            failureThreshold: 3
            successThreshold: 2
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
              port: http
            periodSeconds: 10
            timeoutSeconds: 2
            failureThreshold: 3
          lifecycle:
            preStop:
              exec:
                command: ["sh", "-c", "sleep 5"]
          resources:
            requests:
              cpu: 250m
              memory: 512Mi
            limits:
              cpu: "1"
              memory: 1Gi

示例 preStop要求镜像有Shell;Distroless镜像应依靠应用正确处理SIGTERM或使用受支持Hook。参数必须通过目标镜像冷启动压测和故障注入调整。

二十四、为什么Startup常使用Liveness路径

启动阶段只需证明应用内部已完成足够初始化并能进入正常检查;使用Liveness路径可以避免Readiness中外部依赖抖动阻止容器永远“启动”。

但如果应用进程在Spring Context完成前就让Liveness端点返回成功,startupProbe会过早放行。必须验证Availability State转换时机。

二十五、Readiness与Deployment滚动更新

新Pod必须Ready,并持续满足 minReadySeconds 后才成为Available。maxUnavailable: 0 时,新Pod不Ready会让旧Pod继续保留,Rollout卡住但服务可能仍可用。

text
新版本Readiness失败
→ 新Endpoint不接流量
→ 旧ReplicaSet不继续缩容
→ progressDeadline最终标记失败

progressDeadlineSeconds不会自动业务回滚,流水线要检测并停止扩散。

二十六、Readiness和优雅终止

理想Drain:

  1. 应用开始拒绝新流量,Readiness变False。
  2. EndpointSlice和数据面传播。
  3. 已有连接/在途请求有时间完成。
  4. 收到SIGTERM并关闭Listener/消费者。
  5. 宽限期内退出。

但Pod删除、Endpoint更新、preStop和SIGTERM并非全局原子顺序。常用短preStop等待传播只是缓冲,不是绝对保证。应用必须处理SIGTERM、停止接新工作和幂等重试。

二十七、Readiness Gates

Pod可以声明额外Readiness Gate,让自定义Condition参与Pod Ready,例如云LB后端注册或平台准入:

yaml
spec:
  readinessGates:
    - conditionType: example.com/lb-registered

只有内置容器Ready和自定义Condition都满足,Pod才整体Ready。负责写Condition的Controller故障会让Pod长期NotReady;必须监控该Controller和Condition Reason。

不要让业务应用随意伪造平台Readiness Condition,写status需要受控权限。

二十八、探针不能替代业务Smoke和合成监控

Probe通常只验证Node→Pod局部路径。外部合成监控应验证:

text
公网/企业DNS
→ LoadBalancer
→ TLS证书
→ Ingress Host/Path
→ Service/Endpoint
→ 应用
→ 关键只读业务依赖

发布Smoke可以创建测试订单/查询并清理,但要有幂等、隔离测试账号和副作用控制。不要让kubelet每5秒执行真实下单。

二十九、Kubernetes Probe与Docker Healthcheck区别

能力Dockerfile HEALTHCHECKKubernetes Probe
定义位置镜像PodSpec
Startup/Ready/Live分工通常单一Health状态三种决策分离
Service Endpoint联动无K8s语义Readiness联动Pod/Endpoint
重启动作取决于运行/编排系统kubelet按Liveness/Startup重启
环境配置镜像默认可按环境配置

Kubernetes通常使用PodSpec Probe做编排决策;镜像Healthcheck是否被底层Runtime直接用于K8s决策,不能假设,需以集群实现为准。

三十、探针自身的资源开销

假设1000个Pod,每个配置两个5秒周期HTTP Probe:

text
约400次探测/秒(忽略启动、抖动和额外执行)

如果每次探针都:

  • 查询数据库。
  • 执行Redis命令。
  • 调用多个下游。
  • 生成大JSON和堆栈。

会形成稳定背景压力。Exec还会创建进程并消耗PID。健康端点必须轻量、超时有界,并通过缓存/状态聚合避免探针风暴。

三十一、探针安全

  • 健康端点不返回Secret和内部拓扑。
  • Management端口用NetworkPolicy限制Node/监控来源。
  • 不要求高权限Token才能Probe,否则轮换/认证故障导致误杀。
  • Exec脚本不可由低权限配置任意覆盖,防命令注入。
  • 不在URL Query中放密码。
  • TLS与认证复杂性由外部合成监控补充。

Probe是高频自动调用面,也需要威胁建模。

三十二、场景一:Startup反复失败

证据:

bash
kubectl describe pod <pod> -n commerce
kubectl get pod <pod> -n commerce -o yaml
kubectl logs <pod> -n commerce -c order-api --previous --tail=300 --timestamps

检查:

  • 路径/端口/scheme错误。
  • 应用冷启动超过窗口。
  • CPU Limit导致严重Throttle。
  • 配置、Secret、数据库迁移失败。
  • 健康端点在启动完成前不可用是否符合设计。
  • 容器实际没有监听Pod IP。

不要只无限增大failureThreshold。若应用永远失败,窗口越大只会拖慢发布失败发现。

三十三、场景二:Liveness制造重启风暴

表现:

  • Restart Count持续增加。
  • Event反复 Liveness probe failed
  • logs --previous显示应用正在初始化或依赖异常。
  • 所有副本在依赖抖动时同步重启。

处理:

  1. 保留Event、previous日志、配置和时间线。
  2. 暂停继续发布。
  3. 判断Probe失败是应用真死还是超时/依赖误判。
  4. 回退错误Probe或版本。
  5. 修复Liveness契约,而不是永久删除所有健康检查。

如果数据库被加入Liveness,先移除该外部依赖并设计Readiness/降级。

三十四、场景三:Readiness全部失败导致503

bash
kubectl get pod -n commerce -l app=order-api
kubectl describe pod <pod> -n commerce
kubectl get endpointslice -n commerce \
  -l kubernetes.io/service-name=order-api -o yaml

检查:

  • 所有Pod是否Ready=False。
  • EndpointSlice是否没有Ready地址。
  • Ingress 503是否因无Backend。
  • Readiness是否检查共同依赖。
  • 依赖能否降级而不是摘除全部流量。

不要把Readiness固定返回200作为止损,这可能把真正无法服务的实例放回流量。应恢复旧版本、修复依赖或启用经过验证的降级路径。

三十五、场景四:高峰期偶发Probe Timeout

关联:

  • Probe latency和失败时间。
  • Pod CPU Usage/Throttle。
  • JVM GC/Safepoint。
  • Web线程池和队列。
  • Node CPU/IO压力。
  • kubelet健康。

如果健康端点与业务共用线程池,Timeout可能真实反映服务饱和;简单调大timeout会延迟摘除。若只是Node/kubelet调度抖动,则应治理Node。用故障实验决定,而不是猜。

三十六、场景五:Probe成功但用户访问失败

因为Probe不覆盖:

  • Service Selector/targetPort。
  • CoreDNS。
  • IngressClass/Host/Path/Rewrite。
  • 公网DNS。
  • TLS/SNI和证书。
  • 外部LB/WAF。
  • 完整业务依赖。

Service网络排查Ingress七层排查 继续,不能据Probe成功关闭告警。

三十七、场景六:TCP Probe成功但请求挂死

端口accept成功不代表工作线程处理。改用轻量HTTP/gRPC健康协议,检查线程池、事件循环和锁。Liveness是否要通过主请求线程路径,需要在避免假阳性和避免重启风暴之间权衡。

三十八、场景七:Exec Probe超时或进程增长

bash
kubectl top pod <pod> -n commerce --containers
kubectl exec <pod> -n commerce -- ps -ef

精简镜像无ps时使用受控Debug Container。检查脚本是否:

  • fork后台进程。
  • 调用无超时网络命令。
  • 每次生成临时文件。
  • 依赖不存在的Shell/工具。
  • 并发执行超过周期。

将检查改为应用内轻量状态或受控小程序,并验证超时能终止全部子进程。

三十九、场景八:Readiness反复抖动

观察Condition转换时间、Event和Endpoint变化,检查:

  • 依赖阈值无滞后。
  • successThreshold太低。
  • 健康接口偶发超时。
  • GC/CPU周期峰值。
  • 依赖熔断器状态。
  • 配置中心短暂断开。

加入恢复稳定窗口和本地状态聚合,而不是只把失败阈值调到很大,让坏实例长时间接流量。

四十、取证命令全集

bash
kubectl get pod <pod> -n commerce -o wide
kubectl describe pod <pod> -n commerce
kubectl get pod <pod> -n commerce -o yaml
kubectl logs <pod> -n commerce -c order-api --tail=300 --timestamps
kubectl logs <pod> -n commerce -c order-api --previous --tail=300 --timestamps
kubectl get events -n commerce \
  --field-selector involvedObject.name=<pod> \
  --sort-by=.metadata.creationTimestamp
kubectl get endpointslice -n commerce \
  -l kubernetes.io/service-name=order-api -o yaml
kubectl top pod <pod> -n commerce --containers

ContainerStatus摘要:

bash
kubectl get pod <pod> -n commerce \
  -o jsonpath='{range .status.containerStatuses[*]}name={.name}{" ready="}{.ready}{" started="}{.started}{" restarts="}{.restartCount}{" current="}{.state}{" last="}{.lastState}{"\n"}{end}'

四十一、监控哪些Probe指标

  • Probe成功/失败/Unknown次数。
  • 按type、Pod、版本、Node的失败率。
  • Probe执行耗时。
  • Container Restart Count和原因。
  • Pod Ready比例与Condition转换。
  • Endpoint Ready数量。
  • Rollout Available/Unavailable。
  • 从NotReady到恢复的时间。
  • Liveness重启后的恢复成功率。

告警需要版本、Node、Probe类型、错误消息和Runbook,不只写“Pod不健康”。

四十二、常见误区

  1. Running等于健康:进程存在不等于Ready/业务可用。
  2. 三个Probe用同一复杂接口:三者决策不同。
  3. initialDelay能完全替代startupProbe:固定等待不能适应快慢启动。
  4. Readiness失败会重启容器:它主要改变流量准入。
  5. Liveness失败会把Pod迁移Node:通常只在同Pod重启容器。
  6. Liveness检查数据库:共享依赖故障会造成重启风暴。
  7. TCP成功代表业务健康:只证明端口accept。
  8. Probe成功代表Ingress可用:通常不经过Service/Ingress。
  9. timeoutSeconds默认足够:默认1秒可能误杀高负载Java应用。
  10. sub-second精确执行:kubelet调度和传播有延迟。
  11. 调大所有阈值就稳定:会延迟真实故障发现。
  12. 固定返回200最安全:会制造假健康和错误流量。

四十三、面试标准回答

startup、readiness和liveness区别

startup判断本次容器是否完成启动,成功前门控readiness/liveness,失败达阈值会重启;readiness决定是否作为Service正常新流量后端,失败不重启;liveness判断当前容器是否需要重启恢复,失败达阈值由kubelet重启该容器,通常不迁移Pod。

Readiness失败后流量怎样摘除

kubelet把Container Ready和Pod Ready Condition写回API Server,EndpointSlice Controller更新Endpoint ready条件,kube-proxy/Ingress等数据面再异步同步。该过程不是原子的,已有长连接不会自动迁移,直接PodIP访问也不受Service选择控制。

为什么Liveness不应检查数据库

数据库是共享外部依赖,故障时重启应用通常不能修复;如果所有Pod都把数据库加入Liveness,会同步重启、制造冷启动和连接风暴,进一步压垮数据库。Liveness只检查重启本容器可能恢复的本地不可恢复状态。

HTTP、TCP、gRPC、Exec Probe区别

HTTP验证Pod内HTTP路径,TCP只验证端口可连接,gRPC调用标准Health协议,Exec在容器内执行命令看退出码。它们通常只覆盖Node到Pod或容器内部路径,不能证明Service、Ingress、TLS和完整业务可用;Exec还有进程和资源开销。

探针为什么会造成CrashLoopBackOff

Startup/Liveness路径、端口或超时错误,慢启动窗口不足,CPU Throttle或外部依赖误入Liveness,都可能让kubelet反复终止容器;重启退避后表现为CrashLoopBackOff。应看Event、previous日志、Container lastState和资源指标,不能只增大阈值。

独立Management端口做Liveness有什么风险

它可避免主业务线程池拥塞影响健康,但也可能在主业务端口已经死锁/关闭时仍返回成功,产生假阳性。需要让Probe覆盖主服务最小处理能力,并用线程池指标和外部合成监控补充。

四十四、学习实验与验收

实验一:慢启动误杀

让测试应用启动90秒,先只配过短Liveness复现重启,再加入120秒级startupProbe,观察Started、Restart Count和Event。

实验二:Readiness与EndpointSlice

切换应用Readiness状态,记录Pod Condition、EndpointSlice、Service新连接和已有Keep-Alive连接,证明传播和连接边界。

实验三:数据库故障重启风暴

在隔离环境把数据库检查加入Liveness并短暂阻断数据库,观察所有Pod重启;再改为降级/Readiness策略并比较恢复时间。不得在生产执行。

实验四:TCP假健康

编写只accept连接但不处理请求的测试服务,比较TCP Probe成功与HTTP业务超时,说明探针能力边界。

实验五:Exec资源开销

配置高频Exec脚本,测量PID、CPU和进程清理,再换成轻量HTTP状态,比较Node/Pod开销。

实验六:Probe成功但入口失败

保持HTTP Probe成功,故意写错Service targetPort或Ingress Host;按Pod→Service→Ingress逐层取证,证明局部健康不等于端到端可用。

验收清单

  1. 能区分Running、Started、Ready、Live和业务可用。
  2. 能画出kubelet探针状态机。
  3. 能计算Startup/Readiness粗略检测窗口。
  4. 能解释Readiness到EndpointSlice传播。
  5. 能解释Liveness重启对象和Restart Count。
  6. 能比较四种Probe方式的证据边界。
  7. 能设计Spring Boot Liveness/Readiness契约。
  8. 能权衡主端口和Management端口。
  9. 能识别依赖故障造成的重启风暴。
  10. 能设计Readiness、优雅终止和长连接Drain。
  11. 能使用Event、previous日志和状态排查误杀。
  12. 能用外部合成监控补齐Probe盲区。

关联知识点