Loading

k8s探针

健康检查(Health Check)用于检测应用实例是否正常工作,是保障业务可用性的一种传统机制,一般用于负载均衡下的业务,如果实例的状态不符合预期,将会把该实例“摘除”,不承担业务流量。

Kubernetes中的健康检查使用存活性探针(liveness probes)和就绪性探针(readiness probes)来实现,对于慢启动容器还专门设有启动探针(startup Probe)。

探测方式

在讨论探针具体的功能和目的之前,先了解一下探针的具体探测方式。无论是存活探针、就绪探针还是启动探针的探测都是由kubelet执行的,K8S提供了三种探测容器的方式:

  • exec:在容器内执行shell命令,根据命令退出状态码是否为0判定成功失败;

    exec:									     #探针类型为exec探针
      command:
      - cat										 #表示cat /usr/share/nginx/html/index.html文件,根据命令执行
      - /usr/share/nginx/html/index.html	     #结果返回状态是否非0来表示探针状态
    
  • httpGet:根据容器IP地址、端口号、路径发送http get请求,返回200-400范围内的状态码表示成功;(生产环境建议使用这种)

    httpGet:							#探针类型为httpGet探针
    #  host: 10.244.0.49			    #指定主机,默认是pod的ip,一般省略不写
       path: /							#路径
       port: 80							#端口
    
  • tcpSocket:与容器IP地址、端口建立TCP Socket链接,能建立则表示成功;

    tcpSocket: 								#探针类型为tcpSocket探针
    #  host: 10.244.0.49			    		#指定主机,默认是pod的ip,一般省略不写
       port: 80									#探测与80端口是否能成功建立tcp链接
    

探针

存活探针

在kubernetes中可以通过存活探针检查容器是否还在运行,可以为pod中的每个容器单独定义存活探针,而每个node节点上的组件kubelet将负责定期执行探针,如果探测失败,将杀死容器,并根据restartPolicy策略来决定是否重启容器。

在exec、httpGet和tcpSocket三种探测方式的基础上,存活探针还有以下几个附加属性:

  • initialDelaySeconds:表示在容器启动后延时多久秒才开始探测;
  • periodSeconds:表示执行探测的频率,即间隔多少秒探测一次,默认间隔周期是10秒,最小1秒;
  • timeoutSeconds:表示探测超时时间,默认1秒,最小1秒,表示容器必须在超时时间范围内做出响应,否则视为本次探测失败;
  • successThreshold:表示最少连续探测成功多少次才被认定为成功,默认是1,对于liveness必须是1,最小值是1;
  • failureThreshold:表示连续探测失败多少次才被认定为失败,默认是3,连续3次失败,k8s 将根据pod重启策略对容器做出决定;

[!NOTE]

定义存活探针时,一定要设置initialDelaySeconds属性,该属性为初始延时,如果不设置,默认容器启动时探针就开始探测了,这样可能会存在应用程序还未启动就绪,就会导致探针检测失败,kubelet就会根据pod重启策略杀掉容器然后再重新创建容器的莫名其妙的问题。

nginx应用,httpGet探活:

apiVersion: apps/v1
kind: ReplicaSet
metadata: 
  name: rs-nginx-http
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-rs
    matchExpressions:
      - {key: env, operator: In, values: [dev]}
  template:
     metadata:
       labels:
         app: nginx-rs
         env: dev
     spec:
         containers:
         - image: nginx:1.7.9
           name: nginx-container
           ports:
           - containerPort: 80
           livenessProbe:						#为容器定义一个存活探针
             httpGet:							#探针类型为httpGet探针
       #       host: 10.244.0.49			    #指定主机,默认是pod的ip,一般省略不写
               path: /							#路径
               port: 80							#端口
             initialDelaySeconds: 15			#初始延时时间为15s
             periodSeconds: 5					#探测周期
             timeoutSeconds: 2					#超时时间
             failureThreshold: 9				#失败次数

就绪探针

当一个pod启动后,就会立即加入service的endpoint ip列表中,并开始接收到客户端的链接请求,假若此时pod中的容器的业务进程还没有初始化完毕,那么这些客户端链接请求就会失败,为了解决这个问题,kubernetes提供了就绪探针来解决这个问题的。

在pod中的容器定义一个就绪探针,就绪探针周期性检查容器,如果就绪探针检查失败了,说明该pod还未准备就绪,不能接受客户端链接,则该pod将从endpoint列表中移除,被剔除了service就不会把请求分发给该pod,然后就绪探针继续检查,如果随后容器就绪,则再重新把pod加回endpoint列表。
nginx应用,httpGet就绪探测:

