Kubernetes Pod的重启策略+健康检查(实现应用自修复);

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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不知名运维:

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值