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

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

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

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

健康检查

使用Liveness及Readness探针

  • Liveness探针:主要用于判断Container是否处于运行状态,比如当服务crash或者死锁等情况发生时,kubelet会kill掉Container, 然后根据其设置的restart policy进行相应操作(可能会在本机重新启动Container,或者因为设置Kubernetes QoS,本机没有资源情况下会被分发的其他机器上重新启动)。
  • Readness探针:主要用于判断服务是否已经正常工作,如果服务没有加载完成或工作异常,服务所在的Pod的IP地址会从服务的endpoints中被移除,也就是说,当服务没有ready时,会将其从服务的load balancer中移除,不会再接受或响应任何请求。

探针处理Handler类型

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

ExecAction:Container内部执行某个具体的命令,例子
TCPSocketAction:通过container的IP、port执行tcp进行检查, 例子
HTTPGetAction: 通过container的IP、port、path,用HTTP Get请求进行检查,例子

探针检查结果

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

  1. 成功(Success):通过检查。
  2. 失败(Failure):检查失败。
  3. 未知(Unknown):检查未知,需要人工干预。

健康检查总结

探针类型          说明                                 通过健康检查标准 
ExecAction       container内部执行shell命令            shell命令返回0
TCPSocketAction  通过container的IP、port执行tcp进行检查  port是否打开
HTTPGetAction    通过container的IP、port、path,       200<=返回值<400
                 用HTTP Get请求进行检查

服务可用性与自动恢复

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恢复故障服务。

服务依赖

理解Init Container

一个pod中可以有一或多个Init Container。Pod的中多个Init Container启动顺序为yaml文件中的描述顺序,且串行方式启动,下一个Init/app Container必须等待上一个Init Container完成后方可启动。例如,Init Container1-> ... -> Init Containern -> 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必须要在pod状态变为Ready之前完成,所以其不需要readiness探针。另外在资源的requests与limits上与普通Container有细微差别,详见 Resources,除以上2点外,Init Container与普通Container并无明显区别。

Init Containers用途

  1. 前文已经提及,由于Init Container必须在app Containers启动之前完成,所以可利用其特性,用作服务依赖处理。比如某一个服务A,需依赖db或memcached,那么可以利用服务A pod的Init Container判断db/memcached是否正常提供服务,如果启动服务失败或工作异常,设置Init Container启动失败,那么pod中的服务A就不会被启动了。
  2. 应用镜像因安全原因等没办法安装或运行的工具,可放到Init Container中运行。另外,Init Container独立于业务服务,与业务无关的工具如sed, awk, python, dig等也可以按需放到Init Container之中。最后,Init Container也可以被授权访问应用Container无权访问的内容。

Init Container处理服务依赖应用举例

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

spec:
  initContainers:
  - name: init-serviceA
    image: registry.docker.dev.fwmrm.net/busybox:latest
    command: ['sh', '-c', "curl --connect-timeout 3 --max-time 5 --retry 10 --retry-delay 5 --retry-max-time 60 serviceB:portB/pathB/"]
  containers:

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

NAME                        READY     STATUS    RESTARTS   AGE       IP          .l  NODE
serviceA-3071943788-8x27q            0/1       Init:0/1   0          20s       10.244.1.172   bjo-ep-svc-017.dev.fwmrm.net

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

Events:
FirstSeen LastSeen    Count   From                    SubObjectPath               Type        Reason  Message
--------- --------    -----   ----                    -------------               --------    ------  -------
25s       25s     1   default-scheduler                               Normal      ScheduledSuccessfully assigned serviceA-3071943788-g03wt to bjo-ep-dep-040.dev.fwmrm.net
25s       25s     1   kubelet, bjo-ep-dep-040.dev.fwmrm.net                       Normal      SuccessfulMountVolume   MountVolume.SetUp succeeded for volume "serviceA-config-volume"
25s       25s     1   kubelet, bjo-ep-dep-040.dev.fwmrm.net                       Normal      SuccessfulMountVolume   MountVolume.SetUp succeeded for volume "default-token-2c9j1"
24s       24s     1   kubelet, bjo-ep-dep-040.dev.fwmrm.net   spec.initContainers{init-myservice} Normal      Pulling pulling image "registry.docker.dev.fwmrm.net/ui-search-solr-data:latest"
24s       24s     1   kubelet, bjo-ep-dep-040.dev.fwmrm.net   spec.initContainers{init-myservice} Normal      Pulled  Successfully pulled image "registry.docker.dev.fwmrm.net/busybox:latest"
24s       24s     1   kubelet, bjo-ep-dep-040.dev.fwmrm.net   spec.initContainers{init-myservice} Normal      Created Created container
24s       24s     1   kubelet, bjo-ep-dep-040.dev.fwmrm.net   spec.initContainers{init-myservice} Normal      Started Started container
20s       20s     1   kubelet, bjo-ep-dep-040.dev.fwmrm.net   spec.containers{is}         Normal      Pulling pulling image "registry.docker.dev.fwmrm.net/infra/is:latest"
20s       20s     1   kubelet, bjo-ep-dep-040.dev.fwmrm.net   spec.containers{is}         Normal      Pulled  Successfully pulled image "registry.docker.dev.fwmrm.net/infra/is:latest"
20s       20s     1   kubelet, bjo-ep-dep-040.dev.fwmrm.net   spec.containers{is}         Normal      Created Created container
19s       19s     1   kubelet, bjo-ep-dep-040.dev.fwmrm.net   spec.containers{is}         Normal      Started Started container

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

docker logs 4fd58bf54f76
waiting for serviceB service
waiting for serviceB service
... ...

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

