文章目录
- 实验环境
- 一、探针概述
- 二、liveness probe 存活探针
-
- 实验1:command探测方式
- 实验2:httpGet探测方式
- 实验3:tcpSocket探测方式
- 三、readiness probe 就绪探针
-
- 实验:command探测方式
实验环境
初始初始集群环境: (vms21)192.168.26.21——master1 (vms22)192.168.26.22——worker1 (vms23)192.168.26.23——worker2
一、探针概述
在一个k8s集群中,deployment作为控制器,作为一个worker节点中的pod有问题,状态不是Running了,这种情况下,deployment会帮我们做到的pod重新创建的 假设节点的状态仍然存在Running,但是pod此时,应用程序运行异常,无法提供外部服务,deployment这个不会重启pod是的,那么如何处理这种情况呢?-我们可以检测和检测每个人pod如果发现问题,根据处理方法的不同,检测可分为两类:
二、liveness probe 存活探针
1.command:在容器中执行命令,不关心命令操作的结果,只关心命令操作是否成功,命令执行成功,认为检测成功,否则检测失败,将立即重启pod 2.httpGet:访问服务,如果访问超时,认为检测失败 3.tcpSocket:与服务建立tcp如果能建立三次握手,则认为检测成功,否则认为检测不成功
实验1:command探测方式
(1)拉取busybox镜像
nerdctl pull busybox (2)创建一个pod,宽限期为0,镜像使用busybox 创建/tmp/healthy然后休眠30s,然后删除/tmp/healthy然后休眠1万s 探针在spec.containers下定义,定义一个livenessProbe探针,使用command这是一种检查//tmp/healthy文件的命令 若/tmp/healthy如果文件存在,探针命令可以成功执行,否则执行不成功 initialDelaySeconds——定义的是容器启动内多少秒内不检测 periodSeconds——定义是每隔多少秒检测一次 还有其他参数,如: timeoutSeconds——定义超时检测,默认1秒,最小1秒,超过此时检测失败(在这里command不需要探测方法,在httpGet、tcpSocket应用于网络探测) failureThreshold——当pod启动,检测失败,kubernetes生存检测中的放弃意味着重新启动容器,就绪检测中的放弃pod默认值为3,最小值为1 successThreshold——检测失败后,至少连续检测被认定为成功,默认值为1。liveness必须是1,最小值是1 yaml文件如下:
apiVersion: v1 kind: Pod metadata: labels: test: liveness name: pod1 spec: terminationGracePeriodSeconds: 0 containers: - name: liveness image: busybox imagePullPolicy: IfNotPresent args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 100000 livenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 #容器启动5s内不检测 periodSeconds: 5 #每5s检查一次 (3)创建这个pod
kubectl apply -f xxx.yaml (4)进入pod执行列出/在容器中tmp目录下的文件可以看到healthy这个文件
kubectl exec -it pod1 -- ls /tmp
过了30s后,/tmp/healthy删除后可以看到/tmp下healthy文件没有了(探测命令执行不成功) 每隔5s会检测一次,此时会检测失败,失败后默认重试次数为3次,所以会检测3次(15次s),或者检测失败,可能是pod创建的47s此外,这里的宽限期为0,因此约为47s会立即重启pod
实验2:httpGet探测方式
(1)删除实验1中的实验pod1.重建一个pod,使用nginx镜像 livenessProbe中定义使用httpGet探测方法,path定义httpGet地址,端口80,使用HTTP协议 检测失败后重试次数failureThreshold为3,initialDelaySeconds容器启动10s内不检测 每次探测间隔时间periodSeconds为10s,超时时间timeoutSeconds为10s,successThreshold连续探测一次成功意味着成功 yaml文件如下:
apiVersion: v1 kind: Pod metadata: labels: test: liveness name: pod2 spec: containers: - name: liveness image: nginx imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /index.html #这里的index.html不是指宿主机index.html,相反,它在容器中/usr/share/nginx/html/index.html port: 80 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 succesThreshold: 1
timeoutSeconds: 10
(3)创建这个pod
kubectl apply -f xxx.yaml
(4)进入pod内容器,查看/usr/share/nginx/html目录下文件,可以看到index.html
kubectl exec -it pod2 -- ls /usr/share/nginx/html
然后我们大概在pod创建后的10s后删除index.html,这样探针就访问不到这个页面了 yaml中httpGet探测方式中定义的path: index.html不是指宿主机中的index.html,而是在容器内的/usr/share/nginx/html/index.html
kubectl exec -it pod2 -- rm -rf /usr/share/nginx/html/index.html
我们定义的探针在容器启动后10s内不检测,每隔10s检测一次,因此大概在20s时,会访问不到index.html(10s时删除了index.html) 定义的探针的httpGet探测超时时间为10s,因此大概在30s时会认为探测失败,并进行第一次重试,默认的探测失败后的重试次数为3,因此在50s后认为探测失败,这时候会重启pod
实验3:tcpSocket探测方式
(1)删除实验2中的pod2,重新创建一个pod,使用nginx镜像,宽限期为0, lvenessProbe中定义使用tcpSocket探测方式 tcpSocket下定义端口port为80,意为与容器端口80能够建立三次握手,即认为探测成功 yaml文件如下:
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: pod3
spec:
terminationGracePeriodSeconds: 0
containers:
- name: liveness
image: nginx
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
tcpSocket:
port: 80
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
(2)创建这个pod (3)假设在yaml文件中,将tcpSocket访问的端口改为其他,不为80,会怎么样呢? 因为容器使用nginx镜像,默认端口为80,因此能够成功建立三次握手,若设置访问端口不为80,则建立不起三次握手,认为探测失败,会不停地重启pod
...
livenessProbe:
failureThreshold: 3
tcpSocket:
port: 808
initialDelaySeconds: 10
...
重新创建这个pod,会发现它不停地重启
三、readiness probe 就绪探针
1.command 2.httpGet 3.tcpSocket
就绪探针与存活探针的区别就是:探测失败后不会去重启pod,并且后续不会继续将用户请求转发到该pod(会掐断svc到该pod的线路),但是pod仍然是通的,若直接访问pod(不通过svc转发)还是能访问
实验:command探测方式
(1)我们创建一个deployment,创建3个副本 pod模板中使用nginx镜像,宽限期为0 容器中使用钩子进程或初始化进程来使容器创建/tmp/healthy文件(这里使用钩子进程),这样又可以不影响nginx主进程,又可以启动一个进程创建/tmp/healthy文件 使用readinessProbe定义就绪探针,使用command探测方式,命令为查看/tmp/healthy文件,命令执行成功则认为探测成功 yaml文件如下:
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web1
name: web1
spec:
replicas: 3
selector:
matchLabels:
app: web1
strategy: {
}
template:
metadata:
creationTimestamp: null
labels:
app: web1
spec:
terminationGracePeriodSeconds: 0
containers:
- image: nginx
name: c1
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ["/bin/sh","-c","touch /tmp/healthy"]
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 2 #容器启动5s内不检测
periodSeconds: 5 #每间隔5s检测一次
resources: {
}
status: {
}
(2)创建这个deployment,可以看到创建了3个pod副本
kubectl apply -f xxx.yaml
(3)为了方便演示,将内容“111”、“222”、“333”写入3个pod内的index.html
kubectl exec -it web1-656db66885-njhjq -- sh -c "echo 111 > /usr/share/nginx/html/index.html"
kubectl exec -it web1-656db66885-nzjq6 -- sh -c "echo 222 > /usr/share/nginx/html/index.html"
kubectl exec -it web1-656db66885-vg7r4 -- sh -c "echo 333 > /usr/share/nginx/html/index.html"
(4)创建一个负载均衡器svc
kubectl expose --name=svc1 deploy web1 --port=80
(5)查看svc访问地址
kubectl get svc
#输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc1 ClusterIP 10.97.6.220 <none> 80/TCP 20s
(6)每隔1s循环访问svc,都能输出index.html内容,探针也能探测成功
while true ; do curl 10.97.6.220 ; sleep 1 ; done
安ctrl+c退出 (7)现在模拟将web1-656db66885-vg7r4(index.html内容为333)的这个pod内的/tmp/healthy文件删除
kubectl exec -it web1-656db66885-vg7r4 -- rm -rf /tmp/healthy
此时,可以看到该pod的Ready已为未就绪状态 可想而知,此时探针也会探测失败 此时访问svc,将不会继续把请求转发给该pod(掐断svc到该pod的线路)
while true ; do curl 10.97.6.220 ; sleep 1 ; done
但是readiness探针并不会将该pod重启,因此,若直接访问该pod,还是能访问通
curl 10.244.70.120
httpGet、与tcpSocket探测方式同理