9.1 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,它不会重新启动。初始化容器的官方地址:https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#init-containers-in-use[root@k8s01 test1]# cat init.yamlapiVersion: v1kind: Podmetadata: name: app-pod labels: app: myappspec: containers: - name: myapp-container image: busybox:1.28 imagePullPolicy: IfNotPresent command: ['sh', '-c', 'echo The app is running! && sleep 3600'] initContainers: - name: init-myservice image: busybox:1.28 imagePullPolicy: IfNotPresent 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 imagePullPolicy: IfNotPresent 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"]kubectl apply -f init.yaml[root@k8s01 test1]# kubectl get podsNAME READY STATUS RESTARTS AGEapp-pod 0/1 Init:0/2 0 6s[root@k8s01 test1]# cat service.yaml---apiVersion: v1kind: Servicemetadata: name: myservicespec: ports: - protocol: TCP port: 80 targetPort: 9376---apiVersion: v1kind: Servicemetadata: name: mydbspec: ports: - protocol: TCP port: 80 targetPort: 9377kubectl apply -f service.yaml[root@k8s01 test1]# kubectl get podsNAME READY STATUS RESTARTS AGEapp-pod 0/1 PodInitializing 0 73s[root@k8s01 test1]# kubectl get podsNAME READY STATUS RESTARTS AGEapp-pod 1/1 Running 0 75s
9.2 主容器
1、容器钩子初始化容器启动之后,开始启动主容器,在主容器启动之前有一个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 将认为存活探针探测一直为成功状态。第二类是状态检readinessprobe(pod就绪性探测):用于判断容器中应用是否启动完成,当探测成功后才使Pod对外提供网络访问,设置容器Ready状态为true,如果探测失败,则设置容器的Ready状态为false。
9.3 创建pod需要经过哪些阶段
当用户创建pod时,这个请求给apiserver,apiserver把创建请求的状态保存在etcd中;接下来apiserver会请求scheduler来完成调度,如果调度成功,会把调度的结果(如调度到哪个节点上了,运行在哪个节点上了,把它更新到etcd的pod资源状态中)保存在etcd中,一旦存到etcd中并且完成更新以后,如调度到k8s01上,那么k8s01节点上的kubelet通过apiserver当中的状态变化知道有一些任务被执行了,所以此时此kubelet会拿到用户创建时所提交的清单,这个清单会在当前节点上运行或者启动这个pod,如果创建成功或者失败会有一个当前状态,当前这个状态会发给apiserver,apiserver在存到etcd中;在这个过程中,etcd和apiserver一直在打交道,不停的交互,scheduler也参与其中,负责调度pod到合适的node节点上,这个就是pod的创建过程pod在整个生命周期中有非常多的用户行为:1、初始化容器完成初始化2、主容器启动后可以做启动后钩子3、主容器结束前可以做结束前钩子4、在主容器运行中可以做一些健康检测,如liveness probe,readness probe