NAME                        READY     STATUS    RESTARTS   AGE       IP          .l  NODE
serviceA-3071943788-g03wt   1/1       Running   0          1m        10.244.2.68   bjo-ep-dep-040.dev.fwmrm.net

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

参考资料

Container Lifecycle Hooks: https://kubernetes.io/docs/con ... ooks/
Attach Handlers to Container Lifecycle Events: https://kubernetes.io/docs/tas ... vent/
Init Containers: https://kubernetes.io/docs/con ... ners/
Init Container and Probe: https://blog.giantswarm.io/wai ... etes/
Configure Pod Initialisation: https://kubernetes.io/docs/tas ... ainer
Debug Init Containers: https://kubernetes.io/docs/tas ... ners/
Delaying the deployment of our stubborn service: https://blog.giantswarm.io/wai ... etes/

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

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

本文作者:张夏

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

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

时间: 2024-09-26 11:59:20

Kubernetes之健康检查与服务依赖处理的相关文章

Java微服务开发指南 -- 使用Docker和Kubernetes构建可伸缩的微服务

使用Docker和Kubernetes构建可伸缩的微服务     从现在开始,我们将从更高的维度讨论微服务,涵盖了组织敏捷性.设计和依赖的思考.领域驱动设计以及Promise理论.当我们深入使用之前介绍的三个流行的微服务框架:Spring Boot.Dropwizard和WildFly Swarm,我们能够使用它们开箱即用的能力去构建一个暴露或者消费REST服务的应用,能够使用外部环境对应用进行配置,可以打包成一个可执行的jar,同时提供Metrics信息,但这些都是围绕着一个微服务实例.当我们

Docker 容器健康检查机制

在分布式系统中,经常需要利用健康检查机制来检查服务的可用性,防止其他服务调用时出现异常. 对于容器而言,最简单的健康检查是进程级的健康检查,即检验进程是否存活.Docker Daemon会自动监控容器中的PID1进程,如果docker run命令中指明了restart policy,可以根据策略自动重启已结束的容器.在很多实际场景下,仅使用进程级健康检查机制还远远不够.比如,容器进程虽然依旧运行却由于应用死锁无法继续响应用户请求,这样的问题是无法通过进程监控发现的. 在Kubernetes提供了

SLB配置健康检查/会话保持

  现在,您已经定义好了一个SLB实例的名称.服务协议及服务端口号.接下来进行健康检查及会话保持的相关配置.整个负载均衡服务将依照您的配置自动运行,并对作为负载均衡服务的云服务器进行健康检查.如果某一云服务器出现故障,它会自动将该云服务器从您的负载均衡服务中移除,而当该云服务器恢复正常运行时,健康检查服务会将其自动加入您的负载均衡服务.为了为了保证用户会话能转发到固定的云服务上,您可以开启会话保持功能,负载均衡服务将会把来自同一客户端的访问请求分发到同一台云服务器上进行处理. HTTP协议配置

负载均衡健康检查的使用误区和最佳实践

本期分享专家:隽勇, 曾就职微软,擅长网络.Windows相关技术,网络问题的终结者,现就职阿里云专注于弹性计算方面的技术研究,"对技术负责,更对用户负责" 针对客户反馈的问题,不但要解决,还要总结分析,隽勇针对SLB问题进行了分析总结,发现大家遇到的很多负载均衡(简称 SLB)异常问题都与健康检查配置相关.不合理的健康检查策略可能会导致很多问题出现: 例如: · 健康检查间隔设置过长,无法准确发现后端 ECS 出现服务不可用,造成业务中断. · 使用 HTTP 模式健康检查,未合理配

nignx健康检查

健康检查分为tcp方式和http方式      tcp方式如果服务假死,则会继续分发请求,造成很大一部分用户无法访问,比如一个tomcat server假死,但8080端口并没有关闭     http方式则服务假死,即可剔除该分支

lvs健康检查

健康检查分为tcp方式和http方式      tcp方式如果服务假死,则会继续分发请求,造成很大一部分用户无法访问     http方式则服务假死,即可剔除该分支

ORAchk-数据库健康检查

ORAchk-数据库健康检查  原文地址:ORAchk-数据库健康检查 作者:paulyibinyi ORAchk 之前被称为RACcheck,后来它的检查范围进行了扩展,改名为了ORAchk,它是在数据库系统进行健康检查的一个专用工具,这个工具主要用来检查软件的配置是否符合要求以及一些最佳实践是否被应用了.通过这个工具,用户可以很方便地.自动化地对自己的系统进行健康检查和评估.  ORAchk 能够检查的软件主要有:OS.Oracle Clusterware (CRS). Grid Infra

我的oracle健康检查报告

       最近一直想用sql来生成oracle的健康检查报告,这样看起来一目了然,经过网上搜资料加自己整理终于算是成型了,部分结果如下图所示, 具体参考附件,恳请广大网友看看是否还有需要添加的地方. DB_healthcheck_by_lhr_ORADG11G_20150826160539.zip ORADG11G 数据库巡检报告 Copyright (c) 2015-2100 (http://blog.itpub.net/26736162) lhrbest. All rights rese

我的oracle健康检查报告(三)

       之前分别在http://blog.itpub.net/26736162/viewspace-1783297/ 和 http://blog.itpub.net/26736162/viewspace-1805156/ 中发布了我的健康检查报告(oracle巡检报告)第一版和第二版本的预览版,经过最近一段时间的改造,从界面到内容上又有了新的突破,具体参考附件,恳请广大网友看看是否还有需要添加的地方,以便更加完善这个报告内容,该脚本也耗费了我巨大精力,请大家注意版权,所有与此相似的请注明出