我会从底层原理→每个参数的精确含义→常见坑点→生产级配置四个维度把健康探测讲得明明白白。这是K8s实现零故障滚动更新和自动故障恢复的核心90%的生产环境可用性问题都和健康探测配置不当有关。一、先彻底搞懂为什么默认健康检查完全不够用1. K8s默认的健康检查机制K8s天生自带一个最基础的健康检查监控容器的主进程PID。如果主进程退出且退出码≠0就认为容器故障然后根据restartPolicy决定是否重启容器。这个机制的致命缺陷它只能检测进程是否活着完全无法检测服务是否可用。2. 生产环境中90%的故障场景默认机制都检测不到我给你举3个最常见的真实故障故障1应用死锁/内存泄漏现象Java应用进程还在CPU占用100%但所有请求都超时默认机制的表现认为容器正常不会重启后果服务完全不可用直到人工介入故障2应用初始化未完成现象SpringBoot应用启动需要30秒加载配置、连接数据库、初始化缓存但Pod启动1秒后就被标记为Ready默认机制的表现立即把流量转发给这个Pod后果滚动更新时出现大量503错误用户体验极差故障3数据库连接池耗尽现象应用进程正常但所有数据库操作都超时返回500错误默认机制的表现认为容器正常不会重启也不会从负载中移除后果所有请求都失败服务雪崩这就是为什么我们必须配置自定义健康探测的原因健康探测让K8s能够从应用的视角判断服务是否正常而不仅仅是从进程的视角。二、三种健康探测的底层原理与核心区别K8s提供了三种互补的健康探测它们各司其职共同保证服务的可用性。1. 启动探测startupProbe专门解决慢启动问题核心作用一次性探测只在容器启动阶段执行。它的唯一目的是确认应用已经完成初始化可以开始接收流量和其他探测。工作原理容器启动后startupProbe首先开始执行在startupProbe成功之前所有其他探测liveness和readiness都会被完全禁用如果startupProbe在failureThreshold × periodSeconds时间内成功则认为应用启动完成然后启动liveness和readiness探测如果超过这个时间仍然失败则kubelet会杀死容器并根据restartPolicy重启容器解决的核心问题慢启动应用被livenessProbe误杀。举个例子你的SpringBoot应用需要60秒才能启动完成你配置了livenessProbeinitialDelaySeconds30periodSeconds10failureThreshold3那么livenessProbe会在容器启动30秒后开始执行最多再等30秒3×10也就是总共60秒但如果应用启动需要65秒那么在第60秒时livenessProbe会认为应用故障杀死容器然后容器重启进入无限循环永远无法启动成功有了startupProbe之后你可以给startupProbe设置足够长的超时时间比如failureThreshold30periodSeconds5总共150秒只要应用在150秒内启动完成livenessProbe就会正常开始工作如果应用真的启动失败150秒后也会被重启必须配置startupProbe的场景Java应用SpringBoot、SpringCloud.NET应用任何需要加载大量数据或初始化复杂依赖的应用2. 存活性探测livenessProbe检测应用是否活着核心作用持续探测在容器的整个生命周期内执行。它的目的是检测应用是否陷入了无法自愈的故障状态。工作原理容器启动且startupProbe成功后livenessProbe开始按照periodSeconds的间隔定期执行如果连续failureThreshold次探测失败则认为容器故障kubelet会杀死容器并根据restartPolicy决定是否重启容器什么情况应该让livenessProbe失败只有当应用无法自愈必须重启才能恢复时才应该让livenessProbe失败。比如应用死锁内存泄漏导致OOM虽然OOM会直接杀死进程但有些情况下应用会卡住而不退出应用内部错误导致所有请求都失败绝对不要让livenessProbe依赖外部服务如数据库、Redis。如果数据库挂了你的应用不应该被重启因为重启也解决不了问题只会导致所有Pod都被重启加剧故障。3. 就绪性探测readinessProbe检测应用是否能干活核心作用持续探测在容器的整个生命周期内执行。它的目的是检测应用是否已经准备好接收外部流量。工作原理容器启动且startupProbe成功后readinessProbe开始按照periodSeconds的间隔定期执行如果连续failureThreshold次探测失败则认为应用暂时无法提供服务kubelet会将这个Pod的IP从所有对应Service的Endpoint列表中移除不再转发流量给它如果后续探测成功则会将Pod重新加入Endpoint列表恢复流量转发什么情况应该让readinessProbe失败当应用暂时无法提供服务但不需要重启时应该让readinessProbe失败。比如应用正在加载缓存数据库连接池耗尽依赖的下游服务暂时不可用应用正在处理大量请求负载过高readinessProbe是实现优雅滚动更新和流量熔断的核心。4. 三种探针的执行顺序与关系90%的人都搞错了这是最容易混淆的知识点我用一张表给你讲清楚阶段执行的探针其他探针的状态容器刚启动只有startupProbeliveness和readiness被完全禁用startupProbe成功livenessProbe和readinessProbe并发执行两者互不影响互不等待startupProbe失败无容器被杀死并重启官方文档明确说明Liveness probes do not wait for readiness probes to succeed. If you want to wait before executing a liveness probe you should use initialDelaySeconds or a startupProbe.翻译存活性探针不会等待就绪性探针成功。如果你想在执行存活性探针之前等待应该使用initialDelaySeconds或者startupProbe。三、三种探测实现方式的细节与坑点所有探针都支持三种实现方式每种方式都有自己的适用场景和隐藏的坑。1. exec在容器内执行命令原理kubelet会在容器内执行你指定的命令。如果命令的退出码为0则探测成功否则探测失败。适用场景没有HTTP接口的应用如数据库、消息队列需要自定义复杂健康检查逻辑的场景示例livenessProbe:exec:command:-/bin/sh--c-ps aux | grep tomcat | grep -v grepinitialDelaySeconds:20periodSeconds:10timeoutSeconds:5failureThreshold:3超级大坑90%的人都踩过不要用ps aux | grep xxx来做健康检查原因grep命令本身会出现在进程列表中所以即使你的应用已经死了ps aux | grep tomcat也会因为匹配到grep自己而返回退出码0导致探测永远成功无法检测到应用故障正确的写法# 方法1用pgrep推荐command:[pgrep,tomcat]# 方法2给grep加个过滤command:-/bin/sh--c-ps aux | grep tomcat | grep -v grep | wc -l | grep -q ^1$其他注意事项命令执行的超时时间由timeoutSeconds控制默认1秒命令会在容器的默认工作目录下执行命令的输出会被丢弃不会出现在Pod日志中2. TCPSocket尝试建立TCP连接原理kubelet会尝试与容器的指定端口建立TCP连接。如果连接成功建立则探测成功否则探测失败。适用场景数据库MySQL、PostgreSQL缓存Redis、Memcached任何基于TCP的服务示例livenessProbe:tcpSocket:port:3306initialDelaySeconds:30periodSeconds:10timeoutSeconds:5failureThreshold:3坑点TCPSocket只能检测端口是否开放无法检测服务是否正常工作。比如MySQL进程在端口也通但因为权限问题拒绝所有连接Redis进程在端口也通但已经进入只读模式这些情况TCPSocket都会认为探测成功但实际上服务已经不可用。解决方法对于数据库这类服务最好使用exec方式执行一个简单的查询命令来检测服务是否正常livenessProbe:exec:command:-mysql--h-localhost--u-root--p123456--e-SELECT 1initialDelaySeconds:30periodSeconds:10timeoutSeconds:5failureThreshold:33. HTTPGet发送HTTP GET请求原理kubelet会向容器的指定端口和路径发送一个HTTP GET请求。如果响应的状态码在[200, 399]范围内则探测成功否则探测失败。适用场景Web应用RESTful API服务任何提供HTTP接口的服务完整的参数说明livenessProbe:httpGet:path:/actuator/health# 请求路径port:8081# 请求端口可以是端口号或端口名称scheme:HTTP# 协议HTTP或HTTPS默认HTTPhost:localhost# 请求的主机名默认是Pod的IPhttpHeaders:# 自定义请求头-name:Authorizationvalue:Bearer token123initialDelaySeconds:20periodSeconds:5timeoutSeconds:10failureThreshold:3非常重要的细节状态码范围是200-399包括301、302、304等重定向状态码。也就是说如果你的健康检查接口返回302重定向也会被认为是成功的。如果请求超时超过timeoutSeconds则认为探测失败。kubelet会从节点上发起请求而不是从Pod内部。最佳实践对于SpringBoot应用强烈推荐使用Actuator的/actuator/health接口作为健康检查地址。它会自动检查应用的所有依赖数据库、Redis、消息队列等的健康状态。四、所有探针参数的精确含义与调优方法每个探针都有5个通用参数理解每个参数的精确含义是配置出健壮的健康探测的关键。参数精确含义默认值调优建议initialDelaySeconds容器启动后等待多少秒才开始第一次探测0秒- startupProbe根据应用的实际启动时间设置- liveness/readiness如果配置了startupProbe设为0即可periodSeconds两次探测之间的时间间隔10秒- 生产环境建议设为5-10秒- 不要设得太短3秒会增加kubelet和容器的负载- 不要设得太长30秒会导致故障检测不及时timeoutSeconds单次探测的超时时间1秒- HTTP/exec探测建议设为5-10秒- TCP探测建议设为3-5秒- 绝对不要使用默认值1秒网络波动时很容易误判successThreshold连续探测成功多少次才认为容器恢复健康1秒- livenessProbe必须为1K8s强制要求- readinessProbe建议设为1或2让故障恢复的Pod尽快重新接收流量failureThreshold连续探测失败多少次才认为容器故障3次- startupProbe根据应用启动时间设置比如30次30×5150秒- livenessProbe建议设为3次避免网络波动导致的误判- readinessProbe建议设为2次更快地将故障Pod从负载中移除怎么计算应用需要的启动时间一个简单的方法手动启动应用记录从启动到可以正常接收请求的时间给startupProbe设置failureThreshold × periodSeconds 实际启动时间 × 1.5比如你的应用实际启动时间是60秒那么可以设置periodSeconds: 5failureThreshold: 18总共等待时间18×590秒给应用留30秒的余量五、生产环境常见的致命错误配置我见过太多因为健康探测配置不当导致的生产事故这里给你列出最常见的7个错误一定要避免错误1没有配置startupProbe后果慢启动应用被livenessProbe频繁误杀进入无限重启循环。错误2livenessProbe依赖外部服务错误示例# 绝对不要这么写livenessProbe:httpGet:path:/healthport:8080如果/health接口会检查数据库连接那么当数据库挂了的时候所有Pod的livenessProbe都会失败导致所有Pod被重启整个服务雪崩。正确做法livenessProbe只检查应用自身的健康状态不依赖任何外部服务readinessProbe可以检查外部依赖的健康状态错误3livenessProbe和readinessProbe完全相同后果当依赖的外部服务故障时应用会被不断重启而不是暂时从负载中移除。错误4initialDelaySeconds设得太长后果应用已经启动完成但还要等很久才开始探测导致服务不可用时间延长。错误5timeoutSeconds使用默认值1秒后果网络稍微有点波动就会导致探测失败误杀容器或误移除Pod。错误6没有配置readinessProbe后果滚动更新时新Pod还没启动完成就开始接收流量导致大量503错误。错误7过度探测后果过于频繁的探测会消耗大量的CPU和内存资源影响应用的性能。六、生产级健康探测完整示例SpringBoot应用这是我在生产环境中使用的标准配置你可以直接套用apiVersion:v1kind:Podmetadata:name:springboot-productionlabels:app:springbootspec:containers:-name:springbootimage:mydlqclub/springboot-helloworld:0.0.1ports:-name:servercontainerPort:8080# 业务端口-name:managementcontainerPort:8081# 管理端口专门用于健康检查resources:requests:cpu:500mmemory:512Milimits:cpu:2memory:2Gi# 启动探测专门处理慢启动startupProbe:httpGet:path:/actuator/health/liveness# 只检查应用自身是否启动port:8081periodSeconds:5# 每5秒探测一次timeoutSeconds:10# 超时时间10秒failureThreshold:30# 最多重试30次总共等待150秒successThreshold:1# 存活性探测检测应用是否活着livenessProbe:httpGet:path:/actuator/health/liveness# 只检查应用自身的健康状态port:8081periodSeconds:10# 每10秒探测一次timeoutSeconds:5# 超时时间5秒failureThreshold:3# 连续3次失败则重启successThreshold:1# 就绪性探测检测应用是否可以接收流量readinessProbe:httpGet:path:/actuator/health/readiness# 检查所有依赖数据库、Redis等port:8081periodSeconds:5# 每5秒探测一次timeoutSeconds:5# 超时时间5秒failureThreshold:2# 连续2次失败则移除流量successThreshold:1restartPolicy:Always配置说明使用了SpringBoot Actuator的独立的健康检查端点/actuator/health/liveness只检查应用自身是否存活不依赖外部服务/actuator/health/readiness检查所有外部依赖是否正常startupProbe给了足够长的启动时间150秒适合大多数Java应用livenessProbe和readinessProbe分开配置职责明确所有超时时间都设置得比较合理避免误判七、怎么调试健康探测当你的健康探测不工作时可以按照以下步骤排查步骤1查看Pod的事件kubectl describe podspod-name在Events部分你会看到探测失败的详细信息比如Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning Unhealthy 10s kubelet Liveness probe failed: Get http://10.244.121.45:8081/actuator/health: dial tcp 10.244.121.45:8081: connect: connection refused步骤2手动执行探测命令对于exec探测kubectlexec-itpod-name--你的探测命令比如kubectlexec-itspringboot-production --curlhttp://localhost:8081/actuator/health步骤3从节点上测试HTTP/TCP探测kubelet是从节点上发起探测的所以你需要登录到Pod所在的节点上然后测试# 登录到节点sshrootxianchaonode1# 测试HTTP探测curlhttp://pod-ip:8081/actuator/health# 测试TCP探测telnetpod-ip3306八、终极总结默认健康检查完全不够用生产环境必须配置自定义健康探测三种探针各司其职startupProbe解决慢启动问题livenessProbe检测应用是否需要重启readinessProbe检测应用是否可以接收流量三种探测方式各有优劣HTTPGet最准确优先使用exec最灵活适合自定义逻辑TCPSocket最简单但准确性最低合理设置参数根据应用的实际情况调整探测间隔、超时时间和重试次数避免常见坑点不要让livenessProbe依赖外部服务不要使用默认的1秒超时时间健康探测是K8s服务高可用的基石花时间把它配置好能帮你避免90%的生产环境可用性问题。
Pod健康探测终极详解
我会从底层原理→每个参数的精确含义→常见坑点→生产级配置四个维度把健康探测讲得明明白白。这是K8s实现零故障滚动更新和自动故障恢复的核心90%的生产环境可用性问题都和健康探测配置不当有关。一、先彻底搞懂为什么默认健康检查完全不够用1. K8s默认的健康检查机制K8s天生自带一个最基础的健康检查监控容器的主进程PID。如果主进程退出且退出码≠0就认为容器故障然后根据restartPolicy决定是否重启容器。这个机制的致命缺陷它只能检测进程是否活着完全无法检测服务是否可用。2. 生产环境中90%的故障场景默认机制都检测不到我给你举3个最常见的真实故障故障1应用死锁/内存泄漏现象Java应用进程还在CPU占用100%但所有请求都超时默认机制的表现认为容器正常不会重启后果服务完全不可用直到人工介入故障2应用初始化未完成现象SpringBoot应用启动需要30秒加载配置、连接数据库、初始化缓存但Pod启动1秒后就被标记为Ready默认机制的表现立即把流量转发给这个Pod后果滚动更新时出现大量503错误用户体验极差故障3数据库连接池耗尽现象应用进程正常但所有数据库操作都超时返回500错误默认机制的表现认为容器正常不会重启也不会从负载中移除后果所有请求都失败服务雪崩这就是为什么我们必须配置自定义健康探测的原因健康探测让K8s能够从应用的视角判断服务是否正常而不仅仅是从进程的视角。二、三种健康探测的底层原理与核心区别K8s提供了三种互补的健康探测它们各司其职共同保证服务的可用性。1. 启动探测startupProbe专门解决慢启动问题核心作用一次性探测只在容器启动阶段执行。它的唯一目的是确认应用已经完成初始化可以开始接收流量和其他探测。工作原理容器启动后startupProbe首先开始执行在startupProbe成功之前所有其他探测liveness和readiness都会被完全禁用如果startupProbe在failureThreshold × periodSeconds时间内成功则认为应用启动完成然后启动liveness和readiness探测如果超过这个时间仍然失败则kubelet会杀死容器并根据restartPolicy重启容器解决的核心问题慢启动应用被livenessProbe误杀。举个例子你的SpringBoot应用需要60秒才能启动完成你配置了livenessProbeinitialDelaySeconds30periodSeconds10failureThreshold3那么livenessProbe会在容器启动30秒后开始执行最多再等30秒3×10也就是总共60秒但如果应用启动需要65秒那么在第60秒时livenessProbe会认为应用故障杀死容器然后容器重启进入无限循环永远无法启动成功有了startupProbe之后你可以给startupProbe设置足够长的超时时间比如failureThreshold30periodSeconds5总共150秒只要应用在150秒内启动完成livenessProbe就会正常开始工作如果应用真的启动失败150秒后也会被重启必须配置startupProbe的场景Java应用SpringBoot、SpringCloud.NET应用任何需要加载大量数据或初始化复杂依赖的应用2. 存活性探测livenessProbe检测应用是否活着核心作用持续探测在容器的整个生命周期内执行。它的目的是检测应用是否陷入了无法自愈的故障状态。工作原理容器启动且startupProbe成功后livenessProbe开始按照periodSeconds的间隔定期执行如果连续failureThreshold次探测失败则认为容器故障kubelet会杀死容器并根据restartPolicy决定是否重启容器什么情况应该让livenessProbe失败只有当应用无法自愈必须重启才能恢复时才应该让livenessProbe失败。比如应用死锁内存泄漏导致OOM虽然OOM会直接杀死进程但有些情况下应用会卡住而不退出应用内部错误导致所有请求都失败绝对不要让livenessProbe依赖外部服务如数据库、Redis。如果数据库挂了你的应用不应该被重启因为重启也解决不了问题只会导致所有Pod都被重启加剧故障。3. 就绪性探测readinessProbe检测应用是否能干活核心作用持续探测在容器的整个生命周期内执行。它的目的是检测应用是否已经准备好接收外部流量。工作原理容器启动且startupProbe成功后readinessProbe开始按照periodSeconds的间隔定期执行如果连续failureThreshold次探测失败则认为应用暂时无法提供服务kubelet会将这个Pod的IP从所有对应Service的Endpoint列表中移除不再转发流量给它如果后续探测成功则会将Pod重新加入Endpoint列表恢复流量转发什么情况应该让readinessProbe失败当应用暂时无法提供服务但不需要重启时应该让readinessProbe失败。比如应用正在加载缓存数据库连接池耗尽依赖的下游服务暂时不可用应用正在处理大量请求负载过高readinessProbe是实现优雅滚动更新和流量熔断的核心。4. 三种探针的执行顺序与关系90%的人都搞错了这是最容易混淆的知识点我用一张表给你讲清楚阶段执行的探针其他探针的状态容器刚启动只有startupProbeliveness和readiness被完全禁用startupProbe成功livenessProbe和readinessProbe并发执行两者互不影响互不等待startupProbe失败无容器被杀死并重启官方文档明确说明Liveness probes do not wait for readiness probes to succeed. If you want to wait before executing a liveness probe you should use initialDelaySeconds or a startupProbe.翻译存活性探针不会等待就绪性探针成功。如果你想在执行存活性探针之前等待应该使用initialDelaySeconds或者startupProbe。三、三种探测实现方式的细节与坑点所有探针都支持三种实现方式每种方式都有自己的适用场景和隐藏的坑。1. exec在容器内执行命令原理kubelet会在容器内执行你指定的命令。如果命令的退出码为0则探测成功否则探测失败。适用场景没有HTTP接口的应用如数据库、消息队列需要自定义复杂健康检查逻辑的场景示例livenessProbe:exec:command:-/bin/sh--c-ps aux | grep tomcat | grep -v grepinitialDelaySeconds:20periodSeconds:10timeoutSeconds:5failureThreshold:3超级大坑90%的人都踩过不要用ps aux | grep xxx来做健康检查原因grep命令本身会出现在进程列表中所以即使你的应用已经死了ps aux | grep tomcat也会因为匹配到grep自己而返回退出码0导致探测永远成功无法检测到应用故障正确的写法# 方法1用pgrep推荐command:[pgrep,tomcat]# 方法2给grep加个过滤command:-/bin/sh--c-ps aux | grep tomcat | grep -v grep | wc -l | grep -q ^1$其他注意事项命令执行的超时时间由timeoutSeconds控制默认1秒命令会在容器的默认工作目录下执行命令的输出会被丢弃不会出现在Pod日志中2. TCPSocket尝试建立TCP连接原理kubelet会尝试与容器的指定端口建立TCP连接。如果连接成功建立则探测成功否则探测失败。适用场景数据库MySQL、PostgreSQL缓存Redis、Memcached任何基于TCP的服务示例livenessProbe:tcpSocket:port:3306initialDelaySeconds:30periodSeconds:10timeoutSeconds:5failureThreshold:3坑点TCPSocket只能检测端口是否开放无法检测服务是否正常工作。比如MySQL进程在端口也通但因为权限问题拒绝所有连接Redis进程在端口也通但已经进入只读模式这些情况TCPSocket都会认为探测成功但实际上服务已经不可用。解决方法对于数据库这类服务最好使用exec方式执行一个简单的查询命令来检测服务是否正常livenessProbe:exec:command:-mysql--h-localhost--u-root--p123456--e-SELECT 1initialDelaySeconds:30periodSeconds:10timeoutSeconds:5failureThreshold:33. HTTPGet发送HTTP GET请求原理kubelet会向容器的指定端口和路径发送一个HTTP GET请求。如果响应的状态码在[200, 399]范围内则探测成功否则探测失败。适用场景Web应用RESTful API服务任何提供HTTP接口的服务完整的参数说明livenessProbe:httpGet:path:/actuator/health# 请求路径port:8081# 请求端口可以是端口号或端口名称scheme:HTTP# 协议HTTP或HTTPS默认HTTPhost:localhost# 请求的主机名默认是Pod的IPhttpHeaders:# 自定义请求头-name:Authorizationvalue:Bearer token123initialDelaySeconds:20periodSeconds:5timeoutSeconds:10failureThreshold:3非常重要的细节状态码范围是200-399包括301、302、304等重定向状态码。也就是说如果你的健康检查接口返回302重定向也会被认为是成功的。如果请求超时超过timeoutSeconds则认为探测失败。kubelet会从节点上发起请求而不是从Pod内部。最佳实践对于SpringBoot应用强烈推荐使用Actuator的/actuator/health接口作为健康检查地址。它会自动检查应用的所有依赖数据库、Redis、消息队列等的健康状态。四、所有探针参数的精确含义与调优方法每个探针都有5个通用参数理解每个参数的精确含义是配置出健壮的健康探测的关键。参数精确含义默认值调优建议initialDelaySeconds容器启动后等待多少秒才开始第一次探测0秒- startupProbe根据应用的实际启动时间设置- liveness/readiness如果配置了startupProbe设为0即可periodSeconds两次探测之间的时间间隔10秒- 生产环境建议设为5-10秒- 不要设得太短3秒会增加kubelet和容器的负载- 不要设得太长30秒会导致故障检测不及时timeoutSeconds单次探测的超时时间1秒- HTTP/exec探测建议设为5-10秒- TCP探测建议设为3-5秒- 绝对不要使用默认值1秒网络波动时很容易误判successThreshold连续探测成功多少次才认为容器恢复健康1秒- livenessProbe必须为1K8s强制要求- readinessProbe建议设为1或2让故障恢复的Pod尽快重新接收流量failureThreshold连续探测失败多少次才认为容器故障3次- startupProbe根据应用启动时间设置比如30次30×5150秒- livenessProbe建议设为3次避免网络波动导致的误判- readinessProbe建议设为2次更快地将故障Pod从负载中移除怎么计算应用需要的启动时间一个简单的方法手动启动应用记录从启动到可以正常接收请求的时间给startupProbe设置failureThreshold × periodSeconds 实际启动时间 × 1.5比如你的应用实际启动时间是60秒那么可以设置periodSeconds: 5failureThreshold: 18总共等待时间18×590秒给应用留30秒的余量五、生产环境常见的致命错误配置我见过太多因为健康探测配置不当导致的生产事故这里给你列出最常见的7个错误一定要避免错误1没有配置startupProbe后果慢启动应用被livenessProbe频繁误杀进入无限重启循环。错误2livenessProbe依赖外部服务错误示例# 绝对不要这么写livenessProbe:httpGet:path:/healthport:8080如果/health接口会检查数据库连接那么当数据库挂了的时候所有Pod的livenessProbe都会失败导致所有Pod被重启整个服务雪崩。正确做法livenessProbe只检查应用自身的健康状态不依赖任何外部服务readinessProbe可以检查外部依赖的健康状态错误3livenessProbe和readinessProbe完全相同后果当依赖的外部服务故障时应用会被不断重启而不是暂时从负载中移除。错误4initialDelaySeconds设得太长后果应用已经启动完成但还要等很久才开始探测导致服务不可用时间延长。错误5timeoutSeconds使用默认值1秒后果网络稍微有点波动就会导致探测失败误杀容器或误移除Pod。错误6没有配置readinessProbe后果滚动更新时新Pod还没启动完成就开始接收流量导致大量503错误。错误7过度探测后果过于频繁的探测会消耗大量的CPU和内存资源影响应用的性能。六、生产级健康探测完整示例SpringBoot应用这是我在生产环境中使用的标准配置你可以直接套用apiVersion:v1kind:Podmetadata:name:springboot-productionlabels:app:springbootspec:containers:-name:springbootimage:mydlqclub/springboot-helloworld:0.0.1ports:-name:servercontainerPort:8080# 业务端口-name:managementcontainerPort:8081# 管理端口专门用于健康检查resources:requests:cpu:500mmemory:512Milimits:cpu:2memory:2Gi# 启动探测专门处理慢启动startupProbe:httpGet:path:/actuator/health/liveness# 只检查应用自身是否启动port:8081periodSeconds:5# 每5秒探测一次timeoutSeconds:10# 超时时间10秒failureThreshold:30# 最多重试30次总共等待150秒successThreshold:1# 存活性探测检测应用是否活着livenessProbe:httpGet:path:/actuator/health/liveness# 只检查应用自身的健康状态port:8081periodSeconds:10# 每10秒探测一次timeoutSeconds:5# 超时时间5秒failureThreshold:3# 连续3次失败则重启successThreshold:1# 就绪性探测检测应用是否可以接收流量readinessProbe:httpGet:path:/actuator/health/readiness# 检查所有依赖数据库、Redis等port:8081periodSeconds:5# 每5秒探测一次timeoutSeconds:5# 超时时间5秒failureThreshold:2# 连续2次失败则移除流量successThreshold:1restartPolicy:Always配置说明使用了SpringBoot Actuator的独立的健康检查端点/actuator/health/liveness只检查应用自身是否存活不依赖外部服务/actuator/health/readiness检查所有外部依赖是否正常startupProbe给了足够长的启动时间150秒适合大多数Java应用livenessProbe和readinessProbe分开配置职责明确所有超时时间都设置得比较合理避免误判七、怎么调试健康探测当你的健康探测不工作时可以按照以下步骤排查步骤1查看Pod的事件kubectl describe podspod-name在Events部分你会看到探测失败的详细信息比如Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning Unhealthy 10s kubelet Liveness probe failed: Get http://10.244.121.45:8081/actuator/health: dial tcp 10.244.121.45:8081: connect: connection refused步骤2手动执行探测命令对于exec探测kubectlexec-itpod-name--你的探测命令比如kubectlexec-itspringboot-production --curlhttp://localhost:8081/actuator/health步骤3从节点上测试HTTP/TCP探测kubelet是从节点上发起探测的所以你需要登录到Pod所在的节点上然后测试# 登录到节点sshrootxianchaonode1# 测试HTTP探测curlhttp://pod-ip:8081/actuator/health# 测试TCP探测telnetpod-ip3306八、终极总结默认健康检查完全不够用生产环境必须配置自定义健康探测三种探针各司其职startupProbe解决慢启动问题livenessProbe检测应用是否需要重启readinessProbe检测应用是否可以接收流量三种探测方式各有优劣HTTPGet最准确优先使用exec最灵活适合自定义逻辑TCPSocket最简单但准确性最低合理设置参数根据应用的实际情况调整探测间隔、超时时间和重试次数避免常见坑点不要让livenessProbe依赖外部服务不要使用默认的1秒超时时间健康探测是K8s服务高可用的基石花时间把它配置好能帮你避免90%的生产环境可用性问题。