pod如何实现container的健康运行?
我们要解决的问题是什么?为什么要有livenessProbe? 它可以解决什么问题?
Contents
一 要解决的问题:container不响应请求
前面,我们知道通过在pod级别定义restartPolicy,可以实现pod自动重启container。进而解决了当container自身出现异常、故障时,pod会自动重启这些container。进而避免了由这些container提供的服务不可用的情况出现。
可是,这样就真的比较好的解决了问题吗?
试想:container自身并没有出现故障,而是出现了比如OutOfMemory的错误,或是程序故障陷入死循环导致,不能正常对外提供服务。那么此时,pod的restartPolicy就不生效了,不会去自动重启container了。
我们该怎么解决这个问题呢?于是,人们引入了一种解决方案:livenessProbe,存活探针。它是定义在每个container级别的,用来周期性的探测该container是不是正常的。它有指定的探测的策略和时间间隔,当它发现container不正常时,就会把container失败的结果”上报“给Kubernetes,然后Kubernetes就会根据pod上的restartPolicy来判断是不是要重启这个container。
二 livenessProbe的分类
- HTTP GET probe:向container的IP和端口,加上指定的路径上,发送一个HTTP请求,如果返回值是诸如2xx或者3xx的,则认为container是healthy,否则如果返回值是不符合预期的错误码、或者请求超时了,则认为container是故障的;
- TCP socket probe:向container的IP和指定的端口上,发起1个TCP socket连接请求。如果不能建立连接,或者连接超时,则认为container是故障的,否则连接正常的话,则container是OK的。
- Exec probe: 在container内部执行一个特定的命令,根据命令的返回结果来判断命令执行是否成功,进而判定container是否正常。
三 httpGet类型的livenessProbe验证
1 kiada pod yaml
[root@master-node Chapter06]# pwd
/root/kubernetes-in-action-2nd-edition/Chapter06
[root@master-node Chapter06]# cat pod.kiada-liveness.yaml
apiVersion: v1
kind: Pod
metadata:
name: kiada-liveness
spec:
containers:
- name: kiada
image: luksa/kiada:0.2
ports:
- name: http
containerPort: 8080
livenessProbe:
httpGet:
path: /
port: 8080 #没有指定initialDelaySeconds、periodSeconds、timeoutSeconds、failureThreshold,其采用默认值,分别为10,10,1,3.
- name: envoy
image: luksa/kiada-ssl-proxy:0.1
imagePullPolicy: Always
ports:
- name: https
containerPort: 8443
- name: admin
containerPort: 9901
livenessProbe:
httpGet:
path: /ready
port: admin
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
[root@master-node Chapter06]# 2 创建pod
[root@master-node Chapter06]# kubectl apply -f pod.kiada-liveness.yaml pod/kiada-liveness created [root@master-node Chapter06]# kubectl get pods -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES curl 1/1 Running 14 (2d8h ago) 17d 10.244.2.245 node-2 <none> <none> curl-with-ambassador 2/2 Running 0 40d 10.244.1.47 node-1 <none> <none> downward 1/1 Running 0 40d 10.244.1.45 node-1 <none> <none> fortune-configmap-volume 2/2 Running 0 48d 10.244.2.235 node-2 <none> <none> fortune-https 2/2 Running 0 47d 10.244.2.236 node-2 <none> <none> kiada-liveness 2/2 Running 0 7s 10.244.2.248 node-2 <none> <none> my-job-jfhz9 0/1 Completed 0 17d 10.244.2.244 node-2 <none> <none> [root@master-node Chapter06]#
3 livenessProbe的字段含义
initialDelaySeconds: 表示,当container启动多久以后,开始执行livenessProbe探测;默认值是10秒; periodSeconds: 表示,每间隔多久重复执行livenessProbe探测;默认值是10秒; timeoutSeconds: 表示,在多久时间范围内,没收到container的响应请求,认为container失败1次;默认值是1秒; failureThreshold: 连续失败多少次,就认为container是彻底失败了,开始restart container;默认值是3次;
上述2个container分别设置了livenessProbe,其中第一个container kiada的livenessProbe没有显示指定相关字段,均采用默认值。表示,当container启动10秒以后,开始执行livenessProbe,如果在1秒内没有收到请求,记作container失败一次,间隔10秒之后,重复执行livenessProbe,如果联系3次都失败了,那么就开始重启这个container;
第二个container envoy显示指定了这几个字段,就按照指定的参数值来执行livenessProbe。
4 开启port-forward
[root@master-node ~]# kubectl port-forward --address=172.16.11.168 kiada-liveness 8080 8443 9901 Forwarding from 172.16.11.168:8080 -> 8080 Forwarding from 172.16.11.168:8443 -> 8443 Forwarding from 172.16.11.168:9901 -> 9901 Handling connection for 9901
5 监控events:kubectl get events -w
[root@master-node ~]# kubectl get events -w LAST SEEN TYPE REASON OBJECT MESSAGE ...
6 客户端向envoy container发起请求,模拟故障
$ curl -X POST 172.16.11.168:9901/healthcheck/fail OK asher at MacBook-Air-3 in ~ $
7 再次查看events
[root@master-node ~]# kubectl get events -w LAST SEEN TYPE REASON OBJECT MESSAGE ... 0s Warning EvictionThresholdMet node/master-node Attempting to reclaim ephemeral-storage 0s Warning Unhealthy pod/kiada-liveness Liveness probe failed: HTTP probe failed with statuscode: 503 0s Warning Unhealthy pod/kiada-liveness Liveness probe failed: HTTP probe failed with statuscode: 503 0s Warning Unhealthy pod/kiada-liveness Liveness probe failed: HTTP probe failed with statuscode: 503 0s Normal Killing pod/kiada-liveness Container envoy failed liveness probe, will be restarted 0s Normal Pulling pod/kiada-liveness Pulling image "luksa/kiada-ssl-proxy:0.1" 0s Normal Pulled pod/kiada-liveness Successfully pulled image "luksa/kiada-ssl-proxy:0.1" in 2.760213466s 0s Normal Created pod/kiada-liveness Created container envoy 0s Normal Started pod/kiada-liveness Started container envoy
从上,我们可以看到,连续livenessProbe开始工作,并且探测到连续3次错误,Liveness probe failed: HTTP probe failed with statuscode: 503 出现3行之后。container被杀死,然后重启了。
验证了我们的livenessProbe符合我们的预期开始工作。
说明:当我们的客户端执行curl -X POST 172.16.11.168:9901/healthcheck/fail向container发起请求,模拟故障之后,在master上看到Liveness probe failed: HTTP probe failed with statuscode: 503。此时,我们再次向container发起请求,模拟container恢复正常之后,Kubernetes的livenessProbe不会再次认为container故障,并重启了。
发起正常请求的命令是:
$ curl -X POST 172.16.11.168:9901/healthcheck/ok OK asher at MacBook-Air-3 in ~ $
8 查看envoy这个container被重启的细节
kubectl describe pod kiada-liveness
[root@master-node Chapter06]# kubectl describe pod kiada-liveness
Name: kiada-liveness
Namespace: default
Priority: 0
Node: node-2/172.16.11.161
...
Containers:
kiada:
...
envoy:
Container ID: docker://5d8c136443f477606fc79114e020c75a9b2249612ac3376764cdcfec35246a61
Image: luksa/kiada-ssl-proxy:0.1
Image ID: docker-pullable://docker.io/luksa/kiada-ssl-proxy@sha256:ee9fc6cfe26a53c53433fdb7ce0d49c5e1bffb889adf4d7b8783ae9f273ecfe7
Ports: 8443/TCP, 9901/TCP
Host Ports: 0/TCP, 0/TCP
State: Running
Started: Fri, 27 May 2022 18:30:43 +0800
Last State: Terminated
Reason: Completed
Exit Code: 0
Started: Fri, 27 May 2022 18:25:39 +0800
Finished: Fri, 27 May 2022 18:30:40 +0800
Ready: True
Restart Count: 1
Liveness: http-get http://:admin/ready delay=10s timeout=2s period=5s #success=1 #failure=3
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-2mz9d (ro)我们看到,envoy的信息:Last State: Terminated,Exit Code: 0,这里的退出代码是0,意味着,envoy是优雅的自动停止了。而不是被kill了,如果是kill的,则可以看到退出代码是137.
查看container被重启前的日志:kubectl logs kiada-liveness -c envoy -p
注意这里的-p表示的是previous,该container前一次的日志。
[root@master-node Chapter06]# kubectl logs kiada-liveness -c envoy -p ... [2022-05-27 10:30:40.441][1][warning][main] [source/server/server.cc:493] caught SIGTERM [2022-05-27 10:30:40.441][1][info][main] [source/server/server.cc:613] shutting down server instance [2022-05-27 10:30:40.441][1][info][main] [source/server/server.cc:560] main dispatch loop exited [2022-05-27 10:30:40.442][1][info][main] [source/server/server.cc:606] exiting [root@master-node Chapter06]#
意味着,container的进程被优雅的退出了。
9 envoy的livenessProbe工作流程图

