一、Pod 容器的探针

探针是由 kubelet 对容器执行的定期诊断(pod中探针又分为三类):

  • 存活探针livenessProbe)探测容器是否运行正常。如果探测失败则kubelet杀掉容器(不是Pod),容器会根据重启策略决定是否重启

  • 就绪探针readinessProbe)探测Pod是否能够进入READY状态,并做好接收请求的准备。如果探测失败Pod则会进入NOTREADY状态(READY为0/1)并且从所关联的service资源的端点(endpoints)中踢出,service将不会再把访问请求转发给这个Pod

  • 启动探针startupProbe)探测容器内的应用是否启动成功,在启动探针探测成功之前,其它类型的探针都会暂时处于禁用状态

注意:启动探针只是在容器启动后按照配置满足一次后就不再进行后续的探测了。存活探针和就绪探针会一直探测到Pod生命周期结束为止

kubectl explain pod.spec.containers

在这里插入图片描述

二、探针的探测方式

  • exec : 通过command字段设置在容器内执行的Linux命令来进行探测,如果命令返回码为0,则认为探测成功,返回码非0则探测失败
  • httpGet : 通过向容器的指定端口和uri路径发起HTTP GET请求,如果HTTP返回状态码为 >=200且<400的(2XX,3XX),则认为探测成功,返回状态码为4XX,5XX则探测失败
  • tcpSocket : 通过向容器的指定端口发送tcp三次握手连接,如果端口正确却tcp连接成功,则认为探测成功,tcp连接失败则探测失败

探针探测结果有以下值:
Success:表示通过检测。
Failure:表示未通过检测。
Unknown:表示检测没有正常进行。

官网示例:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

2.1 存活探针的使用

2.1.1 exec方式

//示例1:exec方式
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
 - name: liveness
    image: k8s.gcr.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      failureThreshold: 1
      initialDelaySeconds: 5
      periodSeconds: 5
  • initialDelaySeconds:指定 kubelet 在执行第一次探测前应该等待5秒,即第一次探测是在容器启动后的第6秒才开始执行。默认是 0 秒,最小值是 0。
  • periodSeconds:指定了 kubelet 应该每 5 秒执行一次存活探测。默认是 10 秒。最小值是 1。
  • failureThreshold: 当探测失败时,Kubernetes 将在放弃之前重试的次数。 存活探测情况下的放弃就意味着重新启动容器。就绪探测情况下的放弃 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1。
  • timeoutSeconds:探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。(在 Kubernetes 1.20 版本之前,exec 探针会忽略 timeoutSeconds 探针会无限期地 持续运行,甚至可能超过所配置的限期,直到返回结果为止。)

可以看到 Pod 中只有一个容器。kubelet 在执行第一次探测前需要等待 5 秒,kubelet 会每 5 秒执行一次存活探测。kubelet 在容器内执行命令 cat /tmp/healthy 来进行探测。如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的。 当到达第 31 秒时,这个命令返回非 0 值,kubelet 会杀死这个容器并重新启动它。

//示例2:exec方式
apiVersion: v1
kind: Pod
metadata:
  name: myapp-exec
spec:
  containers:
  - image: soscscs/myapp:v1
    name: myapp-static
    ports:
    - containerPort: 80
    command:
    - /bin/sh
    - -c
    - 'touch /opt/test.txt; sleep 30; rm -f /opt/test.txt; sleep 3600'
    livenessProbe:
      exec:
        command: ["test", "-e", "/opt/test.txt"]
      initialDelaySeconds: 1
      periodSeconds: 3
      failureThreshold: 2
  dnsPolicy: ClusterFirst
  restartPolicy: Always

在这里插入图片描述

在这里插入图片描述

kubectl describe pod demo-exec

在这里插入图片描述

2.1.2 httpGet方式

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

