1.重启策略(restartPolicy)
指的是容器什么时候才会被重启,如果没有健康检查的话,默认是根据pod的status来判断的
有三个值,分别是:
-
Always
: 只要容器被终止退出后,总是重启容器,默认策略;
应用场景:常驻进程(例如nginx,tomcat、mysql等) -
OnFailure
:只有当容器异常退出(退出状态码非0)时,才重启容器;
应用场景:预期性终止的程序,如果执行失败,进行重启(例如定时任务) -
Never
:只要当容器终止退出时,不管什么原因,从不重启容器;
应用场景:预期性终止的程序,如果执行失败,不进行重启(例如一次性任务 需要修改数据库里的数据时,如果执行失败则不能重新执行,否则将会对数据库里的数据造成影响、产生脏数据等等)
查看Pod的重启策略:
kubectl get pod名称 -o yaml [-n 所在命名空间] | grep restartPolicy
[root@k8s-master ~]# kubectl get pod/nginx-9456bbbf9-zdccj -o yaml | grep restartPolicy
restartPolicy: Always
2.健康检查类型
检测容器中应用程序的工作状态
,为了防止那些进程显示正常但是又不能正常工作的应用,例如tomcat的堆内存溢出等等;
有三个值,分别是:
-
livenessProbe
(存活检查):如果检查容器中的应用失败(应用不可用),将杀死容器,根据Pod的restartPlicy来操作; -
readinessProbe
(就绪检查):如果检查失败,Kubernetes会把Pod从service endpoints中剔除; -
startupProbe
(启动检查):检查成功后才会由存活检查/就绪检查接手,用于保护那些启动慢的容器还没起来就被存活检查干掉;
存活检查和就绪检查,也是实现k8s实现自动化的两个纬度/行为,一个是失败后重启pod,一个是剔除不健康的pod;
支持的健康检查方法有:
httpGet
:发送HTTP请求,返回200-400范围的状态码为成功;(例curl、wget命令)exec
:执行Shell命令返回状态码是0为成功;(执行一段命令)tcpSocket
:发起TCP Socket建立成功;(探测端口是否已经打开并可以建立连接,例如nc、netstat、telnet命令)
service endpoints解释:
如下图:浏览器/客户端需要访问我们的应用, 首先应该去访问service,service会将客户端的请求转发给后端关联的一个/一组pod上,所以service在这里可以说是充当了一个虚拟负载均衡器(LB)的角色,那么service和一个/一组pod之间的关联就是service endpoints,当就绪检查发现pod失败时,会将检查失败的pod从service endpoints中剔除,不让service将流量转发至检查失败的pod中去,只留下可以正常工作的pod来处理service转发过来的请求;
可以通过kubectl get endpoints [-n 命名空间]
来查看service关联的容器
如上图:存活和就绪的检查动作都是由kubelet完成的;
因为kubelet是分布在每个节点运行的,相当于是一个每个节点都运行了一个agent;而容器也是在每个节点都运行的,所以kubelet是有直接的条件去接触/探测容器的;
- kubelet 通过使用 liveness probe 来确定你的应用程序是否正在运行,通俗点将就是是否还活着。一般来说,如果你的程序一旦崩溃了, Kubernetes 就会立刻知道这个程序已经终止了,然后就会重启这个程序。而我们的 liveness probe 的目的就是来捕获到当前应用程序还没有终止,还没有崩溃,如果出现了这些情况,那么就重启处于该状态下的容器,使应用程序在存在 bug 的情况下依然能够继续运行下去。
- kubelet 使用 readiness probe 来确定容器是否已经就绪可以接收流量过来了。这个探针通俗点讲就是说是否准备好了,现在可以开始工作了。只有当 Pod 中的容器都处于就绪状态的时候 kubelet 才会认定该 Pod 处于就绪状态,因为一个 Pod 下面可能会有多个容器。当然 Pod 如果处于非就绪状态,那么我们就会将他从 Service 的 Endpoints 列表中移除出来,这样我们的流量就不会被路由到这个 Pod 里面来了。
3.存活、就绪探针使用方法(httpGet)如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
labels:
app: web
spec:
selector:
matchLabels:
app: web
replicas: 3
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:latest
#存活检查
livenessProbe:
httpGet:
#进行探测的地址/页面,一般都是由开发写一个简单的用于健康检查的页面
#如果没有的话就找一个url页面内容较少的,尽量不要找页面里业务逻辑多的 因为健康检查也会不断的去请求这个页面来判断是否可以访问,在请求的过程中,也会不断的进行处理,消耗一定的cpu和内存
path: /index.html
#指定健康检查的端口,就是程序使用的端口【例如nginx80 tomcat8080 mysql3306】
port: 80
#启动容器后多少秒开始进行健康检查【根据自己应用的启动时间来设置】
initialDelaySeconds: 5
#以后每间隔多少秒检查一次
periodSeconds: 10
#就绪检查【就绪检查和存活检查配置项一样,根据自己应用相对应调整参数即可】
readinessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: web
namespace: default
spec:
selector:
app: web
type: ClusterIP
ports:
- name: web
protocol: TCP
port: 80
targetPort: 80
[root@k8s-master ~]# kubectl apply -f probe-web.yaml
[root@k8s-master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS[重启次数] AGE IP NODE NOMINATED NODE READINESS GATES
web-6c5678449f-ddkpd 1/1 Running 0 9m22s 10.244.36.94 k8s-node1 <none> <none>
web-6c5678449f-pj9xn 1/1 Running 0 9m22s 10.244.36.93 k8s-node1 <none> <none>
web-6c5678449f-rqbf9 1/1 Running 0 9m22s 10.244.36.91 k8s-node1 <none> <none>
[root@k8s-master ~]# kubectl get ep
NAME ENDPOINTS AGE
kubernetes 10.8.0.2:6443 78d
web 10.244.36.91:80,10.244.36.93:80,10.244.36.94:80 13m
#此时我们的nginx副本已经创建好了,通过kubectl get ep 也可以查看道service关联的副本的pod;
(1).验证存活检查
(存活检查的行为是当容器里的服务挂了之后会进行重启)
大家可以通过 kubectl logs -f [pod名称] [-n 命名空间] 看下正常的容器日志输出为:
每隔10秒会出现两条健康检查的日志,分别是由kubelet的组件kube-proxy发起的存活检查和就绪检查的日志,探测的页面地址就是我们上面配置的index.html;
此时模拟存活检查失败,也就是将状态码变成非200
,才可以触发这个条件;
最简单的方法就是进入nginx容器将index.html页面删掉即可将状态码变为404;
[root@k8s-master ~]# kubectl exec -it pod/web-6c5678449f-ddkpd bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@web-6c5678449f-ddkpd:/# cd /usr/share/nginx/html/
root@web-6c5678449f-ddkpd:/usr/share/nginx/html# ls
50x.html index.html
root@web-6c5678449f-ddkpd:/usr/share/nginx/html# rm index.html
root@web-6c5678449f-ddkpd:/usr/share/nginx/html# exit
现在已经将index.html页面删掉了,再次查看容器日志
可以看到探测失败以及关闭此容器的的错误日志;
同时我们可以使用kubectl describe [pod名称] [-n 命名空间] 来查看下容器的事件
可以看到里面有kubelet发出的两个事件
“Liveness probe failed: HTTP probe failed with statuscode: 404”
,“Container web failed liveness probe, will be restarted”
代表存活检查探测HTTP失败状态码为404
,容器网络活动探测失败将重启启动
;
使用kubectl get [pod名称] [-n 命名空间] 查看pod内容器的重启次数(restart列)
可以看有一个pod内的容器在37分钟前被重启了,这是因为健康检查失败导致的;
注:这里重启的是pod内的容器,而不是重建的pod;只是用新的镜像又重新拉起了容器,所以pod名和IP不会发生变化,如果是重建的pod的话,那么pod名和IP就会发生改变;
(2).验证就绪检查
(就绪检查的行为是当容器里的服务未就绪或者挂了之后会将pod在service endpoints列表里剔除,不再将流量转发至pod)
首先使用kubectl get ep查看一下关联的pod
然后使用kubectl get ep -w 实时观察一下,同时新建立一个终端并开始模拟故障(这里就绪检查用的也是httpGet所以,只需要将index.html这个页面删除即可改变状态码为404)
[root@k8s-master ~]# kubectl exec -it web-6c5678449f-pj9xn bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@web-6c5678449f-pj9xn:/# cd /usr/share/nginx/html/
root@web-6c5678449f-pj9xn:/usr/share/nginx/html# ls
50x.html index.html
root@web-6c5678449f-pj9xn:/usr/share/nginx/html# rm index.html
root@web-6c5678449f-pj9xn:/usr/share/nginx/html# exit
exit
如上图,大家可以发现由最开始的3个IP变成了2个,这就是就绪检查失败造成的,就绪检查失败就会把不可用的pod剔除,此时再去访问service就不会再把请求转发至失败的pod了;最后又变成了3个,是因为配置了存活检查将pod的容器重启了、就绪检查没问题了之后,就会再把pod加入到enpoints列表中;
4.存活、就绪探针其它使用方法
示例:tcpSocket端口探测
:
livenessProbe:
tcpSocket:
#要探测的端口号;
port: 80
initialDelaySeconds: 120
periodSeconds: 30
示例:exec执行命令探测
:
livenessProbe:
exec:
#执行的shell命令,如果执行后返回值为0则成功(可以执行完成命令后使用 echo $? 来查看命令返回值);
command:
- cat
- /tmp/healthy
initialDelaySeconds: 120
periodSeconds: 30
注:存活检查和就绪检查是没有先后顺序的,如果一个项目都配置了这两个探针的话,配置的时间参数也一致 是可以同时去进行检测的;
总结:
我们可以把k8s的健康检查
和nacos/eureka
结合起来实现真正的优雅上下线
;
具体方案可以参考如下地址:
https://blog.csdn.net/Dream_Weave/article/details/126379544