本文我来讲解 Kubernetes 中的一个重要概念:容器的健康检查。

介绍

在 Kubernetes 中,你可以为 Pod 里的容器定义一个健康检查“探针”(Probe)。 这样,kubelet 就会根据这个 Probe 的返回值决定这个容器的状态,而不是直接以容器镜像是否运行(来自 Docker 返回的信息)作为依据。 这种机制,是生产环境中保证应用健康存活的重要手段。

k8s 主要有三种健康检查的探针:1) LivenessProbe 存活探针 2) ReadinessProbe 就绪探针 3) StartupProbe 启动探针

kubelet 使用存活探针来确定什么时候要重启容器。例如,存活探针可以探测到应用死锁(应用程序在运行,但是无法继续执行后面的步骤)情况。重启这种状态下的容器有助于提高应用的可用性,即使其中存在缺陷。

存活探针的常见模式是为就绪探针使用相同的低成本 HTTP 端点,但具有更高的 failureThreshold。这样可以确保在硬性终止 Pod 之前,将观察到 Pod 在一段时间内处于非就绪状态。

kubelet 使用就绪探针可以知道容器何时准备好接受请求流量,当一个 Pod 内的所有容器都就绪时,才能认为该 Pod 就绪。这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。若 Pod 尚未就绪,会被从 Service 的负载均衡器中剔除。

kubelet 使用启动探针来了解应用容器何时启动。如果配置了这类探针,你就可以控制容器在启动成功后再进行存活性和就绪态检查,确保这些存活、就绪探针不会影响应用的启动。启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉。

probe 介绍

接下来我来讲解用的较多的 2 个探针:1) LivenessProbe 存活探针 2) ReadinessProbe 就绪探针

LivenessProbe

许多应用由于长时间运行导致程序异常,需要重启服务才能继续正常使用,Kubernetes 提供了存活探针 (LivenessProbe) 来发现并处理这种情况。

我们先创建一个 pod, pod 的文件如下:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: nginx
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

在这个配置文件中,可以看到 Pod 中只有一个 Container。periodSeconds 字段指定了 kubelet 应该每 5 秒执行一次存活探测。initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒。kubelet 在容器内执行命令 cat /tmp/healthy 来进行探测。如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的。如果这个命令返回非 0 值,kubelet 会杀死这个容器并重新启动它。

容器启动时会执行 /bin/sh -c "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600" 在容器启动的前 30s /tmp/healthy 是存在的,30s 后这个文件被删掉了,导致存活探测失败,使得容器重启。

我们创建这个 pod ,过一会查看 pod 的事件,发现 pod30s 后由于文件删掉了后重启了。

img.png

还有一种方式是通过 http 的 get 请求来探测容器存活状态,我们定义一个新的 pod,如下:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: registry.k8s.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3

可以看到 kubelet 会每隔 3s 向容器的 http 接口发送请求,如果容器返回的状态码大于或等于 200 并且小于 400 都标示成功,其它状态码都标示失败,容器则会被杀死重启。

还有一种是存活探测方式是通过 TCP 检测来实现的,TCP 探测和 http 探测类似,TCP 探测是尝试连接相应的端口,如果连接成功则是就绪状态,

在 Kubernetes v1.24 版本新添加了一个 Grpc 存活探针,是根据前面文章讲述的 Grpc 健康检查协议来实现的,如果你的应用实现了 gRPC 健康检查协议,kubelet 可以配置为使用该协议来执行应用存活性检查。你必须启用 GRPCContainerProbe 特性配置才能配置依赖于 gRPC 的检查机制。

ReadinessProbe

有时候,应用会暂时性地无法为请求提供服务。例如,应用在启动时可能需要加载大量的数据或配置文件,或是启动后要依赖等待外部服务。在这种情况下,既不想杀死应用,也不想给它发送请求。Kubernetes 提供了就绪探针来发现并缓解这些情况。容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量。

就绪探针的配置和存活探针的配置相似。唯一区别就是要使用 readinessProbe 字段,而不是 livenessProbe 字段。

就绪和存活探测可以在同一个容器上并行使用。两者共同使用,可以确保流量不会发给还未就绪的容器,当这些探测失败时容器会被重新启动。

参考