互联网技术 / 互联网资讯 · 2024年1月29日

配置Kubernetes容器的健康检查

此文讲述如何配置容器的LiveneSS、ReadineSS、StaRtup探针。

kubelet使用LiveneSS探测器来知道什么时候要重启容器。例如,LiveneSS探测器可以捕捉到死锁(应用程序在运行,但是无法继续执行后面的步骤)。这样的情况下重启容器有助于让应用程序在有问题的情况下更可用。

Kubernetes容器健康检查配置

kubelet使用ReadineSS探测器可以知道容器什么时候准备好了并可以开始接受请求流量, 当一个Pod内的所有容器都准备好了,才能把这个Pod看作就绪了。这种信号的一个用途就是控制哪个Pod作为SeRvice的后端。在Pod还没有准备好的时候,会从SeRvice的负载均衡器中被剔除的。

kubelet使用StaRtup探测器可以知道应用程序容器什么时候启动了。如果配置了这类探测器,就可以控制容器在启动成功后再进行LiveneSS和ReadineSS检查,确保这些存活、就绪探测器不会影响应用程序的启动。这可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉。

定义一个LiveneSS探针

许多长时间运行的应用程序最终会过渡到断开的状态,除非重新启动,否则无法恢复。KubeRnetes提供了LiveneSS探测器来发现并补救这种情况。

创建一个Pod,其中运行一个基于k8s.gcR.io/bUSybox镜像的容器。配置文件如下。文件名:exec-liveneSS.yaMl

APIversion: v1 kind: Pod Metadata: labels: test: liveneSS naMe: liveneSS-exec spec: contAIneRs: – naMe: liveneSS image: k8s.gcR.io/bUSybox aRgs: – /BIn/sh – -c – toUCh /tMp/healthy; sLeep 30; RM -Rf /tMp/healthy; sLeep 600 liveneSSProbe: exec: command: – cat – /tMp/healthy inITialDelaYseconds: 5 peRiodSeconds: 5

在配置文件中,可以看到Pod中只有一个容器。peRiodSeconds字段指定了kubelet应该每5秒执行一次存活检测。inITialDelaYseconds字段告诉kubelet在执行第一次探针前应该等待5秒。kubelet在容器中执行命令cat /tMp/healthy来进行检测。如果命令执行成功并且返回值为0,kubelet会认为这个容器是健康存活的。如果这个命令返回非0值,kubelet会杀死这个容器并重新启动它。执行命令如下:

/BIn/sh -c “toUCh /tMp/healthy; sLeep 30; RM -Rf /tMp/healthy; sLeep 600”

这个容器生命的前30秒,/tMp/healthy文件是存在的。执行命令cat /tMp/healthy会返回成功码。30秒后,执行命令cat /tMp/healthy就回返回失败码。

创建Pod:

# kubectl apply -f /Root/k8s-example/Probe/exec-liveneSS.yaMl

在 30 秒内,查看Pod的事件:

kubectl descRibe pod liveneSS-exec

输出结果显示还没有存活探测器失败:

Events: Type reason Age FRoM MeSSage NoRMal Scheduled deFAult-scheduleR SUCceSSfully aSSigned deFAult/liveneSS-exec to k8s-node04 NoRMal Pulled 22s kubelet, k8s-node04 ContAIneR image “k8s.gcR.io/bUSybox” alReady pResent on MacHine NoRMal CReated 22s kubelet, k8s-node04 CReated contAIneR liveneSS NoRMal StaRted 22s kubelet, k8s-node04 StaRted contAIneR liveneSS

30秒之后,再来看Pod的事件:

kubectl descRibe pod liveneSS-exec

在输出结果的最下面,有信息显示存活探测器失败了,这个容器被杀死并且被重建了。

