探针概述

探针是有 kubelet 对容器执行的定期诊断,并不是由 Master 节点发起的探测,而是由每一个 Node 所在的 kubelet 进行探测,这样可以减轻 Master 节点系统负载压力。

探针方式

liveness Probe

是一个存活探测器,会随着 Pod 生命周期一直循环检测。探测容器是否正在运行,如果存活探测失败,则 kubelet 会杀死容器,然后根据其容器的​​重启策略​​来对容器进行操作,默认为 Always,则 Pod 进行重启。

readiness Probe

是一个就绪探测器,检测 Pod 是否到达就绪状态,只有达到就绪状态了才可以对外提供服务,当一个 Pod 内的所有容器都准备好了,才能把这个 Pod 看作就绪了。探针可以让 kubelet 知道应用程序何时准备接受新流量。如果应用程序在进程启动后需要一些时间来初始化状态,要配置 readiness 探针让 Kubernetes 在发送新流量之前进行等待。readiness 探针的主要作用是将流量引导至 service 后的 deployment。

就绪探针可以应用在 Service 后端的 Pod 探测上,在 Pod 还没有准备好的时候,会从 Service 的负载均衡器中剔除。

startup Probe

1.16版本后加入,判断容器内的应用程序是否已启动。如果提供了启动探测,则禁用所有其他探测,直到它成功为止。如果启动探测失败,kubelet将杀死容器,容器将服从其重启策略。如果容器没有提供启动探测,则默认状态为成功。

应用场景:

比如服务A启动时间很慢,需要60s。这个时候如果还是用上面的探针就会进入死循环,因为上面的探针10s后就开始探测,这时候我们服务并没有起来,发现探测失败就会触发restartPolicy。这时候有的朋友可能会想到把​​initialDelay​​调成60s不就可以了?但是我们并不能保证这个服务每次起来都是60s,假如新的版本起来要70s,甚至更多的时间,我们就不好控制了

三种探针均支持的参数

  • ​initialDelaySeconds​​:启动 liveness、readiness 探针前要等待的秒数。
  • ​periodSeconds​​:检查探针的频率。
  • ​timeoutSeconds​​:将探针标记为超时(未通过运行状况检查)之前的秒数。
  • ​successThreshold​​:探针需要通过的最小连续成功检查数量。
  • ​failureThreshold​​:将探针标记为失败之前的重试次数。对于 liveness 探针,这将导致 Pod 重新启动。对于 readiness 探针,将标记 Pod 为未就绪(unready)。

三种探针支持的方式

kubelet 要执行诊断,kubelet 调用由容器实现的 Handler (处理程序)。一共有三种类型的处理程序:

  • ExecAction: 在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功,非 0 都属于不成功。
  • TCPSocketAction: 对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。
  • HTTPGetAction: 对容器的 IP 地址上指定端口和路径执行 HTTP Get 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。

每次探测都将获得以下三种结果之一:

  • ​Success​​(成功):容器通过了诊断。
  • ​Failure​​(失败):容器未通过诊断。
  • ​Unknown​​(未知):诊断失败,因此不会采取任何行动

exec

通过在容器内执行指定命令,来判断命令退出时返回的状态码,如果为 0 表示正常。

startupProbe:
failureThreshold: 3
exec:
command: ['/bin/sh','-c','echo Hello World']
initialDelaySeconds: 20
periodSeconds: 3
successThreshold: 1
timeoutSeconds: 2

​httpGet

通过对容器的 IP 地址、端口和 URL 路径来发送 GET 请求;如果响应的状态码在 200 ~ 399 间,表示正常

livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: 8080
scheme: HTTP # 可以使用 HTTP 或 HTTPS 方式
initialDelaySeconds: 20
periodSeconds: 3
successThreshold: 1
timeoutSeconds: 2

tcpSocket

通过对容器的 IP 地址和指定端口,进行 TCP 检查,如果端口打开,表示正常。

readinessProbe:
failureThreshold: 3
tcpSocket:
port: 8080
initialDelaySeconds: 20
periodSeconds: 3
successThreshold: 1
timeoutSeconds: 2

案例解说

livenessProbe:
httpGet:
path: /test
prot: 80
failureThreshold: 1 #允许失败的次数
initialDelay:10 #容器启动后多久启动探针
periodSeconds: 10 #探针检测频率

容器启动10s后每10s检查一次,允许失败的次数是1次。如果失败次数超过1则会触发restartPolicy。

但是有时候会存在特殊情况,比如服务A启动时间很慢,需要60s。这个时候如果还是用上面的探针就会进入死循环,因为上面的探针10s后就开始探测,这时候我们服务并没有起来,发现探测失败就会触发restartPolicy。这时候有的朋友可能会想到把​​initialDelay​​调成60s不就可以了?但是我们并不能保证这个服务每次起来都是60s,假如新的版本起来要70s,甚至更多的时间,我们就不好控制了。有的朋友可能还会想到把失败次数增加,比如下面配置:

livenessProbe:
httpGet:
path: /test
prot: 80
failureThreshold: 5
initialDelay:60
periodSeconds: 10

这在启动的时候是可以解决我们目前的问题,但是如果这个服务挂了呢?如果​​failureThreshold=1​​​则10s后就会报警通知服务挂了,如果设置了​​failureThreshold=5​​,那么就需要​​5*10s=50s​​的时间,在现在大家追求快速发现、快速定位、快速响应的时代是不被允许的。

在这时候我们把​startupProbe​​livenessProbe​结合起来使用就可以很大程度上解决我们的问题。

livenessProbe:
httpGet:
path: /test
prot: 80
failureThreshold: 1
initialDelay:10
periodSeconds: 10

startupProbe:
httpGet:
path: /test
prot: 80
failureThreshold: 10
initialDelay:10
periodSeconds: 10

上面的配置是只有​startupProbe​探测成功后再交给​livenessProbe​。我们​startupProbe​配置的是10s*10+10s,也就是说只要应用在110s内启动都是OK的,而且应用挂掉了10s就会发现问题。