【云原生 | 从零开始学Kubernetes】十二、k8spod的生命周期与容器钩子_容器钩子

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

该篇文章已经被专栏《从零开始学k8s》收录
上一篇文章k8s污点、容忍度和pod状态 点击跳转

在这里插入图片描述

pod生命周期

请添加图片描述

Init 容器

Pod 里面可以有一个或者多个容器部署应用的容器可以称为主容器在创建 Pod 时候Pod 中 可以有一个或多个先于主容器启动的Init 容器这个 init 容器就可以成为初始化容器初始化容器一旦执行完它从启动开始到初始化代码执行完就退出了它不会一直存在所以在主容器启动之前执行初始化初始化容器可以有多个多个初始化容器是要串行执行的先执行初始化容器 1在执行初始化容器 2等等初始化容器执行完初始化就退出了然后再执行主容器主容器一退出pod 就结束了主容器退出的时间点就是 pod 的结束点它俩时间轴是一致的

Init 容器就是做初始化工作的容器。可以有一个或多个如果多个按照定义的顺序依次执行只有所有的初始化容器执行完后主容器才启动。由于一个 Pod 里的存储卷是共享的所以 Init Container 里产生的数据可以被主容器使用到Init Container 可以在多种 K8S 资源里被使用到如 Deployment、DaemonSet, StatefulSet、Job 等但都是在 Pod 启动时在主容器启动前执行做初始化工作。

Init 容器与普通的容器区别是:

1、Init 容器不支持 Readiness,因为它们必须在 Pod 就绪之前运行完成

2、每个 Init 容器必须运行成功,下一个才能够运行

3、如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止如果 Pod 对应的 restartPolicy 值为 Never,它不会重新启动。

[root@k8smaster node]# vim init.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
 
#上面两段长的是myservice的svc和mydb的svc
[root@k8smaster node]# kubectl apply -f init.yaml 
pod/myapp-pod created
[root@k8smaster node]# kubectl get pods 
NAME                    READY   STATUS     RESTARTS   AGE
myapp-pod               0/1     Init:0/2   0          7s
#发现一直在初始化查看一下日志
[root@k8smaster node]# kubectl logs myapp-pod
Error from server (BadRequest): container "myapp-container" in pod "myapp-pod" is waiting to start: PodInitializing
#有个container是waiting状态去yaml看看
until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; 
#这是在解析myservice的svc解析到才成功不然就会一直循环我们没有创建所以一直卡在这里

[root@k8smaster node]# vim service.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377
 
[root@k8smaster node]# kubectl apply -f service.yaml 
service/myservice created
service/mydb created

[root@k8smaster node]# kubectl get pods 
NAME                    READY   STATUS    RESTARTS   AGE
myapp-pod               1/1     Running   0          4m46s
#成功启动

[root@k8smaster node]# kubectl logs myapp-pod
The app is running!
[root@k8smaster node]# kubectl describe pods myapp-pod
#也可以看启动了哪些容器 在下面

主容器

容器钩子

初始化容器启动之后开始启动主容器在主容器启动之前有一个 post start hook容器启动后钩子和 pre stop hook容器结束前钩子无论启动后还是结束前所做的事我们可以给它放两个钩子这个钩子就表示用户可以用它来钩住一些命令来执行它做开场前的预设结束前的清理如 awk 有 beginend和这个效果类似。

postStart 该钩子在容器被创建后立刻触发通知容器它已经被创建。如果该钩子对应的 hook handler 执行失败则该容器会被杀死并根据该容器的重启策略决定是否要重启该容器这个钩子不需要传递任何参数。

preStop 该钩子在容器被删除前触发其所对应的 hook handler 必须在删除该容器的请求发送 给 Docker daemon 之前完成。在该钩子对应的 hook handler 完成后不论执行的结果如何Docker daemon 会发送一个 SGTERN 信号量给 Docker daemon 来删除该容器这个钩子不需要传递任何参数。

在 k8s 中支持两类对 pod 的检测

第一类叫做 livenessprobepod 存活性探测 存活探针主要作用是用指定的方式检测 pod 中的容器应用是否正常运行如果检测失败则认为容器不健康那么 Kubelet 将根据 Pod 中设置的 restartPolicy 来判断 Pod 是否要进行重启操作如果容器配置中没有配置 livenessProbeKubelet 将认为存活探针探测一直为成功状态。 get pods里的status就是存活探测

