三个已注册 Web 端点分为仅 passing 的 web-1 集合,以及包含 warning 的 web-1 与 web-2 集合。

Consul 发现结果取决于健康策略与新鲜度

Consul 服务发现提供注册端点和已经记录的健康观测,不能承诺每个返回端点都会成功响应调用方的下一次请求。实用的运维模型需要分开四件事:注册了什么、哪些检查与该实例有关、查询接受哪些状态,以及这些观测可能已经过去多久。仅仅成功解析到一个地址,并没有自动建立上述全部保证,也没有证明业务请求已经能够完成。 注册记录与健康状态是两回事 catalog 存储注册信息,健康端点再附上检查结果。不加过滤的 /v1/health/service/web 响应,可以包含检查为 critical 的实例。检查失败并不会自动抹去服务注册;显式注销、配置了持续 critical 后自动移除,属于不同的生命周期机制。ACL 也可能影响读者能看到哪些记录,所以查询里缺少实例,不能只归因于健康检查失败。 注册的检查通常从 critical 开始,除非显式提供初始状态。但这并不意味着每个注册服务都一定具有有意义的就绪检查。判断某个服务实例时,需要结合它自己的服务级检查,以及 serfHealth 等节点级检查。同一节点上,数据库服务的检查失败,不会自动让不相关的 Web 服务检查失败;节点级检查变为 critical,则会影响该节点上的服务。不要把“相关检查全部通过”误解成“这台机器上的所有服务检查都必须通过”。 检查结果也不只是布尔值。脚本退出码零表示 passing,一表示 warning,其他退出码表示 critical;HTTP 检查按重定向处理后的响应判断:2xx 为 passing,429 为 warning,其他最终响应表示失败。默认会跟随重定向,除非设置 disable_redirects。这些状态究竟证明了什么,仍取决于探测内容。TCP 握手成功或进程存在,并不证明应用能完成一次真实请求;检查实现必须与希望验证的能力对应。 DNS 并非总是只返回 passing HTTP 健康端点的 passing=true 要求相关检查全部 passing。Consul DNS 服务查询的默认策略不同:warning 实例仍可符合候选条件,critical 实例则被排除。配置 dns_config.only_passing=true 后,warning 也会被排除。因此,一个 warning 实例出现在 DNS,却不在 passing-only API 结果里,不一定意味着检查失效,也可能只是两条路径明确采用了不同策略。 ...

四月 6, 2028 · 2 分钟 · XB Field Notes
配置 startup 探针时,启动成功分别启用两条独立支路:readiness 控制 Service 路由资格,liveness 对应容器恢复。

liveness 与 readiness 告诉 Kubernetes Pod 的状态

慢启动不等于进程已死。readiness 与 liveness 分别决定普通 Service 流量是否应该进入这个 Pod,以及终止容器是否有助于恢复,两项决策相互独立。readiness 失败不会暂停 liveness;需要配置 startup 探针,才能在启动阶段抑制另外两种检查。只把接口分成两个名字,不能自动解决这个时序问题。 本文关注健康信号的选择与接线错误的诊断。关键是每次检查实际测到了什么,而不是 URL 名称。共用一个接口可以合理;共用会因下游抖动而失败的检查,并据此触发不必要的重启,却可能扩大故障。设计时应验证具体故障模式与预期恢复动作,不能假定有两个接口就天然安全,也不能把“还没准备好”直接解释成“需要杀死重来”。 普通 Service 路由异步收敛;已有连接与 Pod 直连需要另行考虑。 Readiness 把流量挡在门外 连续 readiness 失败达到阈值,会让 Pod 失去普通 Service 路由资格,但 Pod 仍在运行,好让进程完成热身或自行恢复。端点条件与数据路径在失败、恢复两个方向都异步收敛;已有连接和 Pod 直连需要分别考虑。就绪失败不直接触发探针重启,却可能移除全部服务容量,不能无条件称为安全:缓存可以慢慢热,迁移可以跑完,下游依赖可以回来,全程不丢 Pod 的内存状态,也不付重启的代价。 ...

