Kubernetes容器健康检查配置
作者:竹隐 来源:TechWeb 发布时间:2021-10-23 15:14
简介
此文讲述如何配置容器的Liveness、Readiness、Startup探针。
kubelet使用Liveness探测器来知道什么时候要重启容器。例如,Liveness探测器可以捕捉到死锁(应用程序在运行,但是无法继续执行后面的步骤)。这样的情况下重启容器有助于让应用程序在有问题的情况下更可用。
kubelet使用Readiness探测器可以知道容器什么时候准备好了并可以开始接受请求流量, 当一个Pod内的所有容器都准备好了,才能把这个Pod看作就绪了。这种信号的一个用途就是控制哪个Pod作为Service的后端。在Pod还没有准备好的时候,会从Service的负载均衡器中被剔除的。
kubelet使用Startup探测器可以知道应用程序容器什么时候启动了。如果配置了这类探测器,就可以控制容器在启动成功后再进行Liveness和Readiness检查,确保这些存活、就绪探测器不会影响应用程序的启动。这可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉。
定义一个Liveness探针
许多长时间运行的应用程序最终会过渡到断开的状态,除非重新启动,否则无法恢复。Kubernetes提供了Liveness探测器来发现并补救这种情况。
创建一个Pod,其中运行一个基于k8s.gcr.io/busybox镜像的容器。配置文件如下。文件名:exec-liveness.yaml
apiVersion:v1kind:Podmetadata:labels:test:livenessname:liveness-execspec:containers:-name:livenessimage:k8s.gcr.io/busyboxargs:-/bin/sh--c-touch/tmp/healthy;sleep30;rm-rf/tmp/healthy;sleep600livenessProbe:exec:command:-cat-/tmp/healthyinitialDelaySeconds:5periodSeconds:5
在配置文件中,可以看到Pod中只有一个容器。periodSeconds字段指定了kubelet应该每5秒执行一次存活检测。initialDelaySeconds字段告诉kubelet在执行第一次探针前应该等待5秒。kubelet在容器中执行命令cat /tmp/healthy来进行检测。如果命令执行成功并且返回值为0,kubelet会认为这个容器是健康存活的。如果这个命令返回非0值,kubelet会杀死这个容器并重新启动它。执行命令如下:
/bin/sh-c"touch/tmp/healthy;sleep30;rm-rf/tmp/healthy;sleep600"
这个容器生命的前30秒,/tmp/healthy文件是存在的。执行命令cat /tmp/healthy会返回成功码。30秒后,执行命令cat /tmp/healthy就回返回失败码。
创建Pod:
#kubectlapply-f/root/k8s-example/probe/exec-liveness.yaml
在 30 秒内,查看Pod的事件:
kubectldescribepodliveness-exec
输出结果显示还没有存活探测器失败:
Events:TypeReasonAgeFromMessage-NormalScheduleddefault-schedulerSuccessfullyassigneddefault/liveness-exectok8s-node04NormalPulled22skubelet,k8s-node04Containerimage"k8s.gcr.io/busybox"alreadypresentonmachineNormalCreated22skubelet,k8s-node04CreatedcontainerlivenessNormalStarted22skubelet,k8s-node04Startedcontainerliveness
30秒之后,再来看Pod的事件:
kubectldescribepodliveness-exec
在输出结果的最下面,有信息显示存活探测器失败了,这个容器被杀死并且被重建了。
Events:TypeReasonAgeFromMessage-NormalScheduleddefault-schedulerSuccessfullyassigneddefault/liveness-exectok8s-node04NormalPulled47skubelet,k8s-node04Containerimage"k8s.gcr.io/busybox"alreadypresentonmachineNormalCreated47skubelet,k8s-node04CreatedcontainerlivenessNormalStarted47skubelet,k8s-node04StartedcontainerlivenessWarningUnhealthy5s(x3over15s)kubelet,k8s-node04Livenessprobefailed:cat:can'topen'/tmp/healthy':NosuchfileordirectoryNormalKilling5skubelet,k8s-node04Containerlivenessfailedlivenessprobe,willberestarted
再等另外30秒,检查看这个容器被重启了:
kubectlgetpodliveness-execNAMEREADYSTATUSRESTARTSAGEliveness-exec1/1Running23m10s
再查看Pod资源详情:
kubectldescribepodliveness-exec
输出结果如下,容器重启成功。
创建Pod:
任何大于或等于200并且小于400的返回码标示成功,其它返回码都标示失败。
容器存活的最开始10秒中,/healthz处理程序返回一个200的状态码。之后处理程序返回500的状态码。
kubelet在容器启动之后3秒开始执行健康检测。所以前几次健康检查都是成功的。但是10秒之后,健康检查会失败,并且kubelet会杀死容器再重新启动容器。
10秒之后,通过看Pod事件来检测存活探测器已经失败了并且容器被重新启动了。
第三种类型的liveness探测是使用TCP套接字。通过配置,kubelet会尝试在指定端口和容器建立套接字链接。如果能建立链接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的。
创建一个Pod。文件名:tcp-liveness-readiness.yaml
apiVersion:v1kind:Podmetadata:name:goproxylabels:app:goproxyspec:containers:-name:goproxyimage:k8s.gcr.io/goproxy:0.1ports:-containerPort:8080readinessProbe:tcpSocket:port:8080initialDelaySeconds:5periodSeconds:10livenessProbe:tcpSocket:port:8080initialDelaySeconds:15periodSeconds:20
除了readiness探测,这个配置包括了一个Liveness探测。kubelet会在容器启动15秒后进行第一次Liveness探测。就像Readiness探测一样,会尝试连接goproxy容器的8080端口。如果存活探测失败,这个容器会被重新启动。
#kubectlapply-f/root/k8s-example/probe/tcp-liveness-readiness.yaml
15秒之后,通过看Pod事件来检测存活探测器:
#kubectldescribepodgoproxy
使用命名端口:
所以,前面的例子就变成了:
幸亏有Startup探测,应用程序将会有最多5分钟(30*10=300s)的时间来完成它的启动。 一旦Startup探测成功一次,存活探测任务就会接管对容器的探测,对容器死锁可以快速响应。 如果Startup探测一直没有成功,容器会在300秒后被杀死,并且根据restartPolicy来设置Pod状态。
定义Readliness探测器
有时候,应用程序会暂时性的不能提供通信服务。例如,应用程序在启动时可能需要加载很大的数据或配置文件,或是启动后要依赖等待外部服务。在这种情况下,既不想杀死应用程序,也不想给它发送请求。Kubernetes提供了就绪探测器来发现并缓解这些情况。容器所在Pod上报还未就绪的信息,并且不接受通过Kubernetes Service的流量。
注意:就绪探测器在容器的整个生命周期中保持运行状态。
就绪探测器的配置和存活探测器的配置相似。唯一区别就是要使用readinessProbe字段,而不是LivenessProbe字段。
readinessProbe:exec:command:-cat-/tmp/healthyinitialDelaySeconds:5periodSeconds:5
Readliness和Liveness探测可以在同一个容器上并行使用。两者都用可以确保流量不会发给还没有准备好的容器,并且容器会在它们失败的时候被重新启动。
配置探测器
探测器有很多配置字段,可以使用这些字段精确的控制存活和就绪检测的行为:
initialDelaySeconds:容器启动后要等待多少秒后存活和就绪探测器才被初始化,默认是0秒,最小值是0。 periodSeconds:执行探测的时间间隔(单位是秒)。默认是10秒。最小值是1。 timeoutSeconds:探测的超时后等待多少秒。默认值是1秒。最小值是1。 successThreshold:探测器在失败后,被视为成功的最小连续成功数。默认值是1。存活探测的这个值必须是1。最小值是1。 failureThreshold:当Pod启动了并且探测到失败,Kubernetes的重试次数。存活探测情况下的放弃就意味着重新启动容器。就绪探测情况下的放弃Pod会被打上未就绪的标签。默认值是3。最小值是1。
对于一次探测,kubelet在节点上(不是在Pod里面)建立探测连接,这意味着你不能在host参数上配置service name,因为kubelet不能解析service name。