

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 有 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 时,这个请求给 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
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
感谢各位的观看,文章掺杂个人理解,如有错误请联系我指出~

这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
这是我理想中想要的。用户做:a="hello"输出为Youjustallocated"a"!=>"Hello"顺序无关紧要,只要我能实现该消息即可。 最佳答案 不,没有直接的方法可以做到这一点,因为在执行代码之前,Ruby字节码编译器会丢弃局部变量名。YARV(MRI1.9.2中使用的RubyVM)提供的关于局部变量的唯一指令是getlocal和setlocal,它们都对整数索引进行操作,而不是变量名。以下是1.9.2源代码中insns.def的摘录:/****************************************
目录SpringBootStarter是什么?以前传统的做法使用SpringBootStarter之后starter的理念:starter的实现: 创建SpringBootStarter步骤在idea新建一个starter项目、直接执行下一步即可生成项目。 在xml中加入如下配置文件:创建proterties类来保存配置信息创建业务类:创建AutoConfiguration测试如下:SpringBootStarter是什么? SpringBootStarter是在SpringBoot组件中被提出来的一种概念、简化了很多烦琐的配置、通过引入各种SpringBootStarter包可以快速搭建出一
我正在探索ActiveSupport::Notifications,并且想要更多关于'instantiation.active_record'的信息,而不仅仅是:record_count和:类名[1].例如,ActiveSupport::Notifications.subscribe/instantiation.active_record/do|*args|args.status#DatabaseorActiveRecordreturnstatusargs.result#Theactualresultsetreturnedargs.etc..#AnyotherinfoIcancolle
文章目录🔥Linux系统目录结构🔥Linux用户和用户组🔥Linux用户管理🔥Linux系统目录结构文件系统组织结构⭐ /lib系统开机所需要最基本的动态链接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。⭐ /lost+found一般情况下是空的,当系统非法关机后,这里就存放了一些文件。⭐ /etc所有系统管理所需要的配置文件和子目录my.conf⭐ /usr用户的很多应用程序和文件都放在这个目录下。⭐ /bin是Binary的缩写,这个目录存放着经常使用的命令⭐ /sbin(usr/sbin、/usr/local/sbin)sbin就是peruse
我们的RSpec测试套件中有相当多的测试。目录结构看起来像-spec/truncation/example1_spec.rbexample2_spec.rb...transaction/example1_spec.rbexample2_spec.rb...我想在transaction/文件夹中的所有规范文件运行之前恢复测试数据库转储,并在所有测试完成后将其清空。有办法吗?有before(:suite)和after(:suite)Hook,但它们适用于单个规范文件。有没有办法在RSpec中为目录提供前后Hook? 最佳答案 你在使用R
文章目录一、污点(Taint)1、污点简介2、污点的组成3、污点的设置和去除二、容忍(Tolerations)1、容忍简介2、容忍的基本用法3、示例4、多污点与多容忍配置三、警戒(cordon)和转移(drain)四、Pod启动阶段(相位phase)五、故障排除步骤一、污点(Taint)节点亲和性,是Pod的一种属性(偏好或硬性要求),它使Pod被吸引到一类特定的节点Taint则相反,它使节点能够排斥一类特定的PodTaint和Toleration相互配合,可以用来避免Pod被分配到不合适的节点上。每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的Pod,是不会被
我正在尝试使用ruby改进来应用Rails钩子(Hook)。我想避免猴子补丁。当猴子修补时它会这样工作ActiveRecord::Base.class_evaldoafter_finddo#dosomethingwithmy_methodenddefmy_method#somethingusefulendend我已经能够通过做这样的事情来拥有类方法:moduleActiveRecordRefinementsrefineActiveRecord::Base.singleton_classdodefmy_method#somethingcoolendendend但我无法运行钩子(Hoo
我在/usr/local/lib中安装了一些本地库。我现在正在尝试安装一个需要这些的gem,以便正确构建,但是gem构建失败,因为它找不到图书馆。gem的extconf.rb文件试图确认它可以找到库have_library()但由于某种原因失败了。我尝试设置一堆环境变量,但似乎没有任何效果:irb(main):003:0>require'mkmf'=>trueirb(main):004:0>have_library('gecodesearch')checkingformain()in-lgecodesearch...no=>falseirb(main):005:0>ENV['LD_LI
我最近一直在练习一些Ruby元编程,并且想知道assigninganonymousclassestoconstants.在Ruby中,可以创建一个匿名类,如下所示:anonymous_class=Class.new#=>#可以创建此类的新实例:an_instance=anonymous_class.new#=>#:0x007f9c5afb0330>现在,当匿名类被分配给一个常量时,该类现在有了一个专有名称:Foo=anonymous_class#=>Foo之前创建的实例现在也是该类的实例:an_instance#=>#我的问题:匿名类赋值给常量的时候有没有钩子(Hook)方法?有很多h