Pod健康检查(就绪性探针、存活性探针和启动检查)

1、简介

K8S中的健康检查主要使用 就绪性探针(readinessProbes​)和 存活性探针(livenessProbes) 来实现,k8s保证 service 后面的 pod 都可用,是k8s中自愈能力的主要手段,主要基于这两种探测机制,可以实现如下需求:

  • 异常实例自动剔除,并重启新实例
  • 多种类型探针检测,保证异常pod不接入流量
  • 不停机部署,更安全的滚动升级

探针种类:

  1. readinessProbe,就绪探针
  2. livenessProbe,存活探针
  3. startupProbe,启动探针,1.17 版本新增

2、样例

可选参数:

参数名称

默认值

最小值

描述

initialDelaySeconds

0秒

0秒

探测延迟时长,容器启动后多久开始进行第一次探测工作。

periodSeconds

10秒

1秒

探测频度,频率过高会对pod带来较大的额外开销,频率过低则无法及时反映容器产生的错误。

timeoutSeconds

1秒

1秒

探测的超时时长。

failureThreshold

3

1

处于成功状态时,探测连续失败几次可被认为失败。

successThreshold

1

1

处于失败状态时,探测连续成功几次,被认为成功。

2.1 exec方式

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: registry.aliyuncs.com/google_containers/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 60
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

解释:

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

现象:这个容器生命的前 30 秒,/tmp/healthy 文件是存在的。 所以在这最开始的 30 秒内,执行命令 cat /tmp/healthy 会返回成功代码。 30 秒之后,执行命令 cat /tmp/healthy 就会返回失败代码。30s之后检查失败后就重启pod了,又正常了。

2.2 httpGet 方式

apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - name: nginx
      containerPort: 80
    livenessProbe:
      httpGet:
        port: nginx
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10

删除 Pod 的 index.html 文件

kubectl exec -it liveness-httpget -- rm -rf /usr/share/nginx/html/index.html

再观察pod状态:

kubectl describe pod liveness-httpget
kubectl get pod liveness-httpget

2.3 tcpSocket 方式

apiVersion: v1
kind: Pod
metadata:
  name: tcpsocket
  labels:
    app: tcpsocket
spec:
  containers:
  - name: tcpsocket
    image: nginx
    ports:
    - containerPort: 80
    readinessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 15
      periodSeconds: 20

完整版的示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-demo
spec:
  replicas: 3
  selector:
    matchLabels:
     app: deployment-demo
  template:
    metadata:
      labels:
        app: deployment-demo
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.1
        
        # readinessProbe,就绪探针
        readinessProbe:
          httpGet:
            path: /index.html
            port: nginx
          # 延迟多久后开始探测
          initialDelaySeconds: 10
          # 执行探测频率(秒) 【 每隔秒执行一次 】
          periodSeconds: 10
          #  超时时间
          timeoutSeconds: 1
          # 处于成功状态时,探测连续失败几次可被认为失败。
          failureThreshold: 3
          # 处于失败状态时,探测连续成功几次,被认为成功。
          successThreshold: 1
        
        # livenessProbe,存活探针
        livenessProbe:
          httpGet:
            path: /index.html
            port: nginx
          # 延迟多久后开始探测
          initialDelaySeconds: 10
          # 执行探测频率(秒) 【 每隔秒执行一次 】
          periodSeconds: 10
          #  超时时间
          timeoutSeconds: 1
          # 处于成功状态时,探测连续失败几次可被认为失败。
          failureThreshold: 3
          # 处于失败状态时,探测连续成功几次,被认为成功。
          successThreshold: 1
        
        # startupProbe,启动探针
        startupProbe:
          httpGet:
            path: /index.html
            port: nginx
          # 延迟多久后开始探测
          initialDelaySeconds: 10
          # 执行探测频率(秒) 【 每隔秒执行一次 】
          periodSeconds: 10
          #  超时时间
          timeoutSeconds: 1
          # 处于成功状态时,探测连续失败几次可被认为失败。
          failureThreshold: 3
          # 处于失败状态时,探测连续成功几次,被认为成功。
          successThreshold: 1