Kubernetes 三大探针详解
Kubernetes 提供了多种探针:
容器探针
probe 是由 kubelet 对容器执行的定期诊断。 要执行诊断,kubelet 既可以在容器内执行代码,也可以发出一个网络请求。
检查机制
使用探针来检查容器有四种不同的方法。 每个探针都必须准确定义为这四种机制中的一种:
exec在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
grpc使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC 健康检查。 如果响应的状态是 "SERVING",则认为诊断成功。
httpGet对容器的 IP 地址上指定端口和路径执行 HTTP
GET请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。tcpSocket对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。 如果远程系统(容器)在打开连接后立即将其关闭,这算作是健康的。
注意: 和其他机制不同,exec 探针的实现涉及每次执行时创建/复制多个进程。 因此,在集群中具有较高 pod 密度、较低的 initialDelaySeconds 和 periodSeconds 时长的时候, 配置任何使用 exec 机制的探针可能会增加节点的 CPU 负载。 这种场景下,请考虑使用其他探针机制以避免额外的开销。
探测结果
每次探测都将获得以下三种结果之一:
Success(成功)容器通过了诊断。
Failure(失败)容器未通过诊断。
Unknown(未知)诊断失败,因此不会采取任何行动。
探测类型
针对运行中的容器,kubelet 可以选择是否执行以下三种探针,以及如何针对探测结果作出反应:
livenessProbe指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为
Success。readinessProbe指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为
Failure。 如果容器不提供就绪态探针,则默认状态为Success。startupProbe指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,
kubelet将杀死容器, 而容器依其重启策略进行重启。 如果容器没有提供启动探测,则默认状态为Success。
如欲了解如何设置存活态、就绪态和启动探针的进一步细节, 可以参阅配置存活态、就绪态和启动探针。
探针类型
存活探针(livenessProbe)
存活探针决定何时重启容器。 例如,当应用在运行但无法取得进展时,存活探针可以捕获这类死锁。
如果一个容器的存活探针失败多次,kubelet 将重启该容器。
存活探针不会等待就绪探针成功。 如果你想在执行存活探针前等待,你可以定义 initialDelaySeconds,或者使用启动探针。
就绪探针(readinessProbe)
就绪探针决定何时容器准备好开始接受流量。 这种探针在等待应用执行耗时的初始任务时非常有用,例如建立网络连接、加载文件和预热缓存。
如果就绪探针返回的状态为失败,Kubernetes 会将该 Pod 从所有对应服务的端点中移除。
就绪探针在容器的整个生命期内持续运行。
启动探针(startupProbe)
启动探针检查容器内的应用是否已启动。 启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被 kubelet 杀掉。
如果配置了这类探针,它会禁用存活检测和就绪检测,直到启动探针成功为止。
这类探针仅在启动时执行,不像存活探针和就绪探针那样周期性地运行。
示例
存活探针(livenessProbe)
存活指针,判断Pod(中的应用容器)是否健康,可以理解为健康检查。我们使用livenessProbe来定期的去探测,如果探测成功,则Pod状态可以判定为Running;如果探测失败,可kubectl会根据Pod的重启策略来重启容器。
如果未给Pod设置livenessProbe,则默认探针永远返回Success。
当我们执行kubectl get pods命令,输出信息中STATUS一列我们可以看到Pod是否处于Running状态。
存活探针 - exec命令检查
cat > ss.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: busybox:latest
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
EOF
参数说明
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy
#创建一个文件,30s后删除,在此期间会通过live不断检查这个heal文件是否存在
livenessProbe: #存活检查
exec: #方法为exec 执行命令
command: #命令多个操作以- 开头
- cat
- /tmp/healthy
initialDelaySeconds: 5
#指定容器启动5s后开始执行liveness检测,
#一般按照服务的特性来调整
#比如一个服务启动需要30s,那么这个值就应该大于30
periodSeconds: 5
#指定每5s执行一个liveness检测。
#如果连续执行3此liveness检测均失败
#则会杀死容器,重启
部署
[root@k8s-master01 ~]# kubectl create -f ss.yaml
pod/liveness-exec created查看
[root@k8s-master01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 3 4m31s
#可以看到pod的状态,以及重新启动
#这是因为pod在创建后在执行commnd命令创建了/tmp/healthy文件
#liveness在pod创建成功5s后开始检查/tmp/healthy文件是否存在,每5s检测一次
#30s后文件被删除,检测不到文件3次后表示失败,根据默认重启规则重启了pod容器存活探针 - HTTP协议
containers:
- name: xxx
image: xxx
# 存活检查
livenessProbe:
httpGet:
scheme: HTTP # 协议
path: /actuator/health # 路径
port: 8080 # 端口
initialDelaySeconds: 30 # 延迟探测时间(秒) 【 在k8s第一次探测前等待秒 】
periodSeconds: 10 # 执行探测频率(秒) 【 每隔秒执行一次 】
timeoutSeconds: 1 # 超时时间
successThreshold: 1 # 健康阈值
failureThreshold: 3 # 不健康阈值存活探针 - TCP协议
containers:
- name: xxx
image: xxx
# 存活检查
livenessProbe:
tcpSocket: # TCP
port: 8090 # 端口
initialDelaySeconds: 50 # 延迟探测时间(秒) 【 在k8s第一次探测前等待秒 】
periodSeconds: 10 # 执行探测频率(秒) 【 每隔秒执行一次 】
timeoutSeconds: 1 # 超时时间
successThreshold: 1 # 健康阀值
failureThreshold: 3 # 不健康阀值 就绪探针(readinessProbe)
就绪指针,就绪的意思是已经准备好了,Pod的就绪我们可以理解为这个Pod可以接受请求和访问。我们使用readinessProbe来定期的去探测,如果探测成功,则Pod 的Ready状态判定为True;如果探测失败,Pod的Ready状态判定为False。
与livenessProbe不同的是,kubelet不会对readinessProbe的探测情况有重启操作。
当我们执行kubectl get pods命令,输出信息中READY一列我们可以看到Pod的READY状态是否为True。
HTTP协议和TCP协议配置方法和存活探测相同(如上,这里只列出一个HTTP协议的)
containers:
- name: xxx
image: xxx
# 就绪检查
readinessProbe:
httpGet:
scheme: HTTP # 协议
path: /actuator/health # 路径
port: 8080 # 端口
initialDelaySeconds: 30 # 延迟探测时间(秒)【 在k8s第一次探测前等待秒 】
periodSeconds: 2 # 执行探测频率(秒) 【 每隔秒执行一次 】
timeoutSeconds: 1 # 超时时间
successThreshold: 1 # 健康阈值,成功1次认为可用
failureThreshold: 3 # 不健康阈值,失败3次认为不可用一般就绪探针会在启动容器一段时间后才开始第一次的就绪探测,之后做周期性探测。所以在定义就绪指针时,会给以下几个参数:
initialDelaySeconds: 在初始化容器多少秒后开始第一次就绪探测;
timeoutSeconds: 如果该次就绪探测超过多少秒后还未成功,判定为超时,该次探测失败,Pod不就绪。默认值1,最小值1;
periodSeconds: 如果Pod未就绪,则每隔多少秒周期性的做就绪探测。默认值10,最小值1;
failureThreshold: 如果容器之前探测成功,后续连续几次探测失败,则确定容器未就绪。默认值3,最小值1;
successThreshold: 如果容器之前探测失败,后续连续几次探测成功,则确定容器就绪。默认值1,最小值1。启动探针(startupProbe)
有时候,会有一些现有的应用在启动时需要较长的初始化时间。 在这种情况下,若要不影响对死锁作出快速响应的探测,设置存活探测参数是要技巧的。 解决办法是使用相同的命令来设置启动探测,针对 HTTP 或 TCP 检测,可以通过将 failureThreshold * periodSeconds 参数设置为足够长的时间来应对最糟糕情况下的启动时间。
这样,前面的例子就变成了:
ports:
- name: liveness-port
containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 10
startupProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 30
periodSeconds: 10幸亏有启动探测,应用将会有最多 5 分钟(30 * 10 = 300s)的时间来完成其启动过程。 一旦启动探测成功一次,存活探测任务就会接管对容器的探测,对容器死锁作出快速响应。 如果启动探测一直没有成功,容器会在 300 秒后被杀死,并且根据 restartPolicy 来执行进一步处置。
配置就绪探针和存活探针
livenessProbe:
failureThreshold: 60
initialDelaySeconds: 10
periodSeconds: 5
successThreshold: 1
httpGet:
path: /actuator/health
port: 10000
timeoutSeconds: 5
name: open-gateway-test
readinessProbe:
failureThreshold: 60
initialDelaySeconds: 10
periodSeconds: 5
successThreshold: 1
httpGet:
path: /actuator/health
port: 10000
timeoutSeconds: 5解析
这段 YAML 配置是针对 Kubernetes 中的 Pod 的 liveness 和 readiness 探针进行设置的。livenessProbe 用于检测容器是否存活,readinessProbe 用于检测容器是否准备好接收流量。
让我们逐个解释每个字段的含义:
livenessProbe:定义 liveness 探针的设置。failureThreshold:在连续多少次检测失败后触发失败,默认是 3 次。initialDelaySeconds:从容器启动后多少秒开始进行第一次检测。periodSeconds:每隔多少秒进行一次检测。successThreshold:在连续多少次检测成功后,将失败状态重置为成功状态,默认是 1 次。httpGet:使用 HTTP GET 请求来检测容器的健康状态。path:请求的路径,一般是用于检查应用程序健康的接口。port:容器内监听的端口号。
timeoutSeconds:请求的超时时间。
readinessProbe:定义 readiness 探针的设置,与 liveness 探针类似。failureThreshold、initialDelaySeconds、periodSeconds、successThreshold:与 liveness 相同。httpGet:与 liveness 的httpGet配置类似,用于检查容器是否准备好接收流量。
这些配置的目的是确保容器在运行时能够保持健康状态并处理流量,以及确保容器准备好接收流量。如果探针检测失败达到阈值,则容器可能会被 Kubernetes 重新启动或标记为不可用,这有助于维护应用程序的可用性和稳定性。
通过 kubectl get pods pod名字 -o wide 可以查看到 pod 的 status ,包含重启次数以及state,如
kubectl -n cloud-dev get pods open-gateway-test-8585c5c8b4-9zpjs -o yamloutput
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2023-08-04T03:11:30Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2023-08-04T03:11:30Z"
message: 'containers with unready status: [open-gateway-test]'
reason: ContainersNotReady
status: "False"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2023-08-04T03:11:30Z"
message: 'containers with unready status: [open-gateway-test]'
reason: ContainersNotReady
status: "False"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2023-08-04T03:11:30Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://019f4b89878fc029840e836f8f350559211e5c33cd091d17fa315123464904e4
image: swr.cn-east-2.myhuaweicloud.com/cloudhos/cloud-dev/2.0/open-gateway_test:14
imageID: docker-pullable://swr.cn-east-2.myhuaweicloud.com/cloudhos/cloud-dev/2.0/open-gateway_test@sha256:6a048dfd05a2f09b60d554eac2f165689f1e3d0ccdda0add5e58659fdac70295
lastState:
terminated:
containerID: docker://019f4b89878fc029840e836f8f350559211e5c33cd091d17fa315123464904e4
exitCode: 143
finishedAt: "2023-08-04T03:36:15Z"
reason: Error
startedAt: "2023-08-04T03:34:36Z"
name: open-gateway-test
ready: false
restartCount: 9
started: false
state:
waiting:
message: back-off 5m0s restarting failed container=open-gateway-test pod=open-gateway-test-8585c5c8b4-9zpjs_cloud-dev(ac8722c8-d7be-4f20-a809-2198acbb253c)
reason: CrashLoopBackOff
hostIP: 192.168.1.3
phase: Running
podIP: 10.42.16.226
podIPs:
- ip: 10.42.16.226
qosClass: Burstable
startTime: "2023-08-04T03:11:30Z"