目录
- 一、Pod 容器的探针
- 二、探针的探测方式
- 2.1 存活探针的使用
- 2.1.1 exec方式
- 2.1.2 httpGet方式
- 2.1.3 tcpSocket方式
- 2.2 就绪探针的使用
- 2.3 启动探针的使用
- 2.4 7.Pod 容器的启动和退出动作
- 三、总结
一、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:
- 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 7.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 时应用容器退出前执行的命令操作