Kubernetes Pod 健康检查机制 LivenessProbe 与 ReadinessProbe
系统环境:
- kubernetes 版本:1.14.0
Kubernetes 官方文档地址:
一、Pod 的整个生命阶段
- Pending: 正在创建 Pod,但是 Pod 中的容器还没有全部被创建完成,这其中也包含集群为容器创建网络,或者下载镜像的过程。
- Running: Pod 内所有的容器都已经被创建,且至少一个容器正在处于运行状态、正在启动状态或者重启状态。
- Succeeded: Pod 中所有容器都执行成功后退出,并且没有处于重启的容器。
- Failed: Pod 中所有容器都已退出,但是至少还有一个容器退出时为失败状态。
- Unknown: 由于一些原因,Pod 的状态无法获取,通常是与 Pod 通信时出错导致的。
二、Pod 重启策略
- Always: 只要容器失效退出就重新启动容器。
- OnFailure: 当容器以非正常退出后重新启动容器。
- Never: 无论容器状态如何,都不重新启动容器。
如果 restartpolicy 没有设置,那么默认值是 Always。RC 和 DaemonSet 必须指定重启策略为 Always。
三、Pod 常见状态转换场景
Pod中的容器数 | Pod状态 | 发生事件 | 不同重启策略下的结果状态 | ||
---|---|---|---|---|---|
Always | OnFailure | Never | |||
包含一个容器 | Running | 容器成功退出 | Running | Succeeded | Succeeded |
包含一个容器 | Running | 容器失败退出 | Running | Running | Failed |
包含两个容器 | Running | 1个容器失败退出 | Running | Running | Running |
包含两个容器 | Running | 容器内存溢出挂掉 | Running | Running | Failed |
四、Pod 的活性与就绪探针
1、Pod 探针机制
在 Kubernetes 中 Pod 是最小的计算单元,而一个 Pod 又由多个容器组成,相当于每个容器就是一个应用,应用在运行期间,可能因为某也意外情况致使程序挂掉。那么如何监控这些容器状态稳定性,保证服务在运行期间不会发生问题,发生问题后进行重启等机制,就成为了重中之重的事情,考虑到这点 kubernetes 推出了活性探针机制。
有了活性探针后能保证程序在运行中如果挂掉能够自动重启,但是还有个经常遇到的问题,比如说,在 Kubernetes 中启动 Pod,显示明明 Pod 已经启动成功,且能访问里面的端口,但是却返回错误信息。还有就是在执行滚动更新时候,总会出现一段时间,Pod 对外提供网络访问,但是访问却发生 404,这两个原因,都是因为 Pod 已经成功启动,但是 Pod 的的容器中应用程序还在启动中导致,考虑到这点 Kubernetes 推出了就绪探针机制。
2、Pod 两种探针简介
- LivenessProbe(存活探针): 存活探针主要作用是,用指定的方式进入容器检测容器中的应用是否正常运行,如果检测失败,则认为容器不健康,那么
Kubelet
将根据Pod
中设置的restartPolicy
(重启策略)来判断,Pod 是否要进行重启操作,如果容器配置中没有配置livenessProbe
存活探针,Kubelet
将认为存活探针探测一直为成功状态。 - ReadinessProbe(就绪探针): 用于判断容器中应用是否启动完成,当探测成功后才使 Pod 对外提供网络访问,设置容器
Ready
状态为true
,如果探测失败,则设置容器的Ready
状态为false
。对于被 Service 管理的 Pod,Service
与Pod
、EndPoint
的关联关系也将基于 Pod 是否为Ready
状态进行设置,如果 Pod 运行过程中Ready
状态变为false
,则系统自动从Service
关联的EndPoint
列表中移除,如果 Pod 恢复为Ready
状态。将再会被加回Endpoint
列表。通过这种机制就能防止将流量转发到不可用的 Pod 上。
3、Pod 探针的探测方式与结果
目前 LivenessProbe 和 ReadinessProbe 两种探针都支持下面三种探测方法:
- ExecAction: 在容器中执行指定的命令,如果能成功执行,则探测成功。
- HTTPGetAction: 通过容器的IP地址、端口号及路径调用 HTTP Get 方法,如果响应的状态码 200 ≤ status ≤ 400,则认为容器探测成功。
- TCPSocketAction: 通过容器的 IP 地址和端口号执行 TCP 检查,如果能够建立 TCP 连接,则探测成功。
探针探测结果有以下值:
- Success:表示通过检测。
- Failure:表示未通过检测。
- Unknown:表示检测没有正常进行。
4、Pod 探针的相关属性
两种探针有许多可选字段,可以用来更加精确的控制 LivenessProbe 和 ReadinessProbe 两种探针的探测,具体如下:
- initialDelaySeconds: Pod 启动后首次进行检查的等待时间,单位“秒”。
- periodSeconds: 检查的间隔时间,默认为 10s,单位“秒”。
- timeoutSeconds: 探针执行检测请求后,等待响应的超时时间,默认为 1s,单位“秒”。
- successThreshold: 探针检测失败后认为成功的最小连接成功次数,默认为 1s,在 Liveness 探针中必须为 1s,最小值为 1s。
- failureThreshold: 探测失败的重试次数,重试一定次数后将认为失败,在 readiness 探针中,Pod会被标记为未就绪,默认为 3s,最小值为 1s。
5、两种探针的区别
总的来说 ReadinessProbe 和 LivenessProbe 是使用相同探测的方式,只是探测后对 Pod 的处置方式不同:
- ReadinessProbe: 当检测失败后,将 Pod 的 IP:Port 从对应 Service 关联的 EndPoint 地址列表中删除。
- LivenessProbe: 当检测失败后将杀死容器,并根据 Pod 的重启策略来决定作出对应的措施。
五、探针使用示例
1、LivenessProbe 探针使用示例
(1)、通过 Exec 方式做健康探测
示例文件 liveness-exec.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec
labels:
app: liveness
spec:
containers:
- name: liveness
image: busybox
args: #创建测试探针探测的文件
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
initialDelaySeconds: 10 #延迟检测时间
periodSeconds: 5 #检测时间间隔
exec:
command:
- cat
- /tmp/healthy
容器启动设置执行的命令:
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"
容器在初始化后,首先创建一个 /tmp/healthy
文件,然后执行睡眠命令,睡眠 30 秒,到时间后执行删除 /tmp/healthy
文件命令。而设置的存活探针检检测方式为执行 shell
命令,用 cat 命令输出 healthy 文件的内容,如果能成功执行这条命令,存活探针就认为探测成功,否则探测失败。在前 30 秒内,由于文件存在,所以存活探针探测时执行 cat /tmp/healthy
命令成功执行。30 秒后 healthy 文件被删除,所以执行命令失败,Kubernetes
会根据 Pod
设置的重启策略来判断,是否重启 Pod。
(2)、通过 HTTP 方式做健康探测
示例文件 liveness-http.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-http
labels:
test: liveness
spec:
containers:
- name: liveness
image: mydlqclub/springboot-helloworld:0.0.1
livenessProbe:
initialDelaySeconds: 20 #延迟加载时间
periodSeconds: 5 #重试时间间隔
timeoutSeconds: 10 #超时时间设置
httpGet:
scheme: HTTP
port: 8081
path: /actuator/health
上面 Pod 中启动的容器是一个 SpringBoot 应用,其中引用了 Actuator
组件,提供了 /actuator/health
健康检查地址,存活探针可以使用 HTTPGet
方式向服务发起请求,请求 8081
端口的 /actuator/health
路径来进行存活判断:
- 探测结果的 Http 状态码如果为 200 ≤ status ≤ 400 的代码,则表示探测成功。
如果探测失败,则会杀死 Pod 进行重启操作。
httpGet探测方式有如下可选的控制字段:
- scheme: 用于测试连接的协议,默认为 HTTP。
- host: 要连接的主机名,默认为 Pod IP。
- port: 容器上要访问端口号或名称。
- path: Http 服务器上的访问 URL。
- httpHeaders: 自定义 Http 请求 Headers,Http 允许重复 Headers。
(3)、通过 TCP 方式做健康探测
示例文件 liveness-tcp.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcp
labels:
app: liveness
spec:
containers:
- name: liveness
image: nginx
livenessProbe:
initialDelaySeconds: 15
periodSeconds: 20
tcpSocket:
port: 80
TCP 检查方式和 HTTP 检查方式非常相似,在容器启动 initialDelaySeconds
参数设定的时间后,kubelet
将发送第一个 livenessProbe
探针,尝试连接容器的 80 端口,如果连接失败则将杀死 Pod 重启容器。
2、ReadinessProbe 探针使用示例
Pod 的 ReadinessProbe
探针使用方式和 LivenessProbe
探针探测方法一样,也是支持三种,只是一个是用于探测应用的存活,一个是判断是否对外提供流量的条件。这里用一个 Springboot 项目,设置 ReadinessProbe
探测 SpringBoot 项目的 8081
端口下的 /actuator/health
接口,如果探测成功则代表内部程序已经成功启动,就开放对外提供接口访问,否则内部应用没有成功启动或者在启动中,暂不对外提供访问,直到就绪探针探测成功才允许访问。
示例文件 readiness-exec.yaml
apiVersion: v1
kind: Service
metadata:
name: springboot
labels:
app: springboot
spec:
type: NodePort
ports:
- name: server
port: 8080
targetPort: 8080
nodePort: 31180
- name: management
port: 8081
targetPort: 8081
nodePort: 31181
selector:
app: springboot
---
apiVersion: v1
kind: Pod
metadata:
name: springboot
labels:
app: springboot
spec:
containers:
- name: springboot
image: mydlqclub/springboot-helloworld:0.0.1
ports:
- name: server
containerPort: 8080
- name: management
containerPort: 8081
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 5
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 8081
path: /actuator/health
3、ReadinessProbe + LivenessProbe 配合使用示例
一般程序中需要设置两种探针结合使用,并且也要结合实际情况,来配置初始化检查时间和检测间隔,下面列一个简单的 SpringBoot 项目的 Deployment 例子。
apiVersion: v1
kind: Service
metadata:
name: springboot
labels:
app: springboot
spec:
type: NodePort
ports:
- name: server
port: 8080
targetPort: 8080
nodePort: 31180
- name: management
port: 8081
targetPort: 8081
nodePort: 31181
selector:
app: springboot
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: springboot
labels:
app: springboot
spec:
replicas: 1
selector:
matchLabels:
app: springboot
template:
metadata:
name: springboot
labels:
app: springboot
spec:
containers:
- name: readiness
image: mydlqclub/springboot-helloworld:0.0.1
ports:
- name: server
containerPort: 8080
- name: management
containerPort: 8081
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 5
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 8081
path: /actuator/health
livenessProbe:
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
httpGet:
scheme: HTTP
port: 8081
path: /actuator/health