kubernetes 存活、就绪和启动探针

2023/2/20 kubernetes

kubernetes 存活、就绪和启动探针详解

# kubernetes 存活、就绪和启动探针

探针作用于容器,分为存活(Liveness)、就绪(Readiness)和启动(Startup)探针

# 一、存活(Liveness)探针

kubelet 使用存活探针来确定什么时候要重启容器。

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

# 1.1 定义存活命令

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness
spec:
  containers:
  - name: liveness
    image: registry.k8s.io/busybox
    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

initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒; periodSeconds 字段指定了 kubelet 应该每 5 秒执行一次存活探测。

如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的; 如果这个命令返回非 0 值,kubelet 会杀死这个容器并重新启动它。

# 1.2 定义存活态 HTTP 请求接口

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: 5
      periodSeconds: 5

initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒; periodSeconds 字段指定了 kubelet 应该每 5 秒执行一次存活探测。

kubelet 会向容器内运行的服务(服务在监听 8080 端口)发送一个 HTTP GET 请求来执行探测。

如果服务器上 /healthz 路径下的处理程序返回成功代码(200 <= code < 400),则 kubelet 认为容器是健康存活的; 如果处理程序返回失败代码,则 kubelet 会杀死这个容器并将其重启。

# 1.3 定义 TCP 的存活探测

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: registry.k8s.io/goproxy:0.1
    ports:
    - containerPort: 8080
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5

initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒; periodSeconds 字段指定了 kubelet 应该每 5 秒执行一次存活探测。

kubelet 会尝试在指定端口和容器建立套接字链接。

如果能建立连接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的。

# 1.4 定义 gRPC 存活探针

如果你的应用实现了 gRPC 健康检查协议, kubelet 可以配置为使用该协议来执行应用存活性检查。 你必须启用 GRPCContainerProbe 特性门控 才能配置依赖于 gRPC 的检查机制。

apiVersion: v1
kind: Pod
metadata:
  name: etcd-with-grpc
spec:
  containers:
  - name: etcd
    image: registry.k8s.io/etcd:3.5.1-0
    command: [ "/usr/local/bin/etcd", "--data-dir",  "/var/lib/etcd", "--listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls", "http://127.0.0.1:2379", "--log-level", "debug"]
    ports:
    - containerPort: 2379
    livenessProbe:
      grpc:
        port: 2379
      initialDelaySeconds: 5
      periodSeconds: 5

initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒; periodSeconds 字段指定了 kubelet 应该每 5 秒执行一次存活探测。

使用 gRPC 探针,必须配置 port 属性。如果健康状态端点配置在非默认服务之上, 你还必须设置 service 属性。

与 HTTP 和 TCP 探针不同,gRPC 探测不能使用命名端口或定制主机.

配置问题(例如:错误的 port 和 service、未实现健康检查协议) 都被认作是探测失败

# 二、就绪(Readiness)探针

kubelet 使用就绪探针可以知道容器何时准备好接受请求流量。

当一个 Pod 内的所有容器都就绪时,才能认为该 Pod 就绪。 这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。 若 Pod 尚未就绪,会被从 Service 的负载均衡器中剔除。

存活探针 不等待 就绪性探针成功。 如果要在执行存活探针之前等待,应该使用 initialDelaySeconds 或 startupProbe。

# 2.1 定义存活态 HTTP 请求接口

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
    - name: liveness
      image: registry.k8s.io/liveness
      args:
        - /server
      ports:
      - name: liveness-port
        containerPort: 8080
        hostPort: 8080
      readinessProbe:
        httpGet:
          path: /healthz
          port: 8080
        failureThreshold: 5
        periodSeconds: 5
      livenessProbe:
        httpGet:
          path: /healthz
          port: 8080
        failureThreshold: 5
        periodSeconds: 5

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

# 三、启动(Startup)探针

kubelet 使用启动探针来了解应用容器何时启动。

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

使用相同的命令来设置启动探测,针对 HTTP 或 TCP 检测,可以通过将 failureThreshold * periodSeconds 参数设置为足够长的时间来应对糟糕情况下的启动时间

# 3.1 定义存活态 HTTP 请求接口

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
    - name: liveness
      image: registry.k8s.io/liveness
      args:
        - /server
      ports:
      - name: liveness-port
        containerPort: 8080
        hostPort: 8080
      livenessProbe:
        httpGet:
          path: /healthz
          port: 8080
        failureThreshold: 5
        periodSeconds: 5
      startupProbe:
        httpGet:
          path: /healthz
          port: 8080
        failureThreshold: 5
        periodSeconds: 5

应用程序将会有最多 25 秒(5 * 5 = 25s)的时间来完成其启动过程,如果启动探测一直没有成功,容器会在 300 秒后被杀死,并且根据 restartPolicy 来执行进一步处置。

一旦启动探测成功一次,存活探测任务就会接管对容器的探测,对容器死锁作出快速响应。

# 四、配置探针

# 4.1 通用配置字段

  • initialDelaySeconds: 容器启动后要等待多少秒后才启动启动、存活和就绪探针, 默认是 0 秒,最小值是 0。
  • periodSeconds:执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1。
  • timeoutSeconds:探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。
  • successThreshold:探针在失败后,被视为成功的最小连续成功数。默认值是 1。 存活和启动探测的这个值必须是 1。最小值是 1。
  • failureThreshold:探针连续失败了 failureThreshold 次之后, Kubernetes 认为总体上检查已失败:容器状态未就绪、不健康、不活跃。 对于启动探针或存活探针而言,如果至少有 failureThreshold 个探针已失败, Kubernetes 会将容器视为不健康并为这个特定的容器触发重启操作。 kubelet 会考虑该容器的 terminationGracePeriodSeconds 设置。 对于失败的就绪探针,kubelet 继续运行检查失败的容器,并继续运行更多探针; 因为检查失败,kubelet 将 Pod 的 Ready 状况设置为 false。
  • terminationGracePeriodSeconds:为 kubelet 配置从为失败的容器触发终止操作到强制容器运行时停止该容器之前等待的宽限时长。 默认值是继承 Pod 级别的 terminationGracePeriodSeconds 值(如果不设置则为 30 秒),最小值为 1

# 4.2 HTTP 探测

  • host:连接使用的主机名,默认是 Pod 的 IP。也可以在 HTTP 头中设置 “Host” 来代替。
  • scheme :用于设置连接主机的方式(HTTP 还是 HTTPS)。默认是 "HTTP"。
  • path:访问 HTTP 服务的路径。默认值为 "/"。
  • httpHeaders:请求中自定义的 HTTP 头。HTTP 头字段允许重复。
    • name: 请求头名称
    • value: 请求头值
  • port:访问容器的端口号或者端口名。如果数字必须在 1~65535 之间。

# 4.3 TCP 探测

kubelet 在节点上(不是在 Pod 里面)发起探测连接, 这意味着你不能在 host 参数上配置服务名称,因为 kubelet 不能解析服务名称。