一、POD健康检查机制

POD 有 2 种探测类型:

存活性探测 (pod.spec.containers.livenessProbe) 与 就绪性探测(pod.spec.containers.readinessProbe)。就绪和存活探测可以在同一个Pod容器上并行使用。

livenessProbe:
检测容器是否处于running状态(即Pod的状态是否为running)。
若liveness探测到Pod不健康时,会通过kubelet杀掉该pod,并根据重启策略来判断是否重启这个pod。若未配置Liveness,则默认返回值是成功的。

readinessProbe:
检测容器是否能正常对外提供服务,或接收请求(即pod的condition是否为ready)。
若readiness探测结果为不健康,则会将这个Pod从接入层(service)的Endpoint中移除掉,直到下一次判断成功,才会将这个pod再次挂回到相应的endpoint上。

有 3 种探测方式:

exec:通过执行容器中的一个命令来判断服务是否正常,命令返回值为0则表示容器是健康的。

httpGet:通过发送http Get请求来进行判断,若返回200-399状态码时,则表示容器是健康的。

tcpSocket:通过探测容器的IP和Port,执行TCP健康检查,若这个TCP的链接能够正常被建立,则表示容器是健康的。

有 3 种探测结果:

Success:表示container通过了健康检查。

Failure:表示container没有通过健康检查。若未通过检查,则会做一个相应处理,Readiness处理方式就是,在service层将没有通过Readiness检查的pod进行摘除,而Liveness就是将这个pod进行重新拉起或删除。

Unknown:表示说当前这次检查操作没有完整执行,可能是因为超时或一些脚本没有及时返回。此时Readiness-probe或Liveness-probe不做任何操作,会等待下一次的机制来进行检验。

POD容器的重启策略 (pod.spec.restartPolicy):

Always:当POD内容器被终止,不管容器状态是success还是failed,总是重启容器(默认)。

OnFailure:当POD内容器被终止,且容器状态为failed时,才重启。

Never:当POD内容器被终止,不管容器状态是success还是failed,都不重启容器。

1、livenessProbe 探测

Exec方式:

条件:当探测到Pod容器里的/tmp/healthy文件不存在时,认为容器运行不正常。

apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-exec
spec:
  containers:
  - name: liveness
    image: busybox:latest
    command: ["/bin/sh","-c","touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/healthy"]
      initialDelaySeconds: 1
      periodSeconds: 3
  restartPolicy: Always


initialDelaySeconds:在POD容器启动多少秒后再检测。比如JAVA应用,启动时间会较长,因为涉及到jvm启动及jar包加载,所以就需要延迟检测。
periodSeconds:探测的间隔时间,默认为10秒。
timeoutSeconds:探测的超时时间,默认为1秒。当超时时间之内没有检测成功,则会认为是一个失败状态。
successThreshold:从探测失败到再一次判断探测成功的连续次数。比如为2,表示失败后,接下来的2次都探测成功,才表示正常。
failureThreshold:探测失败的重试次数,默认为3次。

验证方法:创建Pod后,等30s,/tmp/healthy文件被删掉后,liveness就会检测到POD容器运行不正常(处于Terminated状态),并尝试重启容器。

httpGet方式:

条件:当探测到【http://容器:80/index.html】网页不能访问时,认为容器运行不正常。

apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-http
spec:
  containers:
  - name: liveness
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
  restartPolicy: Always


验证方法:创建Pod后,进入POD容器,手动删除index.html文件。由于网页不能访问,所以会检测到POD容器运行不正常(处于终止状态),并尝试重启容器

tcpSocket方式:

条件:当探测到8080端口不能建立连接时,则认为容器运行不正常。

apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-tcp
spec:
  containers:
  - name: goproxy
    image: k8s.gcr.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readlinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20
  restartPolicy: Always

2、readinessProbe 探测

readinessProbe 与 livenessProbe 的yaml配置差不多,这里只对Exec方式进行举例。

Exec方式:

条件:当探测到/tmp/healthy文件不存在,认为容器提供的服务不正常。

apiVersion: v1
kind: Pod
metadata:
  name: readiness-exec-pod
  namespace: default
spec:
  containers:
  - name: readiness-exec-container
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    #command: ["/bin/sh","-c","touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 3600"]
    command: ["sleep 3600"]
    readinessProbe:
      exec:
        command: ["test","-e","/tmp/healthy"]
      periodSeconds: 3
  restartPolicy: Always


验证结果:创建Pod后,等30s,/tmp/healthy文件被删掉后,readiness就会检测到Pod容器服务不正常。

二、POD应用状态

查看Pod状态:kubectl describe pods <pod-name>

Pod.Status 描述的是 Pod 的状态,Pod.Containers.State 描述的是 Pod 内某个 Container 的状态。

示例:

$ kubectl describe pods prometheus-tianjimon-prometheus-lite-prometheus-0 -n monitoring
Name:               prometheus-tianjimon-prometheus-lite-prometheus-0
Namespace:          monitoring
Priority:           0
PriorityClassName:  <none>
Node:               node1/10.0.0.100
Start Time:         Wed, 03 Mar 2021 13:57:46 +0800
Labels:             ...
Annotations:        ...
Status:             Running
IP:                 172.16.0.5
Controlled By:      StatefulSet/prometheus-tianjimon-prometheus-lite-prometheus
Containers:
  prometheus:
    Container ID:  docker://bf1b15367e573a95bdcd441f907563fd10f952df4e0f895439c2742ffd99d217
    Image:         www.test.com:5000/qinghai/prometheus:v2.18.1
    ...
    State:          Running
      Started:      Fri, 26 Mar 2021 10:48:31 +0800
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Wed, 03 Mar 2021 13:57:48 +0800
      Finished:     Fri, 26 Mar 2021 10:48:29 +0800
    Ready:          True
    Restart Count:  1
    Limits:
      cpu:     5
      memory:  8000Mi
    Requests:
      cpu:        1
      memory:     2000Mi
    Liveness:     http-get http://:web/-/healthy delay=0s timeout=3s period=5s #success=1 #failure=6
    Readiness:    http-get http://:web/-/ready delay=0s timeout=3s period=5s #success=1 #failure=120
    ...
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  ...
Events:          <none>

1、Pod状态

  • Pending:正在创建Pod,但Pod中的容器还没有全部被创建完成,此阶段包括等待Pod被调度的时间和通过网络下载镜像的时间。
  • Running:Pod已经绑定到了某个节点,Pod中所有的容器都已被创建,且至少一个容器正在处于运行状态、正在启动状态或重启状态。
  • Succeeded:Pod中的所有容器都已成功终止,且不会再重启。
  • Failed:Pod中的所有容器都已终止,但至少有一个容器退出时为失败状态,也就是说,容器以非0状态退出或被系统终止。
  • Unknown:因为某些原因无法取得Pod状态,这种情况通常是因为与Pod所在主机通信失败。

Pod状态变化过程:

         At least one                     All containers
         container is running             terminated with 0
Pending -----------------------> Running -----------------------> Succeed
                                 ↑    ↓
            After Restart,       ↑    ↓   At least one container
    container is running again   ↑    ↓   terminated with non-zero exit code
                                 ↑    ↓
                                 Failed

2、Containers状态

  • Waiting:容器仍在运行完成启动时所需要的操作,如正在拉取镜像等。其中Reason字段给出了容器处于等待状态的原因。
  • Running:容器正在运行,且没有问题发生。
  • Terminated:容器运行正常结束,或由于某些原因失败退出。

3、Conditions部分

  • Type:Name of this Pod condition。
  • Initialized:若为True,表示所有的Init容器都已成功启动。
  • Ready:若为true,表示Pod可接受请求并对外提供服务,并将Pod添加到相应Service的endpoint上。
  • ContainersReady:若为true,表示Pod中所有容器都已就绪
  • PodScheduled:若为true,表示Pod已经被调度到某节点

condition 这个机制意思是说,在K8s里面有很多这种比较小的状态,而这些小状态之间的聚合会变成上层Pod的Status。

4、event部分

在K8s里面不同的状态之间的这个转换都会发生相应的事件,而事件分为两种: normal 与 warning。

三、应用故障排查(常见应用异常)

1、Pod停留在Pending

pending表示调度器没有介入,可通过kubectl describe pod,查看event排查,通常与资源使用相关。


2、Pod停留在waiting

State处在waiting状态,一般表示这个pod无法正常拉取镜像,原因可能是这个镜像是私有镜像,没有配置secret,或镜像地址不存在,或是一个公网镜像。


3、Pod不断被拉起并且可看到crashing

pod不断被拉起,且可看到类似像backoff,通常表示说pod已经被调度完成了,但启动失败,通常是由于配置、权限造成,需查看Pod应用自身的日志分析。


4、Pod处在Runing但是没有正常工作(不能正常对外提供服务)

通常是由于yaml文件中部分字段拼写错误造成的,即yaml文件下发了,部分字段没有正常生效,可通过校验部署来排查,如:kubectl apply --validate -f demo.yaml


5、Service无法正常的工作

因为service和底层的pod之间的关联关系是通过selector的方式来匹配的,也就是说,pod上面配置了一些label,然后service通过match label的方式和这个pod进行相互关联。

如果这个label配置的有问题,可能会造成这个service无法找到后面的endpoint,从而造成相应的service没有办法对外提供服务。

那如果service出现异常时,第一个要看的是这个service后面是不是有一个真正的endpoint,其次来看这个endpoint是否可以对外提供正常的服务。

四、应用远程调试

1、Pod远程调试

# 进入到pod容器
kubectl exec -it <pod-name> /bin/bash

# 进入到pod内的某一个容器(针对一个pod中有多个容器情况)
kubectl exec -it <pod-name> -c container-name /bin/bash

2、开源调试工具kubectl-debug


kubectl-debug 是一个开源的调试工具,需要先安装好,通过kubectl debug <pod-name>来诊断一个Pod。

当执行debug时,实际上它首先会先拉取一些镜像,这个镜像里面实际上会默认带一些诊断的工具。

当这个镜像启用时,会把这个debug container进行启动,然后可在这个debug container里实时地进行查看,执行一些调试命令,如ps、netstat等,这个debug环境与即将创建的Pod容器是同一个环境。

当在debug container里执行logout命令时,会将这个debug pod杀掉,然后退出,此时实际上对应用没有任何影响。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