ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【云原生 | 从零开始学Kubernetes】十二、k8spod的生命周期与容器钩子 [打印本页]

作者: 勿忘初心做自己    时间: 2024-6-11 10:34
标题: 【云原生 | 从零开始学Kubernetes】十二、k8spod的生命周期与容器钩子
该篇文章已经被专栏《从零开始学k8s》收录
上一篇文章:k8s污点、容忍度和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,它不会重新启动。
  1. [root@k8smaster node]# vim init.yaml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5.   name: myapp-pod
  6.   labels:
  7.     app: myapp
  8. spec:
  9.   containers:
  10.   - name: myapp-container
  11.     image: busybox:1.28
  12.     command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  13.   initContainers:
  14.   - name: init-myservice
  15.     image: busybox:1.28
  16.     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"]
  17.   - name: init-mydb
  18.     image: busybox:1.28
  19.     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"]
  20. #上面两段长的是myservice的svc和mydb的svc
  21. [root@k8smaster node]# kubectl apply -f init.yaml
  22. pod/myapp-pod created
  23. [root@k8smaster node]# kubectl get pods
  24. NAME                    READY   STATUS     RESTARTS   AGE
  25. myapp-pod               0/1     Init:0/2   0          7s
  26. #发现一直在初始化,查看一下日志
  27. [root@k8smaster node]# kubectl logs myapp-pod
  28. Error from server (BadRequest): container "myapp-container" in pod "myapp-pod" is waiting to start: PodInitializing
  29. #有个container是waiting状态,去yaml看看
  30. until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local;
  31. #这是在解析myservice的svc,解析到才成功,不然就会一直循环,我们没有创建,所以一直卡在这里!
  32. [root@k8smaster node]# vim service.yaml
  33. ---
  34. apiVersion: v1
  35. kind: Service
  36. metadata:
  37.   name: myservice
  38. spec:
  39.   ports:
  40.   - protocol: TCP
  41.     port: 80
  42.     targetPort: 9376
  43. ---
  44. apiVersion: v1
  45. kind: Service
  46. metadata:
  47.   name: mydb
  48. spec:
  49.   ports:
  50.   - protocol: TCP
  51.     port: 80
  52.     targetPort: 9377
  53. [root@k8smaster node]# kubectl apply -f service.yaml
  54. service/myservice created
  55. service/mydb created
  56. [root@k8smaster node]# kubectl get pods
  57. NAME                    READY   STATUS    RESTARTS   AGE
  58. myapp-pod               1/1     Running   0          4m46s
  59. #成功启动
  60. [root@k8smaster node]# kubectl logs myapp-pod
  61. The app is running!
  62. [root@k8smaster node]# kubectl describe pods myapp-pod
  63. #也可以看启动了哪些容器 在下面
复制代码
主容器

容器钩子

初始化容器启动之后,开始启动主容器,在主容器启动之前有一个 post start hook(容器启动后钩子)和 pre stop hook(容器结束前钩子),无论启动后还是结束前所做的事我们可以给它放两个钩子,这个钩子就表示用户可以用它来钩住一些命令,来执行它,做开场前的预设,结束前的清算,如 awk 有 begin,end,和这个效果类似。
postStart: 该钩子在容器被创建后立即触发,通知容器它已经被创建。如果该钩子对应的 hook handler 执行失败,则该容器会被杀死,并根据该容器的重启计谋决定是否要重启该容器,这个钩子不必要通报任何参数。
preStop: 该钩子在容器被删除前触发,其所对应的 hook handler 必须在删除该容器的请求发送 给 Docker daemon 之前完成。在该钩子对应的 hook handler 完成后不论执行的效果怎样,Docker daemon 会发送一个 SGTERN 信号量给 Docker daemon 来删除该容器,这个钩子不必要通报任何参数。
在 k8s 中支持两类对 pod 的检测
第一类叫做 livenessprobe(pod 存活性探测): 存活探针重要作用是,用指定的方式检测 pod 中的容器应用是否正常运行,如果检测失败,则认为容器不健康,那么 Kubelet 将根据 Pod 中设置的 restartPolicy 来判定 Pod 是否要举行重启操作,如果容器配置中没有配置 livenessProbe,Kubelet 将认为存活探针探测不停为乐成状态。 get pods里的status就是存活探测
第二类是状态检 readinessprobe(pod 就绪性探测):用于判定容器中应用是否启动完成,当探测乐成后才使 Pod 对外提供网络访问,设置容器 Ready 状态为 true,如果探测失败,则设置容器的 Ready 状态为 false。
创建 pod 必要经过哪些阶段?

