跳转至

Pod容器健康探测

为什么要做容器探测?

在Kubernetes中Pbd是最小的计算单元,而一个Pod又由多个容器组成,相当于每个容器就是一个应用,应用在运行期间,可能因为某些意外情况致使程呈序挂掉。那么如何监控这些容器状态稳定性,保证服务在运行期间不会发生问题,发生问题后进行重启等机制,就成为了重中之重的事情,考虑到这点kubernetes推出了活性探针机制。有了存活性探能保证程序在运行中如果挂掉能够自动重启,但是还有个经常遇到的问题,比如说,在Kubernetes中启动Pod,显示明明Pod己经启动成功,且能访问里面的端口,但是却返回错误信息。还有就是在执行滚动更新时候,总会出现一段时间,Pod对外提供网络访问,但是访问却发生404,这两个原因,都是因为1Pod已经成功启动,但是Pod的的容器中应用程序还在启动中导致,考虑到这点Kubernetes推出了就绪性探针机制。

K8s 提供了三种方式来实现容器的健康探测:

目前 LivenessProbeReadinessProbestartupprobe 探测者支持下面三种探针

1、exec: 在容器中执行指定的命令,如果执行成功,退出码为0则探测成功。

2、TCPSocket: 通过容器的IP地址和端口号执行TCP检查,如果能够建立TCP连接,则表明容器健康。

3、HTTPGetAction: 通过容器的IP地址、端口号及路径调用 HTTPGet 方法,如果响应的状态码大于等于200目小于400,则认为容器健康

每类探针都有三种结果:

1、Success:容器通过检查;

2、Failure:容器未通过检查;

3、Unknown:未能执行检查,因此不采取任何措施;

LivenessProbeReadinessProbe两种探针区别:

ReadinessProbelivenessProbe 可以使用相同探测方式我,只是对 Pod 的处置方式不同:

1、readinessProbe 当检测失败后,将 Pod 的 IP:Port 从对应的 EndPoint 列表中删除。

image-20240115162305231

2、livenessProbe 当检测失败后,将杀死容器并根据 Pod 的重启策略来决定作出对应的措施。

startupProbe: 探测容器中的应用是否已经启动。如果提供了启动探测(startup probe),则禁用所有其他探测,直到它成功为止。如果启动探测失败,kubelet将杀死容器,容器服从其重启策略进行重启。如果容器没有提供启动探测,则默认状态为的成功Success。

startupprobe-exec.yaml
apiVersion: v1
kind: Pod
metadata:
  name: startupprobe
spec :
  containers:
  - name: startup
    image: tomcat
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    startupProbe:
      exec:
        command:
        - "/bin/sh"
        - "-c"
        - "ps -axuf|grep tomcat | grep -v 'grep'"
      initialDelaySeconds: 10 #容器启动后多久开始探测
      periodSeconds: 10 #执行探测的时间间隔
      timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
      successThreshold: 1  #成功多少次才算成功
      failureThreshold: 2 #失败多少次才算失败
startupprobe-tcpSocketc.yaml
apiVersion: v1
kind: Pod
metadata:
  name: startupprobe
spec :
  containers:
  - name: startup
    image: tomcat
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    startupProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 10 #容器启动后多久开始探测
      periodSeconds: 10 #执行探测的时间间隔
      timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
      successThreshold: 1 #成功多少次才算成功
      failureThreshold: 2 #失败多少次才算失败
startupprobe-httpGet.yaml
apiVersion: v1
kind: Pod
metadata:
  name: startupprobe
spec :
  containers:
  - name: startup
    image: tomcat
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    startupProbe:
      httpGet:
        path: /
        port: 8080
      initialDelaySeconds: 10 #容器启动后多久开始探测
      periodSeconds: 10 #执行探测的时间间隔
      timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
      successThreshold: 1 #成功多少次才算成功
      failureThreshold: 2 #失败多少次才算失败

livenessprobe: 用指定的方式(exec、tcp、http)检测pod中的容器是否正常运行,如果检测失败,则认为容器不健康,那么Kubelet将根据Pod中设置的restartPolicy策略来判断Pod是否要进行重启操作,如果容器配置中没有配置livenessProbe,Kubelet将认为存活探针探测s一直为success(成功)状态。

livenessprobe-exec.yaml
apiVersion: v1
kind: Pod
metadata:
  name: livenessprobe-exec
  labels: 
    app: liveness
spec :
  containers:
  - name: liveness
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessprobe:
        exec:
          command:
          - cat
          - /tmp/healthy
      initialDelaySeconds: 10 #容器启动后多久开始探测
      periodSeconds: 5 #执行探测的时间间隔
    #   timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
    #   successThreshold: 1  #成功多少次才算成功
    #   failureThreshold: 2 #失败多少次才算失败
livenessprobe-httpGet.yaml
apiVersion: v1
kind: Pod
metadata:
  name: livenessprobe-httpGet
  labels: 
    app: liveness
spec :
  containers:
  - name: liveness
    image: tomcat
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
    livenessprobe:
      initialDelaySeconds: 10 #容器启动后多久开始探测
      periodSeconds: 5 #执行探测的时间间隔
      timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
      httpGet:
        scheme: HTTP
        port: 8080
        path: /health
    #   successThreshold: 1  #成功多少次才算成功
    #   failureThreshold: 2 #失败多少次才算失败
