Pod对象自从其创建开始至其终止退出的时间范围称为其生命周期。在这段时间内,Pod会处于多种不同的状态,并执行一些操作;其中,创建主容器(main container)为必需的操作,其他可选的操作还包括运行初始化容器(init container)、容器启动后钩子(post start hook)、容器的存活探测(liveness probe)、就绪性探测(readiness probe)以及容器终止前钩子(pre stop hook)等,这些操作操作是否执行则取决于pod的定义,如下图:
在这里插入图片描述
在这里插入图片描述

Pod的创建过程

理解Pod的生命周期前,我们来看一下Pod的创建过程,流程大致如下图:
在这里插入图片描述

  1. 用户通过kubelet或其他API客户端提交Pod spec给API Server。
  2. API Server尝试着将Pod对象的相关信息存入etcd中,待写入操作执行完成,API Server即会返回确认信息至客户端。
  3. API Server开始反映etcd中的状态变化。
  4. 所有的kubernetes组件均使用‘watch’机制来跟踪检查API Server上的相关变动。
  5. kube-scheduler(调度器)通过其‘watch’察觉到API Server创建了新的Pod对象但尚未绑定至任何工作节点。
  6. kube-scheduler为Pod对象挑选一个工作节点并将信息更新至API Server。
  7. 调度结果信息由API Server更新至etcd存储系统,而且API Server也开始反映此Pod对象的调度结果。
  8. Pod被调度到目标工作节点上的kubelet尝试在当前节点上调用Docker启动容器,并将容器的结果状态回送至API Server。
  9. API Server将Pod的状态信息存入etcd中。
  10. 在etcd确认写入操作成功完成后,API Server将确认信息发送至相关的kubelet,事件将通过它被接受。

整体流程

client向APIServer发送创建pod的请求:

  1. APIServer将pod信息存入etcd,通知Scheduler;
  2. Scheduler根据调度算法,为pod选择一个节点,然后向APIServer发送更新spec.nodeName;
  3. APIServer更新完毕,通知对应节点的kubelet;
  4. kubelet发现pod调度到本节点,创建并运行pod的容器;

在这里插入图片描述

APIServer处理pod启动

APIServer收到创建pod的请求后:

  • 首先,对client来源进行认证,实现方式是证书(cert)或token(sa);
  • 然后,对client进行鉴权,确认其是否有创建pod的权限,实现方法是rbac;
  • 然后,通过准入控制插件验证或修改资源请求,常用的准入控制插件有:LimitRanger/ResourceQuota/NamespaceLifecycle;
  • 最后,将pod资源存储到etcd;
    在这里插入图片描述
Scheduler处理pod启动

Scheduler监听到APIServer创建pod的事件后:

  • 按照默认的调度算法(预选算法+优选算法),为pod选择一个可运行的节点nodeName;
  • 向APIServer发送更新pod的消息:pod.spec.nodeName;
  • APIServer更新pod,通知nodeName上的kubelet,pod被调度到了nodeName;
Kubelet处理pod启动

kubelet监听到APIServer创建pod的事件后,通知容器运行时dockerd拉取镜像,创建容器,启动容器。
在这里插入图片描述
pod中容器的启动过程:

  • InitC容器:

     多个initC顺序启动,前一个启动成功后才启动下一个;
     仅当最后一个initC执行完毕后,才会启动主容器;
     常用于进行初始化操作或等待依赖的服务已ok;
     postStart钩子:
    
  • postStart与container的主进程并行执行;

     在postStart执行完毕前,容器一直是waiting状态,pod一直是pending状态;
     若postStart运行失败,容器会被杀死;
    
  • startupProbe钩子:

     v1.16版本后新增的探测方式;
     若配置了startupProbe,就会先禁止其他探测,直到成功为止;
    
  • readinessProbe探针:

     探测容器状态是否ready,准备好接收用户流量;
     探测成功后,将pod的endpoint添加到service;
    
  • livenessProbe探针:

     探测容器的健康状态,若探测失败,则按照重启策略进行重启;
    
  • containers:

     多个container之间是顺序启动的
    

POD的终止过程

在这里插入图片描述

  1. 用户发送删除Pod对象的命令。
  2. Api服务器中的Pod对象会随着时间的推移而更新,在宽限期内(默认为30秒),Pod被视为“dead”。
  3. 将Pod标记为“Terminating”状态。
  4. (与第三步同时运行)kubelet在监控到Pod对象转为“Terminating”状态的同时启动Pod关闭过程。
  5. (与第三步同时运行)端点控制器监控到 Pod 对象的关闭行为时将其从所有匹配到此端点的Service资源的端点列表中移除
  6. 如果当前 Pod 对象定义了 preStop钩子处理器,则在其标记为terminating后立即会以同步的方式启动执行;如果宽限期结束后,preStop仍未执行结束,则第二步会被重启执行并额外获取一个时长为2秒的小宽限期。
  7. Pod对象中的容器进程收到TERM信号。
  8. 宽限期结束后,若存在任何一个仍在运行的进程,那么Pod对象即会收到SIGKILL信息。
  9. kubelet 请求 API Server将此 Pod 资源的宽限期设置为 0 从而完成删除操作,它变得用户不再可见

默认情况下,所有删除操作的宽限期都是30秒,不过, kubectl delete 命令可以使用参数 --grance-period= 来自定义其时长,若使用 0 值表示直接强制删除指定的资源,不过,此时需要为命令配合参数 --force选项才可以。

整体流程

APIServer接收到删除Pod的请求后:

  • 首先,修改etcd中的状态;

  • 然后,把删除pod的事件,通知给kubelet和endpoint-controller;

     kubelet: 负责pod资源的删除;
     endpoint-controller: 负责endpoint资源的删除;
     两个组件并行执行;
    

在这里插入图片描述

Kubelet处理pod关闭

kubelet关闭pod的时候,会关闭pod中的每一个容器;kubelet给容器一定的时间(TerminationGracePeriod)优雅的停止。

kubelet终止容器的过程:

	执行preStop,等待它执行完毕;
	向容器的进程发送SIGTERM;
	等待容器优雅的关闭或超时(terminationGracePeriod);
	若关闭超时,则发送SIGKILL强制关闭;

在这里插入图片描述

endpoint-controller处理pod关闭

endpoint-controller接收到pod删除的通知时,向APIServer发送请求,修改svc的endpoints对象,从pod所在svc中删除该pod的endpoint。
然后,APIServer通知节点上的kube-proxy组件,kube-proxy会修改本机的iptables/ipvs规则,将该endpoint移除。

Kubelet和endpoint-controller并行执行的问题

kube-proxy可能由于过载处理请求变慢,会出现:

kubelet已经把容器删除,但kube-proxy还未更新iptables。

这种情况下,流量还会被分发到对应的endpoint,但是pod已删除,客户端返回"连接拒绝"之类的错误。

目前的解决方法,在pod的preStop中sleep一段时间,等待kube-proxy更新iptables完毕:

lifecycle:
  preStop:
    exec:
      command: [ "sh", "-c", "sleep 10" ]
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