在这个配置文件中,可以看到 Pod 也只有一个容器。initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 3 秒。periodSeconds 字段指定了 kubelet 每隔 3 秒执行一次存活探测。kubelet 会向容器内运行的服务(服务会监听 8080 端口)发送一个 HTTP GET 请求来执行探测。如果服务器上 /healthz 路径下的处理程序返回成功代码,则 kubelet 认为容器是健康存活的。如果处理程序返回失败代码,则 kubelet 会杀死这个容器并且重新启动它。

任何大于或等于 200 并且小于 400 的返回代码标示成功,其它返回代码都标示失败。

vim httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: soscscs/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10
	  
kubectl create -f httpget.yaml

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

kubectl get pods
//示例2
vim demo-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-httpget
spec:
  containers:
  - image: soscscs/myapp:v1
    name: myapp-httpget
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 3
      timeoutSeconds: 10
  dnsPolicy: ClusterFirst
  restartPolicy: Always

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

kubectl describe pod myapp-httpget

在这里插入图片描述
在这里插入图片描述

2.1.3 tcpSocket方式

vim demo-tcp.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp-tcp
spec:
  containers:
  - image: soscscs/myapp:v1
    name: myapp-tcp
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
      failureThreshold: 2
      timeoutSeconds: 10
  dnsPolicy: ClusterFirst
  restartPolicy: Always

kubectl apply -f demo-tcp.yaml 

kubectl get pods -owide -w

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.2 就绪探针的使用

kubectl create svc clusterip demo-svc --tcp=8080:80 --dry-run=client -oyaml > demo-svc.yaml
vim demo-httpget.yaml   //添加标签
kubectl delete -f demo-httpget.yaml
kubectl apply -f demo-httpget.yaml

在这里插入图片描述

在这里插入图片描述

vim demo-svc.yaml

在这里插入图片描述

kubectl apply -f demo-svc.yaml 
kubectl get pod,svc

在这里插入图片描述
在这里插入图片描述

kubectl describe svc demo-svc

在这里插入图片描述

[root@master01 demo]# kubectl exec -it myapp-httpget sh
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # ls
50x.html    index.html
/usr/share/nginx/html # mv index.html index.html.bak
/usr/share/nginx/html # exit

在这里插入图片描述

kubectl get pods --show-labels -w

在这里插入图片描述

 kubectl describe pod myapp-httpget

在这里插入图片描述

kubectl describe svc demo-svc

在这里插入图片描述

2.3 启动探针的使用

启动探针存在的必要:

有时候,会有一些现有的应用在启动时需要较长的初始化时间。 要这种情况下,若要不影响对死锁作出快速响应的探测,设置存活探测参数是要技巧的。 技巧就是使用相同的命令来设置启动探测,针对 HTTP 或 TCP 检测,可以通过将 failureThreshold * periodSeconds 参数设置为足够长的时间来应对糟糕情况下的启动时间。(因为启动探针在启动后,其他的两种探针就会进入短暂的禁用装态,于是给容器启动预留了充足的时间,保证容器中业务启动的顺利进行。而且启动探针只会启动一次,后续工作就完全交给其他两个探针,直到容器的生命周期结束)。

ports:
 1. name: liveness-port
  containerPort: 8080
  hostPort: 8080
 
livenessProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 1
  periodSeconds: 10
 
startupProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 30
  periodSeconds: 10

在这里,幸亏有了启动探测,应用程序将会有最多 5 分钟(30 * 10 = 300s)的时间来完成其启动过程。 一旦启动探测成功一次,存活探测任务就会接管对容器的探测,对容器死锁作出快速响应。 如果启动探测一直没有成功,容器会在 300 秒后被杀死,并且根据 restartPolicy 来执行进一步处置。

2.4 Pod 容器的启动和退出动作