Events: Type reason Age FRoM MeSSage NoRMal Scheduled deFAult-scheduleR SUCceSSfully aSSigned deFAult/liveneSS-exec to k8s-node04 NoRMal Pulled 47s kubelet, k8s-node04 ContAIneR image “k8s.gcR.io/bUSybox” alReady pResent on MacHine NoRMal CReated 47s kubelet, k8s-node04 CReated contAIneR liveneSS NoRMal StaRted 47s kubelet, k8s-node04 StaRted contAIneR liveneSS WaRning Unhealthy 5s (x3 OVeR 15s) kubelet, k8s-node04 LiveneSS Probe Failed: cat: can””t open ””/tMp/healthy””: No sUCh file oR diRecTory NoRMal Killing 5s kubelet, k8s-node04 ContAIneR liveneSS Failed liveneSS Probe, will be RestaRted

再等另外30秒,检查看这个容器被重启了:

kubectl get pod liveneSS-exec NAME READY STATUS RESTARTS AGE liveneSS-exec 1/1 Running 2 3M10s

再查看Pod资源详情:

kubectl descRibe pod liveneSS-exec

输出结果如下,容器重启成功。

Events: Type reason Age FRoM MeSSage NoRMal Scheduled deFAult-scheduleR SUCceSSfully aSSigned deFAult/liveneSS-exec to k8s-node04 WaRning Unhealthy 35s (x6 OVeR 2M) kubelet, k8s-node04 LiveneSS Probe Failed: cat: can””t open ””/tMp/healthy””: No sUCh file oR diRecTory NoRMal Killing 35s (x2 OVeR 110s) kubelet, k8s-node04 ContAIneR liveneSS Failed liveneSS Probe, will be RestaRted NoRMal Pulled 5s (x3 OVeR 2M32s) kubelet, k8s-node04 ContAIneR image “k8s.gcR.io/bUSybox” alReady pResent on MacHine NoRMal CReated 5s (x3 OVeR 2M32s) kubelet, k8s-node04 CReated contAIneR liveneSS NoRMal StaRted 5s (x3 OVeR 2M32s) kubelet, k8s-node04 StaRted contAIneR liveneSS

定义一个存活态HTTP请求接口

另外一种类型的LiveneSS探测方式是使用HTTP GET请求。下面是一个Pod的配置文件,其中运行一个基于k8s.gcR.io/liveneSS镜像的容器。

创建Pod:

APIversion: v1 kind: Pod Metadata: labels: test: liveneSS naMe: liveneSS-http spec: contAIneRs: – naMe: liveneSS image: k8s.gcR.io/liveneSS aRgs: – /seRveR liveneSSProbe: httpGet: path: /healthz poRt: 8080 httpHeadeRs: – naMe: X-CUStoM-HeadeR value: AwesoMe inITialDelaYseconds: 3 peRiodSeconds: 3

配置文件中,Pod中只有一个容器。peRiodSeconds字段指定了kubelet每隔3秒执行一次检测。inITialDelaYseconds字段告诉kubelet在执行第一次探测前应该等待3秒。kubelet 会向容器内运行的服务(服务会监听 8080 端口)发送一个 HTTP GET 请求来执行探测。如果服务上/healthz路径下的处理程序返回成功码。则kubelet认为容器是健康存活的。如果处理程序返回失败码,则kubelet会杀死这个容器并且重新启动它。

任何大于或等于200并且小于400的返回码标示成功,其它返回码都标示失败。

容器存活的最开始10秒中,/healthz处理程序返回一个200的状态码。之后处理程序返回500的状态码。

http.HandleFunc(“/healthz”, func(w http.ResponseWRITeR, R *http.request) { duRation := tiMe.Now().Sub(staRted) if duRation.Seconds() > 10 {     w.WRITeHeadeR(500)     w.WRITe([]byte(fMt.SpRintf(“Error: %v”, duRation.Seconds()))) } else {     w.WRITeHeadeR(200)     w.WRITe([]byte(“ok”)) } }) 

kubelet在容器启动之后3秒开始执行健康检测。所以前几次健康检查都是成功的。但是10秒之后,健康检查会失败,并且kubelet会杀死容器再重新启动容器。

# kubectl apply -f /Root/k8s-example/Probe/http-liveneSS.yaMl

10秒之后,通过看Pod事件来检测存活探测器已经失败了并且容器被重新启动了。

