文档首页/ 云容器实例 CCI/ 开发指南/ Pod/ 存活探针(liveness probe)
更新时间:2024-02-23 GMT+08:00

存活探针(liveness probe)

存活探针

Kubernetes提供了自愈的能力,具体就是能感知到容器崩溃,然后能够重启这个容器。但是有时候例如Java程序内存泄漏了,程序无法正常工作,但是JVM进程却是一直运行的,对于这种应用本身业务出了问题的情况,kubernetes提供了liveness probe机制,通过检测容器响应是否正常来决定是否重启,这是一种很好的健康检查机制。

毫无疑问,每个pod最好都定义liveness probe,否则Kubernetes无法感知Pod是否正常运行。

当前云容器实例支持如下两种探测机制。

  • HTTP GET:向容器发送HTTP GET请求,如果probe收到2xx或3xx,说明容器是健康的。

    需要为pod配置以下annotation使超时时间(timeoutSeconds)生效:

    cci.io/httpget-probe-timeout-enable:"true"

    具体请参见Liveness Probe高级配置样例。

  • Exec:probe执行容器中的命令并检查命令退出的状态码,如果状态码为0则说明健康。

HTTP GET

HTTP GET方式是最常见的探测方法,其具体机制是向容器发送HTTP GET请求,如果probe收到2xx或3xx,说明容器是健康的,定义方法如下所示。

apiVersion: v1
kind: Pod
metadata:
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:           # liveness probe
      httpGet:               # HTTP GET定义
        path: /healthz
        port: 8080

创建这个Pod。

$ kubectl create -f liveness-http.yaml -n $namespace_name
pod/liveness-http created

如上,这个probe往容器的8080端口发送HTTP GET请求,上面的程序会在第五次请求会返回500状态码,这时Kubernetes会去重启容器。

查看Pod详情。

$ kubectl describe po liveness-http -n $namespace_name
Name:         liveness-http
......
Containers:
  container-0:
    ......
    State:          Running
      Started:      Mon, 12 Nov 2018 22:57:28 +0800
    Last State:     Terminated
      Reason:       Error
      Exit Code:    137
      Started:      Mon, 12 Nov 2018 22:55:40 +0800
      Finished:     Mon, 12 Nov 2018 22:57:27 +0800
    Ready:          True
    Restart Count:  1
    Liveness:       http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3
......
Events:
  Type     Reason     Age                 From               Message
  ----     ------     ----                ----               -------
  Normal   Scheduled  3m5s                default-scheduler  Successfully assigned default/pod-liveness to node2
  Normal   Pulling    74s (x2 over 3m4s)  kubelet, node2     pulling image "pod-liveness"
  Normal   Killing    74s                 kubelet, node2     Killing container with id docker://container-0:Container failed liveness probe.. Container will be killed and recreated.

可以看到Pod当前状态是Running,Last State是Terminated,Restart Count为1,说明已经重启1次,另外从事件中也可以看到 Killing container with id docker://container-0:Container failed liveness probe.. Container will be killed and recreated.

另外,容器Kill后会重新创建一个新容器,不只是之前的容器重启。

Exec

Exec即执行具体命令,具体机制是probe执行容器中的命令并检查命令退出的状态码,如果状态码为0则说明健康,定义方法如下所示。

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:           # liveness probe
      exec:                  # Exec定义
        command:
        - cat
        - /tmp/healthy

上面定义在容器中执行cat /tmp/healthy命令,如果成功执行并返回0,则说明容器是健康的。

Liveness Probe高级配置

上面liveness-http的describe命令回显中有如下行。

Liveness: http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3

这一行表示liveness probe的具体参数配置,其含义如下:

  • delay=0s 表示容器启动后立即开始探测,没有延迟时间
  • timeout=1s 表示容器必须在1s内做出相应反馈给probe,否则视为探测失败
  • period=10s 表示每10s探测一次
  • #success=1 表示探测连续1次成功表示成功
  • #failure=3 表示探测连续3次失败后会重启容器

这些是创建时默认设置的,您也可以手动配置,如下所示。

apiVersion: v1
kind: Pod
metadata:
  name: liveness-http
spec:
  template:
    metadata:
      annotations:
        cci.io/httpget-probe-timeout-enable:"true"
  containers:
  - image: k8s.gcr.io/liveness
    livenessProbe:
      httpGet:
        path: /
        port: 8080
      initialDelaySeconds: 10    # 容器启动后多久开始探测
      timeoutSeconds: 2          # 表示容器必须在2s内做出相应反馈给probe,否则视为探测失败
      periodSeconds: 30          # 探测周期,每30s探测一次
      successThreshold: 1        # 连续探测1次成功表示成功
      failureThreshold: 3        # 连续探测3次失败表示失败

initialDelaySeconds一般要设置大于0,这是由于很多情况下容器虽然启动成功,但应用就绪也需要一定的时间,需要等就绪时间之后才能返回成功,否则就会导致probe经常失败。

另外failureThreshold可以设置多次循环探测,这样在实际应用中健康检查的程序就不需要多次循环,这一点在开发应用时需要注意。

配置有效的Liveness Probe

  • liveness probe应该检查什么

    一个好的liveness probe应该检查应用内部所有关键部分是否健康,并使用一个专有的URL访问,例如 /health,当访问 /health 时执行这个功能,然后返回对应结果。这里要注意不能做鉴权,不然 probe 就会一直失败导致陷入重启的死循环。

    另外检查只能限制在应用内部,不能检查依赖外部的部分,例如当前端web server不能连接数据库时,这个就不能看成web server不健康。

  • liveness probe必须轻量

    liveness probe不能占用过多的资源,且不能占用过长的时间,否则所有资源都在做健康检查,这就没有意义了。例如Java应用,就最好用HTTP GET方式,如果用 Exec 方式,JVM启动就占用了非常多的资源。