![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_efa819ba-6725-11ec-9177-fa163eb4f6be.png)
文/江晓宇
k8s在Docker技术的基础上,为应用提供容器跨多个服务器主机的容器部署和管理、服务发现、负载均衡和动态伸缩等一系列完整功能,可方便地进行大规模容器集群管理。云上应用程序在运行过程中,由于一些不确定因素(例如网络瞬间不可达、配置错误、程序内部错误等),经常导致出现一些异常状况。为此,k8s提供了一套完善的容器健康检查的探测机制。
通过阅读本文,读者可以了解k8s容器架构中探针的原理及配置方法,以及在探针探测失败时,快速定位问题的方向。
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_efd0c4dc-6725-11ec-9177-fa163eb4f6be.png)
k8s提供了以下两类检测不健康容器的方法,通过健康检查探针来检查容器的就绪或存活状态,以在集群层面保证业务容器的可用性。
1.存活检查(liveness probe,存活探针):使用此探针确认何时重启容器,可以通过此探针捕获到容器中应用程序本身的异常状况,并通过重启该容器尝试恢复正常。该探测机制相当于心跳机制。
2.就绪检查(readiness probe,就绪探针):使用此探针来确认容器是否已经启动完成,已经具备正常对外提供服务的条件,包括提供服务所依赖的外部条件。如果Pod处于非就绪状态,Pod不会被添加到Service的iptables转发规则中,流量不会转发到未就绪状态的Pod;只有当Pod已经就绪,相应Pod才会被添加到Service的iptables转发规则中。
两种类型的探针分别支持以下三种检查类型:
1.执行命令(ExecAction):在容器内执行指定的shell命令,如果命令返回0,说明容器运行状态正常;如果命名返回非0值,说明容器运行状态异常。
2.发送网络HTTP GET请求(HTTPGetAction):使用HTTP GET请求指定的URI,如果返回了成功状态码(2xx或3xx),kubelet会认为容器处于健康状态;如果返回了失败的状态码(除2xx和3xx外的状态码),则kubelet会认为容器处于异常状态。
3.测试TCP Socket连接(TCPSocketAction):使用TCP Socket连接容器中的指定端口,如果能够建立连接,kubelet会认为容器处于健康状态;如果无法建立连接,kubelet认为容器处于异常状态。
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_efefbfe0-6725-11ec-9177-fa163eb4f6be.png)
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_f00f01f2-6725-11ec-9177-fa163eb4f6be.png)
在容器中可以分别定义上述的存活性探针(livenessProbe)与就绪性探针(readinessProbe)。每种探针都可选用ExecAction、HTTPGetAction、TCPSocketAction的其中一种方法进行循环探测。两种探针根据自身方法进行探测到的结果,分别做相应的处置。
两种探针分别包含了以下五个可配置属性参数:
行为属性名称 | 默认值 | 最小值 | 备注 |
initialDelaySeconds | 0秒 | 0秒 | 探测延迟时长,容器启动后多久开始进行第一次探测工作。 |
timeoutSeconds | 1秒 | 1秒 | 探测的超时时长。 |
periodSeconds | 10秒 | 1秒 | 探测频度,频率过高会对pod带来较大的额外开销,频率过低则无法及时反映容器产生的错误。 |
failureThreshold | 3 | 1 | 处于成功状态时,探测连续失败几次可被认为失败。 |
successThreshold | 1 | 1 | 处于失败状态时,探测连续成功几次,被认为成功。 |
下图示例展示的是在容器中通过livenessProbe探针设置了TCPSocketAction探测,对容器内的8080端口进行TCP连接测试。容器启动60秒后即开始进行连接测试,TCP连接超过5秒没有响应记录一次失败结果,探测间隔周期为10秒。当前处于正常状态时,连续三次探测不通过则被认定是异常;当处于异常状态时,只要有一次探测通过即被认为是恢复正常。
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 10
failureThreshold: 3
successThreshold: 1
如下示例展示的是在容器中通过readinessProbe探针设置了HTTPGetAction探测,对容器的8080端口的/healthCheck地址进行周期性的HTTP请求。容器启动40秒后开始进行探测,探测周期为15秒,时长超过10秒没有响应记录一次失败结果。当前处于正常状态时,连续三次探测不通过被认定是异常;当处于异常状态时,只要有一次探测通过即被认为是恢复成功。
readinessProbe:
initialDelaySeconds: 40
timeoutSeconds: 10
periodSeconds: 15
failureThreshold: 3
successThreshold: 1
httpGet:
path: /healthCheck
port: 8080
scheme: HTTP
在httpGet属性段内,可设置HTTP探针的相应参数,解释如下:
行为属性名称 | 默认值 |
host | 连接的主机名,默认连接到Pod的IP,默认为localhost |
scheme | 连接使用的协议,默认我HTTP |
path | 访问HTTP server的接口 |
port | 访问的容器的端口号 |
如下示例展示的是在容器中通过livenessProbe探针设置了ExecAction探测,对容器内执行一条shell命令”sh -c zookeeper-ready 2181”进行验证探活,当shell命令返回码为0时即为成功。容器启动10秒后即开始进行连接测试,命令超时时间为5秒,每10秒周期性执行一次验证。当容器处于成功状态时,三次探测不通过被认为是探测失败;处于失败状态时,一次探测通过即被认为是探测成功。
livenessProbe:
exec:
command:
- sh
- -c
- zookeeper-ready 2181
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
为实际解决在应用上云过程中面临的疑惑和问题,经过对k8s容器探针机制的深入研究,结合云服务商的相关经验,整理了最佳实践供读者参考。
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_efefbfe0-6725-11ec-9177-fa163eb4f6be.png)
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_f00f01f2-6725-11ec-9177-fa163eb4f6be.png)
存活性探针和就绪性探针可支持的探测机制虽然相似,但两种探针在探测失败后的处置逻辑不同,因此应用上云时应为容器同时配置存活性探针与就绪性探针。
对于存活性探针,建议通过TCPAction对主要端口进行Socket探活,用于检测容器内进程的存活状态,或HTTPGetAction对应用接口进行HTTP探活。当该容器无法提供服务时,Kubernetes将会重启此容器。
当容器端口正常打开,但应用服务无法正常访问,或出现“假死”现象时,仅凭借容器端口正常打开无法保证应用可正常对外提供服务,因此需要使用就绪性探针配合进行探测。对于云上的Java应用,推荐通过HTTPGetAction方法进行就绪性检测,应用方需提供一个就绪性检测接口用于检测,该接口应包含应用程序的具体业务逻辑。
当应用与外部数据库、第三方系统有交互时,为避免当外部第三方系统或数据库出现异常时而导致的应用假死,探测接口中应包含与外部系统之间的交互。当默认连续三次探测失败时(HTTP请求的响应码不属于2xx~3xx),Kubernetes会将该容器移除路由表,直到该容器探测再次成功时,该容器再次对外提供服务。
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_efefbfe0-6725-11ec-9177-fa163eb4f6be.png)
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_f00f01f2-6725-11ec-9177-fa163eb4f6be.png)
在示例应用中,正常服务监听的端口为8080,在应用侧开发了两个用于就绪性检测的接口,/check1接口中访问了一个正常的外部系统,/check2中访问了一个异常的外部系统,用于模拟应用假死现象。
应用同时配置了存活性探针与就绪性探针,存活性探针使用TCPSocketAction检测方法,就绪性探针使用HTTPGetAction检测方法,探针定义的yaml段落如下:
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 20
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 10
readinessProbe:
failureThreshold: 3
httpGet:
path: /check1
port: 8080
scheme: HTTP
initialDelaySeconds: 20
periodSeconds: 15
successThreshold: 1
timeoutSeconds: 10
当应用正常访问时,pod状态如下所示,容器的ready状态为1/1,restarts数量为0。
修改应用程序,在程序加载时编写一个未被捕获的除零异常。当应用加载至内存时,抛出错误,这时应用的8080端口无法正常提供服务,pod的状态显示为:
因容器中运行的程序发生故障,可理解为容器的主进程无法正常工作,pod的状态变为CrashLoopBackOff,在15分钟内容器重启了7次。需注意的是,存活性探针探测失败导致的是容器自身的重启,而非pod自身的重启,因此pod名称不会改变。查看该pod的具体事件信息,可看到以下报错:对8080端口的存活性探测失败,容器重启。
将就绪性探针的探测路径改为/check2,模拟应用假死现象。Pod状态显示为:
当前容器已经进入Running状态,容器启动后20秒即开启就绪性检测,但容器已启动5分钟,READY仍为0/1(未就绪),这是明显的就绪性探测失败的现象。查看该pod具体的时间信息,可看到以下报错:对8080端口的/check2接口探测失败。
这时该pod已从路由表中被移除,无法对外提供服务。
当检测失效时,可修改yaml,先删除container中配置的探针对象,后进入容器中通过curl命令手动进行排查。
curl -I localhost:{port}/path
通过对容器8080端口的/check1和/check2两接口分别检测,/check1接口可正常返回200响应码,而/check2接口返回500响应码,表示对容器8080 端口的/check1接口进行HTTPGetAction探测,容器可正常工作。
存活性探针关注于应用程序本身的存活状况。当存活性探针失效发生了容器重启时,应通过排查容器中应用日志、检查pod事件信息等方式进行排查。
而就绪性探针应更关注于应用系统所提供服务的可用性。一个应用系统在对外提供服务时,通常会频繁与外部第三方系统或数据库进行交互,因此当就绪性探针失效时,应根据就绪性探针的接口逻辑,依次检查外部系统和本应用系统的日志信息。
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_f2077836-6725-11ec-9177-fa163eb4f6be.png)
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_f2332d64-6725-11ec-9177-fa163eb4f6be.png)
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_f2614474-6725-11ec-9177-fa163eb4f6be.png)
顾问:许国平 李湘宜
罗学平 刘德清 张刚
总编:孙鹏晖
编辑:韩翠娟
美编:白羽
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_f2614474-6725-11ec-9177-fa163eb4f6be.png)
长按二维码,关注我们吧!
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_f2614474-6725-11ec-9177-fa163eb4f6be.png)
-本文为“数风云”第32期文章;
-转载本公众号文章请联系我们;
-欢迎来稿:请按“题目-作者”格式命名发送到sunpenghui@abchina.com。
![](https://oss-emcsprod-public.modb.pro/wechatSpider/modb_20211227_f2614474-6725-11ec-9177-fa163eb4f6be.png)