七月 14, 2027 · 1 分钟 · XB Field Notes
启动门闩把就绪流量资格与存活重启处理作为两个独立分支放行。

探针告诉平台何时出手

探针结果是控制循环使用的证据,不是平台对应用健康的直接理解。Kubernetes 不会从 healthz 这个路径名称推断你希望怎样恢复服务;真正决定下一步的是探针类型、结果、阈值与容器生命周期。把每次失败都描述成“重启 Pod”,会抹掉直接影响可用性的关键区别。 三个问题,对应不同动作 启动探针为初始化提供独立的检测政策。配置后,在它成功之前,存活和就绪探针都不会执行。启动探针成功后,在当前容器生命周期内便不再持续检查;如果容器重新启动,则需要再次通过启动阶段,不能把上一次成功沿用到新生命周期。 存活检查用于识别适合通过重启当前容器恢复的状态。达到失败阈值后,kubelet 终止受到影响的容器,并应用对应的重启政策。这不是保证重建整个 Pod、改变其身份或修复外部数据库,也不意味着容器之间的依赖与在途工作都能自动安全恢复。 就绪失败则让容器继续运行,并持续检查是否恢复。它影响通常按就绪状态选择目标的 Service 流量,但不是防火墙,也不会取消已经通过连接到达的请求。直接访问实例的客户端和现有连接,仍需要自己的生命周期处理,不能把就绪状态误读成网络阻断保证。 阈值统计连续观察结果 failureThreshold 为三,不是从启动以来累计失败三次就动作,而是连续失败达到三次;一次成功会打断这段失败序列。就绪恢复可以要求多次连续成功,而启动和存活探针的 successThreshold 必须为一。阅读结果轨迹之前,应先明确进入失败和恢复成功两个方向的阈值。 超时、初始延迟、执行周期和终止宽限期同样影响实际表现。阈值乘周期可以辅助估算,但不能当成端到端故障切换的精确秒表;调度、探针执行和路由传播都参与其中。容器尚未就绪时,就绪探针还可能比配置周期更频繁地执行,以便更快恢复就绪。 实验选择四次启动失败、三次存活失败、两次就绪失败,并要求连续两次就绪成功才能恢复。这组数字只是为了看清不同计数器的边界,不是生产推荐。真实门槛应结合启动时间、检查成本、错误恢复方式以及误判代价确定,不能照搬实验参数。 检查机制决定你拿到了什么证据 HTTP 检查使用文档定义的 200 至 399 成功范围。即使响应正文写着“内部错误”,返回 200 也不会因为人类读出了坏消息,就自动变成失败探针。应沿实际探测路径检查认证和重定向,而不是默认平台与交互式浏览器具有完全相同的访问结果。 TCP 探针证明的是连接可以打开,不是查询或事务能够完成。exec 检查则需要镜像里确实存在相应命令,并且退出状态有明确含义;频繁创建进程还会消耗节点资源。应该选择能够回答当前问题的低成本机制,而不是认为检查越复杂、调用越多就越可靠。 就绪成功并不是存活执行的前提。没有启动探针隔离时,初始化较长的应用可能还没来得及就绪,就因为存活失败反复被终止。相反,启动容忍窗口过大,也会推迟发现真正无法完成的启动。两边都需要依据实际启动分布和恢复目标权衡。 探针失败与 Unknown 结果不是同一种状态。Kubernetes 文档规定 Unknown 不改变容器状态,之后继续检查。本例只接受成功与失败两个值,故意没有第三种结果,所以无法预测传输错误会如何分类。实际排查应检查 kubelet 事件和部署中的探针处理机制,先确认错误属于哪类,再解释是否应计入连续失败。 坏掉的样子 把外部依赖可用性直接作为存活条件,可能在共享故障期间不断重启健康进程;另一个独立线程上始终绿色的处理器,又可能遗漏业务工作线程的死锁。重启并不天然便宜,它会中断在途工作、重复初始化,也可能进一步增加故障依赖的压力。 ...

六月 18, 2027 · 3 分钟 · XB Field Notes