当用户创建 pod 时,这个请求给 apiserver,apiserver 把创建请求的状态保存在 etcd 中;接下来 apiserver 会请求 scheduler 来完成调理,如果调理乐成,会把调理的效果(如调理到哪个节点上了,运行在哪个节点上了,把它更新到 etcd 的 pod 资源状态中)保存在 etcd 中,一旦存到 etcd 中而且完成更新以后,如调理到 k8snode1 上,那么 node1 节点上的 kubelet 通过 apiserver 当中的状态变革知道有一些使命被执行了,以是此时此 kubelet 会拿到用户创建时所提交的清单,这个清单会在当前节点上运行或者启动这个 pod,如果创建乐成或者失败会有一个当前状态,当前这个状态会发给 apiserver,apiserver 在存到 etcd 中;在这个过程 中,etcd 和 apiserver 不停在打交道,不停的交互,scheduler 也到场此中,负责调理 pod 到符合的 node 节点上,这个就是 pod 的创建过程.
pod 在整个生命周期中有非常多的用户行为:
1、初始化容器完成初始化
2、主容器启动后可以做启动后钩子
3、主容器结束前可以做结束前钩子
4、在主容器运行中可以做一些健康检测,如 liveness probe,readness probe
Pod 容器探测和钩子

容器钩子:postStart 和 preStop

postStart:容器创建乐成后,运行前的使命,用于资源摆设、情况准备等。
preStop:在容器被终止前的使命,用于优雅关闭应用步伐、通知其他体系等。
  1. ......
  2. containers:
  3. - image: sample
  4. name: war
  5. lifecycle:
  6.   postStart:         #钩子
  7.    exec:
  8.    command:         #命令
  9.     - “cp”
  10.     - “/sample.war”
  11.     - “/app”
  12. prestop:                 #钩子
  13.   httpGet:                 #httpget的探针
  14.    host: monitor.com        
  15.    path: /waring
  16.   port: 8080
  17.   scheme: HTTP
  18. ......
  19. 以上示例中,定义了一个 Pod,包含一个 JAVA 的 web 应用容器,其中设置了 PostStart
  20. 和PreStop 回调函数。即在容器创建成功后,复制/sample.war 到/app 文件夹中。而在容器
  21. 终止之前,发送 HTTP 请求到 http://monitor.com:8080/waring,即向监控系统发送警告。
  22. #可以看帮助文档
  23. [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,仍旧会给一个很短的优雅退出时间段,才会开始被逼迫杀死。如下:
  1. spec:
  2. containers:
  3. - name: nginx-demo
  4. image: centos:nginx
  5. lifecycle:
  6. preStop: #钩子
  7. exec:
  8. command: ["/usr/local/nginx/sbin/nginx","-s","quit"]  #删除之前会先停掉nginx再删除容器
  9. ports:
  10. - name: http
  11. containerPort: 80
复制代码
写在末了

创作不易,如果以为内容对你有帮助,贫苦给个三连关注支持一下我!如果有错误,请在评论区指出,我会及时更改!
如今正在更新的系列:从零开始学k8s
感谢各位的观看,文章掺杂个人理解,如有错误请联系我指出~


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4