四 tcpSocket类型的livenessProbe举例
如果container不支持HTTP请求的场景,可以使用tcpSocket类型的livenessProbe来验证container是否正常。
livenessProbe:
tcpSocket: #A
port: 1234 #A
periodSeconds: 2 #B
failureThreshold: 1 #C
#A This tcpSocket probe uses TCP port 1234
#B The probe runs every 2s
#C A single probe failure is enough to restart the container 向container的1234端口发送tcp socket连接请求,如果在2s内不能建立连接,且失败1次,则认为container异常,需要restart。
五 exec类型的livenessProbe举例
对于HTTP get和tcp socket都不支持的container,可以通过exec类型来实现,探测container是否正常。
livenessProbe:
exec:
command: #A
- /usr/bin/healthcheck #A
periodSeconds: 2 #B
timeoutSeconds: 1 #C
failureThreshold: 1 #D
#A The command to run and its arguments
#B The probe runs every second
#C The command must return within one second
#D A single probe failure is enough to restart the container
六 小结和参考
在pod上设置了restartPolicy来重启container的缺陷:当container表面看正常运行,但是当它陷入类似Java程序的内存溢出,或者OOM时,其实container是异常的,不能对外提供服务。而此时,pod是不会尝试重启container来解决问题。
我们可以通过给container加上livenessProbe来定期的探测container健康状况,从而确保container的正常运行。
对于生产环境的pod,我们都建议根据实际情况给container加上livenessProbe,来确保container的正常运行。
《Kubernetes in Action Second Edition》 Marko luksa
Chapter 06 managing the lifecycle of the Pod’s containers P152–P158.



一条评论
Pingback: