一、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杀掉,然后退出,此时实际上对应用没有任何影响。