Events: Type reason Age FRoM MeSSage NoRMal Scheduled deFAult-scheduleR SUCceSSfully aSSigned deFAult/liveneSS-http to k8s-node01 NoRMal Pulled 17s kubelet, k8s-node01 ContAIneR image “k8s.gcR.io/liveneSS” alReady pResent on MacHine NoRMal CReated 17s kubelet, k8s-node01 CReated contAIneR liveneSS NoRMal StaRted 16s kubelet, k8s-node01 StaRted contAIneR liveneSS WaRning Unhealthy 1s (x2 OVeR 4s) kubelet, k8s-node01 LiveneSS Probe Failed: HTTP Probe Failed wITh statUScode: 500

定义TCP的存活探测

第三种类型的liveneSS探测是使用TCP套接字。通过配置,kubelet会尝试在指定端口和容器建立套接字链接。如果能建立链接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的。

创建一个Pod。文件名:TCP-liveneSS-ReadineSS.yaMl

APIversion: v1 kind: Pod Metadata: naMe: GoProxy labels: app: GoProxy spec: contAIneRs: – naMe: GoProxy iMage: k8s.gcR.io/GoProxy:0.1 poRts: – contAIneRPoRt: 8080 ReadineSSProbe: TCPSocket: poRt: 8080 inITialDelaYseconds: 5 peRiodSeconds: 10 liveneSSProbe: TCPSocket: poRt: 8080 inITialDelaYseconds: 15 peRiodSeconds: 20

TCP检测的配置和HTTP检测非常相似。下面这个例子同时使用就绪和存活探测器。kubelet会在容器启动5秒后发送第一个就绪探测。这会尝试连接GoProxy容器的8080端口。如果探测成功,这个Pod会被标记为就绪状态,kubelet将继续每隔10秒运行一次检测。

除了ReadineSS探测,这个配置包括了一个LiveneSS探测。kubelet会在容器启动15秒后进行第一次LiveneSS探测。就像ReadineSS探测一样,会尝试连接GoProxy容器的8080端口。如果存活探测失败,这个容器会被重新启动。

# kubectl apply -f /Root/k8s-exaMple/Probe/TCP-liveneSS-ReadineSS.yaMl

15秒之后,通过看Pod事件来检测存活探测器:

# kubectl descRibe pod GoProxy

使用命名端口:

对于HTTP或者TCP存活检测可以使用命名的容器端口。

poRts: – naMe: liveneSS-poRt contAIneRPoRt: 8080 hostPoRt: 8080 liveneSSProbe: httpGet: path: /healthz poRt: liveneSS-poRt

有时候,会有一些现有的应用程序在启动时需要较多的初始化时间。要不影响对引起探测死锁的快速响应,这种情况下,设置LiveneSS探测参数是要技巧的。技巧就是使用一个命令来设置StaRtup探测,针对HTTP或者TCP检测,可以通过设置failureThReshold * peRiodSeconds参数来保证有足够长的时间应对糟糕情况下的启动时间。

所以,前面的例子就变成了:

poRts: – naMe: liveneSS-poRt contAIneRPoRt: 8080 hostPoRt: 8080 liveneSSProbe: httpGet: path: /healthz poRt: liveneSS-poRt failureThReshold: 1 peRiodSeconds: 10 staRtupProbe: httpGet: path: /healthz poRt: liveneSS-poRt failureThReshold: 30 peRiodSeconds: 10

幸亏有StaRtup探测,应用程序将会有最多5分钟(30*10=300s)的时间来完成它的启动。 一旦StaRtup探测成功一次,存活探测任务就会接管对容器的探测,对容器死锁可以快速响应。 如果StaRtup探测一直没有成功,容器会在300秒后被杀死,并且根据RestaRtPolicy来设置Pod状态。

定义ReadlineSS探测器

有时候,应用程序会暂时性的不能提供通信服务。例如,应用程序在启动时可能需要加载很大的数据或配置文件,或是启动后要依赖等待外部服务。在这种情况下,既不想

OpenMagic API

Need more than content? Move into the product flow.

If you are here for model access, pricing, developer docs, or the future API console, the dedicated product path now lives on api.openmagic.ai.

登录免费注册