第二类是状态检 readinessprobepod 就绪性探测用于判断容器中应用是否启动完成当探测成功后才使 Pod 对外提供网络访问设置容器 Ready 状态为 true如果探测失败则设置容器的 Ready 状态为 false。

创建 pod 需要经过哪些阶段

当用户创建 pod 时这个请求给 apiserverapiserver 把创建请求的状态保存在 etcd 中接下来 apiserver 会请求 scheduler 来完成调度如果调度成功会把调度的结果如调度到哪个节点上了运行在哪个节点上了把它更新到 etcd 的 pod 资源状态中保存在 etcd 中一旦存到 etcd 中并且完成更新以后如调度到 k8snode1 上那么 node1 节点上的 kubelet 通过 apiserver 当中的状态变化知道有一些任务被执行了所以此时此 kubelet 会拿到用户创建时所提交的清单这个清单会在当前节点上运行或者启动这个 pod如果创建成功或者失败会有一个当前状态当前这个状态会发给 apiserverapiserver 在存到 etcd 中在这个过程 中etcd 和 apiserver 一直在打交道不停的交互scheduler 也参与其中负责调度 pod 到合适的 node 节点上这个就是 pod 的创建过程.

pod 在整个生命周期中有非常多的用户行为

1、初始化容器完成初始化

2、主容器启动后可以做启动后钩子

3、主容器结束前可以做结束前钩子

4、在主容器运行中可以做一些健康检测如 liveness probereadness probe

Pod 容器探测和钩子

容器钩子postStart 和 preStop

postStart容器创建成功后运行前的任务用于资源部署、环境准备等。

preStop在容器被终止前的任务用于优雅关闭应用程序、通知其他系统等。

...... 
containers: 
- image: sample
 name: war 
 lifecycle 
  postStart: 	#钩子
   exec: 
   command: 	#命令
    - “cp” 
    - “/sample.war” 
    - “/app”
 prestop: 		#钩子
  httpGet: 		#httpget的探针
   host: monitor.com 	
   path: /waring 
  port: 8080 
  scheme: HTTP 
...... 

以上示例中定义了一个 Pod包含一个 JAVA 的 web 应用容器其中设置了 PostStart
和PreStop 回调函数。即在容器创建成功后复制/sample.war 到/app 文件夹中。而在容器
终止之前发送 HTTP 请求到 http://monitor.com:8080/waring即向监控系统发送警告。 

#可以看帮助文档
[root@k8smaster node]# kubectl explain pods.spec.containers.lifecycle

优雅的删除资源对象

当用户请求删除含有 pod 的资源对象时如 RC、deployment 等K8S 为了让应用程序优雅关闭即让应用程序完成正在处理的请求后再关闭软件K8S 提供两种信息通知

默认K8S 通知 node 执行 docker stop 命令docker 会先向容器中 PID 为 1 的进程发送系统信号 SIGTERM然后等待容器中的应用程序终止执行如果等待时间达到设定的超时时间或者默认超时时间30s会继续发送 SIGKILL 的系统信号强行 kill 掉进程。

使用 pod 生命周期利用 PreStop 回调函数它执行在发送终止信号之前。
默认情况下所有的删除操作的优雅退出时间都在 30 秒以内。kubectl delete 命令支持–grace-period=的选项以运行用户来修改默认值。0 表示删除立即执行并且立即从 API 中删除 pod。在节点上被设置了立即结束的的 pod仍然会给一个很短的优雅退出时间段才会开始被强制杀死。如下

spec: 
 containers: 
 - name: nginx-demo 
 image: centos:nginx 
 lifecycle: 
 preStop: #钩子
 exec: 
 command: ["/usr/local/nginx/sbin/nginx","-s","quit"]  #删除之前会先停掉nginx再删除容器
 ports: 
 - name: http 
 containerPort: 80

写在最后

创作不易如果觉得内容对你有帮助麻烦给个三连关注支持一下我如果有错误请在评论区指出我会及时更改
目前正在更新的系列从零开始学k8s
感谢各位的观看文章掺杂个人理解如有错误请联系我指出~
在这里插入图片描述

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: k8s

“【云原生 | 从零开始学Kubernetes】十二、k8spod的生命周期与容器钩子_容器钩子” 的相关文章