存活探针
Kubernetes提供了自愈的能力,具体就是能感知到容器崩溃,然后能够重启这个容器。但是有时候例如Java程序内存泄漏了,程序无法正常工作,但是JVM进程却是一直运行的,对于这种应用本身业务出了问题的情况,Kubernetes提供了Liveness Probe机制,通过检测容器响应是否正常来决定是否重启,这是一种很好的健康检查机制。
毫无疑问,每个Pod最好都定义Liveness Probe,否则Kubernetes无法感知Pod是否正常运行。
Kubernetes支持如下三种探测机制。
- HTTP GET:Probe向容器发送HTTP GET请求,如果Probe收到2xx或3xx,说明容器是健康的。
- TCP Socket:Probe尝试与容器指定端口建立TCP连接,如果连接成功建立,说明容器是健康的。
- Exec:Probe执行容器中的命令并检查命令退出的状态码,如果状态码为0,说明容器是健康的。
注意 1:与存活探针对应的还有一个就绪探针(Readiness Probe),详细介绍请参见《Kubernetes 就绪探针(Readiness Probe)》这篇博文。
HTTP GET
HTTP GET方式是最常见的探测方法,其具体机制是向容器发送HTTP GET请求,如果Probe(探头,Kubelet中创建的HTTP客户端)收到2xx或3xx,说明容器是健康的。
httpGet配置项:
- host:连接的主机名,默认连接到pod的IP。你可能想在http header中设置”Host”而不是使用IP。
- scheme:连接使用的schema,默认HTTP。
- path: 访问的HTTP server的path。
- httpHeaders:自定义请求的header。HTTP运行重复的header。
- port:访问的容器的端口名字或者端口号。端口号必须介于1和65535之间。
apiVersion: v1
kind: Pod
metadata:
name: liveness-http
spec:
containers:
- name: liveness
image: nginx:alpine
livenessProbe: # liveness probe
httpGet: # HTTP GET定义
path: /
port: 80
imagePullSecrets:
- name: default-secret
创建这个Pod。
$ kubectl create -f liveness-http.yaml
pod/liveness-http created
如上,这个Probe往容器的80端口发送HTTP GET请求,如果请求不成功,Kubernetes通常会重启容器。
注意 1: Pod存活探针检测失败后是否重启容器,主要看Pod重启策略,详情请参见《Kubernetes Pod重启策略 》这篇博文,如果Pod是默认的Always重启策略,那么Pod存活探针检查失败肯定是会重启容器的。
查看Pod详情。
$ kubectl describe po liveness-http
Name: liveness-http
......
Containers:
liveness:
......
State: Running
Started: Mon, 03 Aug 2020 03:08:55 +0000
Ready: True
Restart Count: 0
Liveness: http-get http://:80/ delay=0s timeout=1s period=10s #success=1 #failure=3
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-vssmw (ro)
......
可以看到Pod当前状态是Running,Restart Count为0,说明没有重启。如果Restart Count不为0,则说明已经重启。
TCP Socket
TCP Socket(Kubelet中创建的TCP客户端)尝试与容器在指定端口上建立TCP连接。 如果它可以建立连接,则容器被认为是健康的;否则被认为是不健康的。
如果您有HTTP探针或Command探针不能正常工作的情况,TCP探测器会派上用场。 例如,gRPC或FTP服务是此类探测的主要候选者。
TCP 的配置项(tcpSocket):
- host:探测的主机,默认为本pod ip。
- port:端口,1到65535。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-tcp
spec:
containers:
- name: liveness
image: nginx:alpine
livenessProbe: # liveness probe
tcpSocket:
port: 80
imagePullSecrets:
- name: default-secret
Exec
Exec即执行具体命令,具体机制是Probe执行容器中的命令(Kubelet调用CRI接口进入容器内部执行命令)并检查命令退出的状态码。 如果命令以退出代码0返回,则容器标记为健康; 否则,它被标记为不健康。 当您不能或不想运行HTTP服务时,此类型的探针则很有用,但是必须是运行可以检查您的应用程序是否健康的命令。
Exec 的配置项(exec):
- command:需要执行的命令,需要符合命令的格式。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: nginx:alpine
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe: # liveness probe
exec: # Exec定义
command:
- cat
- /tmp/healthy
imagePullSecrets:
- name: default-secret
上面定义在容器中执行cat /tmp/healthy命令,如果成功执行并返回0,则说明容器是健康的。上面定义中,30秒后命令会删除/tmp/healthy,这会导致Liveness Probe判定Pod处于不健康状态,这时候通常会重启容器。
Liveness Probe高级配置
上面liveness-http的describe命令回显中有如下行。
Liveness: http-get http://:80/ delay=0s timeout=1s period=10s #success=1 #failure=3
这一行表示Liveness Probe的具体参数配置,其含义如下:
- delay:延迟,delay=0s,表示在容器启动后立即开始探测,没有延迟时间
- timeout:超时,timeout=1s,表示容器必须在1s内进行响应,否则这次探测记作失败
- period:周期,period=10s,表示每10s探测一次容器
- success:成功,#success=1,表示连续1次成功后记作成功
- failure:失败,#failure=3,表示连续3次失败后会重启容器
以上存活探针表示:容器启动后立即进行探测,如果1s内容器没有给出回应则记作探测失败。每次间隔10s进行一次探测,在探测连续失败3次后重启容器。
这些是创建时默认设置的,您也可以手动配置,如下所示。
apiVersion: v1
kind: Pod
metadata:
name: liveness-http
spec:
containers:
- name: liveness
image: nginx:alpine
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10 # 容器启动后多久开始探测
timeoutSeconds: 2 # 表示容器必须在2s内做出相应反馈给probe,否则视为探测失败
periodSeconds: 30 # 探测周期,每30s探测一次
successThreshold: 1 # 连续探测1次成功表示成功
failureThreshold: 3 # 连续探测3次失败表示失败
initialDelaySeconds一般要设置大于0,这是由于很多情况下容器虽然启动成功,但应用就绪也需要一定的时间,需要等就绪时间之后才能返回成功,否则就会导致probe经常失败。
另外failureThreshold可以设置多次循环探测,它定义了在多少次连续失败后认为应用程序不再健康。如果将其设置为多次循环探测,意味着在实际应用中,系统会进行多次探测以确定应用程序是否健康。这一点在开发应用时需要注意。
配置有效的Liveness Probe
- Liveness Probe应该检查什么 一个好的Liveness Probe应该检查应用内部所有关键部分是否健康,并使用一个专有的URL访问,例如/health,当访问/health时执行这个功能,然后返回对应结果。这里要注意不能做鉴权,不然probe就会一直失败导致陷入重启的死循环。
另外检查只能限制在应用内部,不能检查依赖外部的部分,例如当前端web server不能连接数据库时,这个就不能看成web server不健康。 - Liveness Probe必须轻量 Liveness Probe不能占用过多的资源,且不能占用过长的时间,否则所有资源都在做健康检查,这就没有意义了。例如Java应用,就最好用HTTP GET方式,如果用Exec方式,JVM启动就占用了非常多的资源。