Pod对象自从创建开始至其终止退出的时间范围称为其声明周期。在这段时间中,Pod会处于多种不同的状态,并执行一些操作:
1.其中,创建主容器(main container)为必需的操作。2.其它可选的操作还包括初始化容器(init container)3.容器启动后钩子(post start hook)4.容器的存活性探测(liveness probe)5.就绪性探测(readiness probe)6.以及容器终止前钩子(pre stop hook)等7.这些操作是否执行则取决于 Pod 的定义。
Pod的相位
无论是用户手动创建的Pod,还是通过Deployment等控制器创建的Pod,Pod总是应该处于其生命进程中以下几个相位(phase)之一。
•pending:API Server创建了Pod资源对象并已存入etcd中,但它尚未被调度完成,或仍处于从仓库下载镜像的过程中。•Succeeded:Pod中的所有容器都已经成功终止并且不会被重启。•Failed:所有容器都已经被终止,但至少有一个容器终止失败,即容器返回非0值的退出状态或已经被系统终止。•Unknown:API Server无法正常获取到Pod对象的状态信息,通常是由于其无法与所在的工作节点的kubelet通信所致。
Pod相位是在其生命周期中的宏观概述,而非对容器或Pod对象的综合汇总,而且相位的数量和含义被严格界定,它仅包含上面列举的相位值。
Pod的创建过程
Pod是Kubernetes的基础单元,理解它的创建过程对于了解系统运作大有帮助,下图中描述了一个Pod资源对象的典型过程。
1.用户通过kubectl或者其他API客户端提交Pod Spec给API Server。2.API Server将Pod对象的相关信息存入etcd中。3.待写入etcd操作完成,etcd将写入操作完成信息发送给API Server。4.API Server将etcd写入完成信息返回给kubectl或者其他客户端。5.kube-scheduler监听到API Server要创建一个新的Pod,然后开始对Pod进行调度绑定到Node。6.绑定Node成功后,kube-scheduler将bind结果返回给API Server。7.API Server将bind信息存储到etcd系统中。8.etcd将存储结果返回给API Server。9.API Server告知kube-scheduler调度Pod信息已存储完成。10.kubelet也在一直监听API Server,所以kubelet从API Server得知有一个Pod被调度到当前Node上,此时API Server也在监kubelet的信息。11.kubelet调用当前节点的Docker来启动容器。12.容器启动成功后,docker将启动状态返回给kubelet。13.kubelet收到docker返回的容器状态信息后,将容器状态信息更新给API Server。14.API Server将Pod更新信息写入到etcd中。15.etcd写入后将写入结果返回给API Server。16.API Server将确认信息发送至相关的kubelet,事件将通过它被接受。
Pod生命周期中的重要行为
除了创建应用容器(主容器及其他辅助容器)之外,用户还可以为Pod对象定义其生命周期中的多种行为,如初始化容器、存活性探测及就绪性探测等。
初始化容器
初始化容器(init container)即应用程序的主容器启动之前要运行的容器,常用于为主容器执行一些预置操作,他们具有两种典型的特征。1) 初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么Kubernetes需要重启它直到成功完成。2) 每个初始化容器都必须按定义的顺序串行运行容器,只有当初始化容器运行无异常过后,才能启动业务容器,业务容器启动顺序可以并发启动。
如果Pod的 spec.restartPolicy 重启策略字段为 "Never",那么运行失败的初始化容器不会被重启。后面会讲解关于Pod的重启策略。
Pod资源的 “spec.initContainers” 字段以列表的形式定义可用的初始化容器,下面的资源清单仅是一个初始化容器的使用示例。
cat init-pod.yamlapiVersion: v1kind: Podmetadata: name : nginx-pod-testspec: containers: - name: nginx-containers image: nginx:latest initContainers: - name: init-container image: busybox:latest command: ['sh', '-c', 'sleep 10']
查看Pod状态信息
#可以看到Pod正在初始化
kubectl get pods -o wide | grep nginx-pod
nginx-pod-test 0/1 PodInitializing 0 38s 10.244.3.58 k8s-node01 <none> <none>
#Pod已经正常运行
kubectl get pods -o wide | grep nginx-pod
nginx-pod-test 1/1 Running 0 63s 10.244.3.58 k8s-node01 <none> <none>
#查看容器运行的详细信息
kubectl describe pods/nginx-pod-test
生命周期的钩子函数
生命周期钩子函数(lifecycle hook)是编程语言(如 Angular)中常用的生命周期管理组件,它实现了程序运行周期中关键时刻的可见性,并赋予用户为此采取某种行动的能力,容器生命周期钩子使它能够感知其自身生命周期管理中的事件,并在相应的时刻到来时,运行由用户指定的代码或者命令,Kubernetes为容器提供了两种生命周期的钩子。
•postStart:用于容器创建完成之后立即运行的钩子处理器(handler),不过Kubernetes无法确保它一定会于容器中的ENTRYPOINT之前运行。•preStop:用于容器终止操作之前立即运行的钩子处理器,它以同步的方式调用,因此在其完成之前会阻塞删除容器操作的调用。
钩子处理器的实现方式有Exec
和HTTP
两种,前一种在钩子事件触发时直接在当前容器中运行由用户定义的命令,后一种则是在当前容器中向某URL发起HTTP请求。postStart和preStop处理器定义在容器的spec.lifecycle嵌套字段中,定义方法如下资源清单所示。
cat hook-pod.yamlapiVersion: v1kind: Podmetadata: name: lifecycle-demospec: containers: - name: lifecycle-container image: nginx:latest lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo 'lifecycle hooks handler' > /usr/share/nginx/html/test.html"]
查看Pod状态
#创建Pod
kubectl apply -f hook-pod.yaml
#查看Pod状态
kubectl get pods -o wide | grep lifecycle-demo
lifecycle-demo 1/1 Running 0 19s 10.244.3.60 k8s-node01 <none> <none>
#访问我们在容器启动后执行命令的结果
curl http://10.244.3.60/test.html
lifecycle hooks handler
Pod的终止过程
Pod对象代表了在Kubernetes集群节点上运行的进程,它可能曾用于处理生产数据或向用户提供服务等,于是,当Pod本身不在具有存在的价值时,如何将其优雅地终止就显得尤为重要了,而用户也需要能够在正常提交删除操作后可以获知其何时开始终止并最终完成。操作中,当用户提交了删除请求之后,系统就会进行强制删除操作的宽限期倒计时,并将TERM信息发送给Pod对象中的每个容器的主进程。宽限期倒计时结束后,这些进程将收到强制终止的KILL信息,Pod对象随即也将由API Server删除。如果在等待进程终止的过程中,kubelet或容器管理器发生了重启,那么终止操作会重新获得一个满额的删除宽限期并重新执行删除操作。
如下图所示,一个典型的Pod对象终止流程具体如下。
1.用户发送删除Pod对象的命令。2.API Server中的Pod对象会随着时间的推移而更新,在宽限期内(默认为30秒),Pod被视为 "dead"。3.将Pod标记为 "Terminating" 状态。4.(与第三步同时运行) kubelet在监控到Pod对象转为 "Terminating"状态的同时启动Pod关闭过程。5.(与第三步同时运行)端点控制器监控到Pod对象的关闭行为时将其从所有匹配到此端点Service资源的端点列表中移除。6.如果当前Pod对象啊定义了preStop钩子处理器,则在其标记为 "Terminating" 后会以同步的方式启动执行;如若宽限期结束后,perStop仍未执行结束,则第2步会被重新执行并额外获取一个时长为2秒的小宽限期。7.Pod对象中的容器主进程收到TERM信号。8.宽限期结束后,若存在任何一个扔在运行的进程,那么Pod对象即会收到SIGKILL信号。9.kubelet请求API Server将此Pod资源的宽限期设置为0从而完成删除操作,它变得对用户不可见。
默认情况下,所有删除操作的宽限期都是30秒,不过kubectl delete命令可以使用 --grace-period= 选项自定义其时长,若使用0值则表示直接强制删除指定的资源,不过,此时需要同时为命令使用 --force 选项。