天天看点

Kubernetes之健康检查与服务依赖处理

本文讲的是<b>Kubernetes之健康检查与服务依赖处理</b>【编者的话】对线上业务来说,保证服务的正常稳定是重中之重,对故障服务的及时处理避免影响业务以及快速恢复一直是开发运维的难点。Kubernetes提供了健康检查服务,对于检测到故障服务会被及时自动下线,以及通过重启服务的方式使服务自动恢复。而对于服务依赖,无论资源描述文件是pod, rc或deployment, 对应yaml文件中描述仅是container启动顺序而非Container中服务启动顺序,Kubernetes提供了的Init Container,可处理服务之间依赖。

<a href="http://dockone.io/article/2526">【3 天烧脑式基于Docker的CI/CD实战训练营 | 北京站】本次培训围绕基于Docker的CI/CD实战展开,具体内容包括:持续集成与持续交付(CI/CD)概览;持续集成系统介绍;客户端与服务端的 CI/CD 实践;开发流程中引入 CI、CD;Gitlab 和 CI、CD 工具;Gitlab CI、Drone 的使用以及实践经验分享等。</a>

简单例子说明什么是健康检查以及服务依赖,比如一个应用分别有A、B、 C 3个服务,健康检查就是如何确定A、B与C所在的Container处于运行状态且服务工作正常;而对于服务依赖,假设服务A必须在服务B成功启动之前启动,而服务B必须在服务C成功启动之前启动,即启动顺序为A-&gt;B-&gt;C。

Kubernetes之健康检查与服务依赖处理

Readness探针:主要用于判断服务是否已经正常工作,如果服务没有加载完成或工作异常,服务所在的Pod的IP地址会从服务的endpoints中被移除,也就是说,当服务没有ready时,会将其从服务的load balancer中移除,不会再接受或响应任何请求。

无论对于Readness或Liveness探针,Handler均支持以下3种类型:ExecAction, TCPSocketAction, HTTPGetAction。每种类型说明与举例如下:

探针检查结果分为3种情况:

成功(Success):通过检查。

失败(Failure):检查失败。

未知(Unknown):检查未知,需要人工干预。

1. 如果服务的健康检查(readiness)失败,故障的服务实例从service endpoint中下线,外部请求将不会再转发到该服务上,一定程度上保证正在提供的服务的正确性,如果服务自我恢复了(比如网络问题),会自动重新加入service endpoint对外提供服务。

2. 另外,如果设置了Container(liveness)的探针,对故障服务的Container(liveness)的探针同样会失败,container会被kill掉,并根据原设置的container重启策略,系统倾向于在其原所在的机器上重启该container、或其他机器重新创建一个pod。

3. 由于上面的机制,整个服务实现了自身可用与自动恢复。

1. 建议对全部服务同时设置服务(readiness)和Container(liveness)的健康检查

2. 通过TCP对端口检查形式(TCPSocketAction),仅适用于端口已关闭或进程停止情况。因为即使服务异常,只要端口是打开状态,健康检查仍然是通过的。

3. 基于第二点,一般建议用ExecAction自定义健康检查逻辑,或采用HTTP Get请求进行检查(HTTPGetAction)。

4. 无论采用哪种类型的探针,一般建议设置检查服务(readiness)的时间短于检查Container(liveness)的时间,也可以将检查服务(readiness)的探针与Container(liveness)的探针设置为一致。目的是故障服务先下线,如果过一段时间还无法自动恢复,那么根据重启策略,重启该container、或其他机器重新创建一个pod恢复故障服务。

一个pod中可以有一或多个Init Container。Pod的中多个Init Container启动顺序为yaml文件中的描述顺序,且串行方式启动,下一个Init/app Container必须等待上一个Init Container完成后方可启动。例如,Init Container1-&gt; ... -&gt; Init Containern -&gt; app Container[1-n]。Init Container1成功启动并且完成后,后续的Init Container和app Container才可以启动,如Init Container启动或执行相关检查失败,后续的init Container和应用Container将不会被执行启动命令。

因此可利用Init Container来判断app Container中被依赖的服务是否成功启动。如被依赖的app Container服务启动失败,那么利用Init Container启动失败可以阻止后续app Container服务的启动。

前文已经提及,由于Init Container必须在app Containers启动之前完成,所以可利用其特性,用作服务依赖处理。比如某一个服务A,需依赖db或memcached,那么可以利用服务A pod的Init Container判断db/memcached是否正常提供服务,如果启动服务失败或工作异常,设置Init Container启动失败,那么pod中的服务A就不会被启动了。

应用镜像因安全原因等没办法安装或运行的工具,可放到Init Container中运行。另外,Init Container独立于业务服务,与业务无关的工具如sed, awk, python, dig等也可以按需放到Init Container之中。最后,Init Container也可以被授权访问应用Container无权访问的内容。

serviceA服务依赖serviceB,而serviceB采用上文提及Readness探针的HTTPGetAction Handler。

如果启动serviceA Pod时,serviceB还没有ready,通过kubectl get po -o wide查看pod处于Init状态

通过kubectl describe po serviceA-3071943788-g03wt查看,可以看出app Container的启动时在init Container启动并成功完成后:

查看docker Container log,init Container正在按照预先的设定,每3秒轮询验证serviceB健康检查点serviceB:portB/pathB/

等待一段时间后,再次通过kubectl get po -o wide查看pod处于Running状态

如果pod重启了,所有init Container都需重新运行。Kubernetes禁止Init Container使用readiness探针,可以使用Pod定义 activeDeadlineSeconds 和 Container的 livenessProbe 防止 init containers 一直重复失败. activeDeadlineSeconds 包含了 init container 启动的时间。

欢迎转载,请注明作者出处:张夏,FreeWheel Lead Engineer,DockOne社区

原文发布时间为:2017-08-13

本文来自云栖社区合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。

原文标题:Kubernetes之健康检查与服务依赖处理