启动动作和退出动作是Pod的两个重要属性,用于定义在容器启动和停止时要执行的动作。

  1. 启动动作(Startup Probes):
    启动动作是一种用于检测容器是否成功启动的探针机制当Pod中的容器启动时,Kubernetes将定期执行启动动作来检查容器是否已经准备就绪。如果启动动作失败,则Kubernetes可以将Pod标记为不可用,并采取相应的重启策略(例如,重新启动Pod或进行滚动更新)。
    使用启动动作的主要用途是确保容器在正常运行之前已经准备好处理请求。例如,某个容器可能需要一些时间来初始化数据库连接、加载配置文件或完成其他启动任务。启动动作可以确保在容器被认为是“就绪”之前,这些必要的初始化步骤已经完成。

  2. 退出动作(Termination Probes):
    退出动作是一种用于检测容器是否已经正确停止的探针机制。当Pod中的容器接收到终止信号时(比如因为调度器需要停止Pod或进行滚动更新),Kubernetes将定期执行退出动作来检查容器是否已经成功终止。如果退出动作失败,Kubernetes可以采取相应的措施,比如等待一段时间再强制终止容器。
    使用退出动作的主要用途是确保容器在被终止之前完成必要的清理和资源释放工作。例如,容器可能需要将未保存的数据写入磁盘、关闭网络连接或清理临时文件。退出动作可以确保容器在被终止之前,这些清理任务已经完成。

通过使用启动动作和退出动作,Kubernetes可以更准确地控制Pod的生命周期,并确保容器在启动和停止过程中的正确行为。这些功能对于构建可靠的、高可用性的容器化应用程序至关重要。

postStart 配置 exec.command 字段设置 Linux 命令,实现当应用容器启动时,会执行的额外操作

preStop 配置 exec.command 字段设置 Linux 命令,实现当应用容器退出时,会执行的最后一个操作

//示例
apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: soscscs/myapp:v1
    lifecycle:   #此为关键字段
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler >> /var/log/nginx/message"]      
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the prestop handler >> /var/log/nginx/message"]
    volumeMounts:
    - name: message-log
      mountPath: /var/log/nginx/
      readOnly: false
  initContainers:
  - name: init-myservice
    image: soscscs/myapp:v1
    command: ["/bin/sh", "-c", "echo 'Hello initContainers'   >> /var/log/nginx/message"]
    volumeMounts:
    - name: message-log
      mountPath: /var/log/nginx/
      readOnly: false
  volumes:
  - name: message-log
    hostPath:
      path: /data/volumes/nginx/log/
      type: DirectoryOrCreate

三、总结

Pod 容器的探针(健康检查) 3种

  • 存活探针(livenessProbe)探测容器是否正常运行。如果探测失败则Kubelet杀掉容器(Pod会根据重启策略决定是否重启)
  • 就绪探针(readinessProbe)探测Pod是否能进入ready状态(比如ready状态栏变成1/1),并做好接收请求的准备。如果探测失败则Pod会变成NotReady状态(比如ready状态栏变成0/1),service会删除所关联的端点(endpoint),并且不再转发请求给就绪探测失败的Pod
  • 启动探针(startupProbe)探测容器内的应用是否启动成功。在启动探测成功之前,存活探针和就绪探针都会暂时处于禁用状态,直到启动探测成功

探针的探测方式 3 种

  • exec :通过在command字段设置在容器执行的Linux命令来进行探测,如果命令返回码为0,则认为探测正常,如命令返回码为非0,则认为探测失败
  • tcpSocket:通过向容器的指定端口发送tcp三次握手连接请求。如果端口正确且tcp连接成功,则认为探测正常,如tcp连接失败则探测失败
  • httpGet:通过向容器的指定端口和URL路径发起HTTP GET请求。如果HTTP响应返回状态码为 2XX 3XX 则认为探测正常,如响应状态码返回为 4XX 3XX则认为探测失败

探针参数:
initialDelaySeconds:设置容器启动后延迟几秒后开始探测
periodSeconds:每次探测的间隔时间(秒数)
failureThreshold:探测连续失败几次后判断探测失败
timeoutSeconds:探测超时等待时间(秒数)

Pod 应用容器生命周期的启动动作和退出动作
spec.containers.lifecycle.postStart 配置 exec.command 字段设置 Pod 中的应用容器启动时额外的命令操作
spec.containers.lifecycle.preStop 配置 exec.command 字段设置删除 Pod 时应用容器退出前执行的命令操作

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