apiVersion: apps/v1
kind: ReplicaSet
metadata: 
  name: rs-nginx-http
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-rs
    matchExpressions:
      - {key: env, operator: In, values: [dev]}
  template:
     metadata:
       labels:
         app: nginx-rs
         env: dev
     spec:
         containers:
         - image: nginx:1.7.9
           name: nginx-container
           ports:
           - containerPort: 80
           readinessProbe:						#为容器定义一个存活探针
             httpGet:							#探针类型为httpGet探针
       #       host: 10.244.0.49			    #指定主机,默认是pod的ip,一般省略不写
               path: /reader     				#路径
               port: 80							#端口
             initialDelaySeconds: 10    # 容器启动后多久开始探测
             timeoutSeconds: 2          # 表示容器必须在2s内做出相应反馈给probe,否则视为探测失败
             periodSeconds: 30          # 探测周期,每30s探测一次
             successThreshold: 1        # 连续探测1次成功表示成功
             failureThreshold: 3        # 连续探测3次失败表示失败

启动探针

对于慢启动容器来说,存活探针和就绪探针这两种健康检查机制不太好用。

慢启动容器:指需要大量时间(一到几分钟)启动的容器。启动缓慢的原因可能有多种:

  • 长时间的数据初始化:只有第一次启动会花费很多时间。
  • 负载很高:每次启动都花费很多时间。
  • 节点资源不足/过载:即容器启动时间取决于外部因素。

这种容器的主要问题在于,在存活探针失败之前,应该给它们足够的时间来启动它们。对于这种问题,现有的机制的处理方式为:

  • 方法一:livenessProbe中把延迟初始时间 initialDelaySeconds 设置的很长,以允许容器启动(即initialDelaySeconds大于平均启动时间)。虽然这样可以确保 livenessProbe不会检测失败,但是不知道 initialDelaySeconds 应该配置为多少,因为启动时间不是一个固定值。另外,因为 livenessProbe 在启动过程还没运行,因此 Pod 得不到反馈,Events 看不到内容,如果 initialDelaySeconds 是 10 分钟,那这 10 分钟内你不知道在发生什么。
  • 方法二:增加 livenessProbe 的失败次数。即 failureThreshold*periodSeconds 的乘积足够大,这样可以挺过容器启动,虽然简单粗暴,但是在容器在初次成功启动后,由于livenessProbe 的失败次数过大,就算容器死锁或以其他方式挂起,livenessProbe 也会不断探测到,这样就失去了存活检查的意义。

[!NOTE]

livenessProbe的设计是为了在 Pod 启动成功后进行健康探测,最好前提是 Pod 已经启动成功,在启动阶段的多次失败是没有意义的。

以上两种方式都可以对慢启动容器进行监控检查,但都不够优雅。因此官方提出了一种新的探针:即startupProbe,startupProbe并不是一种新的数据结构,他完全复用了livenessProbe,只是名字改了下,多了一种概念。

startupProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 30
  periodSeconds: 10

这个配置的含义是:

startupProbe首先检测,该应用程序最多有5分钟(30 * 10 = 300s)完成启动。一旦startupProbe成功一次,livenessProbe将接管,以对后续运行过程中容器死锁提供快速响应。如果startupProbe从未成功,则容器将在300秒后被杀死。

探针对比

如果不特意配置这三种健康检查机制,Kubernetes 将采取的默认机制,即通过判断容器启动主进程的返回值是否为零来判断探测是否成功。

startupProbe 完全复用了 livenessProbe,只是名字改了下,多了一种概念,startupProbe常用于慢启动程序,启动探针只在容器启动期间起作用,在容器成功启动后*不会*继续执行定期的监控检查。

Liveness 探测和 Readiness 探测配置方法完全一样,支持的配置参数也一样。不同之处在于探测失败后的行为:Liveness 探测是重启容器;Readiness 探测则是将容器设置为不可用,不接收 Service 转发的请求。

Liveness 探测和 Readiness 探测是独立执行的,二者之间没有依赖,所以可以单独使用,也可以同时使用。

用 Liveness 探测判断容器是否需要重启以实现自愈;用 Readiness 探测判断容器是否已经准备好对外提供服务。Readiness可用于指定容器启动后,判断容器各服务是否已正常启动(如启动脚本执行后写指定内容至特定文件)。

posted @ 2025-11-14 17:24  VitoChen  阅读(10)  评论(0)    收藏  举报