livenessprobe-tcpSocket.yaml
apiVersion: v1
kind: Pod
metadata:
  name: livenessprobe-tcpSocket
  labels: 
    app: liveness
spec :
  containers:
  - name: liveness
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    livenessprobe:
      initialDelaySeconds: 15 #容器启动后多久开始探测
      periodSeconds: 20 #执行探测的时间间隔
      tcpSocket:
        port: 80

readnessprobe: 就绪性探针,用于检测容器中的应用是否可以接受请求,当探测成功后才使Pod对外提供网络访问,将容器标记为就绪状态,可以加到pod前端负载,如果探测失败,则将容器标记为未就绪状态,会把pod从前端负载移除。

readiness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget                   # Pod 名称
  labels: 
    app: readiness-httpget
spec :
  containers:
  - name: readiness-httpget-container       # 容器名称
    image: hub.test.com/library/mynginx:v1  # 镜像地址
    imagePullPolicy: IfNotPresent           # 镜像下载策略
    ports:
    - containerPort: 80                    
    readinessProbe:                         # 就绪探测
      httpGet:                              # 检测方案
        path: /index.html                   # 检测路径
        port: 80                            # 检测端口
      initialDelaySeconds: 15               # 启动后多少秒开始第一次检测
      periodSeconds: 3                      # 每次间隔检测时间

检测 http://localhost:80/index.html 是否正常

readiness-tcpSocket.yaml
apiVersion: v1
kind: Pod
metadata:
  name: readiness-tcpSocket                   # Pod 名称
  labels: 
    app: readiness-tcpSocket
spec :
  containers:
  - name: readiness-tcpSocket-container     # 容器名称
    image: hub.test.com/library/mynginx:v1  # 镜像地址
    imagePullPolicy: IfNotPresent           # 镜像下载策略
    ports:
    - containerPort: 80                    
    readinessProbe:                         # 就绪探测
      tcpSocket:                            # 检测方案
        port: 80                            # 检测端口
      initialDelaySeconds: 15               # 启动后多少秒开始第一次检测
      periodSeconds: 3                      # 每次间隔检测时间
readiness-exec.yaml
apiVersion: v1
kind: Pod
metadata:
  name: readiness-exec                   # Pod 名称
  labels: 
    app: readiness-exec
spec :
  containers:
  - name: readiness-exec-container          # 容器名称
    image: hub.test.com/library/mynginx:v1  # 镜像地址
    imagePullPolicy: IfNotPresent           # 镜像下载策略
    ports:
    - containerPort: 80                    
    readinessProbe:                         # 就绪探测
      exec:                                 # 检测方案
        command:                            # 使用命令进行探测
        - cat
        - /var/www/html/ready.txt           # 检测文件
      initialDelaySeconds: 15               # 启动后多少秒开始第一次检测
      periodSeconds: 3                      # 每次间隔检测时间
案例
apiVersion: v1
kind: Pod
metadata:
  name: myhello-pod
  namespace: default
  labels:
    name: myhello-pod
    env: dev
spec:
  restartPolicy: Always
  initContainers:
  - name: init-myservice
    image: busybox
    # 查找命名空间下myservice服务,如果存在则执行成功,如果不存在则一直查找
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox
    # 查找命名空间下mydb服务,如果存在则执行成功,如果不存在则一直查找
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
  containers:
  - name: myhello
    image: nongtengfei/hello:curl
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    command: ["./app"]
    args: ["--param1=k8s-p1", "--param2=k8s-p2"]
    resources:
      limits:
        cpu: 200m
        memory: 500Mi
      requests:
        cpu: 100m
        memory: 200Mi
    env: # 注入到容器的环境变量
    - name: env1
      value: "k8s-env1"
    - name: env2
      value: "k8s-env2"
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c","echo post start command exec >> /tmp/data"]
      preStop:
        exec:
          command: ["/bin/sh", "-c","echo pre stop command exec >> /tmp/data"]
    startupProbe:
      exec:
        command: ["/bin/sh", "-c","statuscode=`curl -o /dev/null -s -w % {http_code} http://localhost/healthz`; [ $$statuscode -le 400 ] || exit 1"]
      # 指定初始化时间,即探针在容器启动之后的延迟时长
      initialDelaySeconds: 5
      # 探测周期,即每隔多长时间探测一次
      periodSeconds: 5
      # 最小连续失败次数,即连续失败多少次表示探测失败
      failureThreshold: 3
      # 最小连续成功次数,即连续探测成功多少次表示探测成功,liveness 和 startup 必须为1
      successThreshold: 1
      # 探测超时时间
      timeoutSeconds: 1
    readinessProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      successThreshold: 1
      timeoutSeconds: 1
    livenessProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      successThreshold: 1
      timeoutSeconds: 1
  - name: myredis #容器的名称
    image: redis #容器对应的 Docker Image
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
    resources:
      limits:
        cpu: 200m
        memory: 500Mi
      requests:
        cpu: 100m
        memory: 200Mi
    livenessProbe:
      tcpSocket:
        port: 6379
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      successThreshold: 1
      timeoutSeconds: 1