文章目录

  • Pod Lifecle
  • Pod的阶段:Pod phase
  • 容器的状态:Container states
  • 容器的探针:Container probes
  • 重启策略:restartPolicy
  • Pod删除
  • Pod的回收
  • 参考资料


Pod Lifecle

Pod的阶段:Pod phase

相关字段:.status.phase phase表示一个Pod处于其生命周期的哪个阶段,一共有以下5个可能的取值:

  • Pending:Pod已经被k8s系统接受,但Pod中还有容器没有被创建。Pod被调度前和下载容器镜像的时候都处于这个阶段
  • Running:Pod已经被调度到Node上,所有的容器都已经被创建,并且至少有一个容器还在运行中(正在启动或重启中的容器也算)
  • Succeeded:Pod中的所有容器都成功停止,并且不会再次重启
  • Failed:Pod中的所有容器都已经停止,并且至少有一个容器是以失败停止的(以非0状态退出或被系统强制停止)
  • Unknown:由于某种原因无法获得Pod的状态,一般是和Pod所在的Host出现通信问题导致

Pod phase的查看方式:

kubectl get pods pi2-ll9dn -o yaml |grep 'phase'
phase: Succeeded

注意,使用以下命令看到的STATUS并不是Pod的phase:

kubectl get pod pi2-ll9dn
NAME        READY   STATUS      RESTARTS   AGE
pi2-ll9dn   0/1     Completed   0          4h50m

Pod并没有Completed这个phase。

容器的状态:Container states

相关字段:.status.containerStatuses[index].state(containerStatuses是一个数组,每个数组元素对应Pod中的一个容器)
我们知道,一个Pod中是包含有多个容器的,所以Pod的状态或者说阶段并不能直接反映Pod中容器的状态。当一个Pod被调度到Node上时,kubelet就会开始使用容器运行时(如Docker)创建容器,容器的状态可以通过命令kubectl describe pod [POD_NAME]查看,一共以下3种状态:

  • Waiting:容器默认的状态,只要不是Running和Terminated状态就是这个状态,拉取镜像的时候也是这个状态
  • Running:表示容器正在正常运行中,如果定义了postStarthook(钩子),则该hook会在容器进入Running状态前执行
  • Terminated:表示容器已经执行完并停止运行。如果定义了preStop钩子,在一个容器进入Terminated状态前,该钩子会被执行。执行完有两种情况,一种是正常退出,另外一种是因为某种原因失败退出,通过ReasonExit Code查看容器停止的原因和状态码:
State:          Terminated
   Reason:       Completed
   Exit Code:    0
   Started:      Wed, 30 Jan 2019 11:45:26 +0530
   Finished:     Wed, 30 Jan 2019 11:45:26 +0530

容器的探针:Container probes

Node上的kebulet可以使用探针来周期性地检测运行中的容器的状态。探针的实现方式有3种:

  • 在容器内执行某个特定的命令,如cat /tmp/healthy,如果命令返回的状态码为0,则认为探测成功
  • 向容器的IP和指定端口发起一个TCP检测,如果成功则认为探测成功,类似于使用telnet来检测Linux服务器上的端口
  • 向容器的IP和指定端口发起一次HTTP请求,如果返回的状态码在[200,400)区间内则认为探测成功

有如下3种探针:

  • livenessProbe:检测容器是否还在运行中,kubelet使用这个探针来知道什么时候重启一个容器,一旦探测失败,kubelet会把该容器kill掉,至于容器需不需要重启,还需要看容器所在的Pod的重启策略(restartPolicy,详见下文),如果容器没有提供这个探针,则默认成功
  • readinessProbe:用于检测容器是否已经准备好接收服务请求,如果探测失败,控制器会把这个Pod的IP地址从相应的Service上移除。在容器启动时的初始化延迟(initial delay,详见下文的initialDelaySeconds)时间内,探测默认为失败。如果一个容器没有提供这个探针,默认为成功(在initial delay之后)
  • startupProbe:用于容器启动时判断容器是否启动完成,在这个探针探测成功前,即容器启动成功前,livenessProbe和readinessProbe探针都不会起作用,防止某些启动很慢的容器在启动过程中,livenessProbe探针探测容器失败触发容器重启导致死锁。如果这个探针探测失败(容器启动时间超过了阈值),kubelet会把这个容器kill掉,再根据restartPolicy决定是否创建容器

探针支持的属性:

  • initialDelaySeconds:默认值是0,最小值是0,容器启动后等待多久,liveness or readiness开始第1次执行
  • periodSeconds:多久执行一次探针,默认值是10,最小值是1
  • timeoutSeconds:探针执行超时时间,默认值是1,最小值是1
  • successThreshold:失败后执行多少次探针成功才算成功,默认值是1,最小值是1,对于liveness来说必须是1
  • failureThreshold:探针连续失败多少次后才算失败,默认是3,最小值是1

探针的定义方式可参考:

apiVersion: v1
kind: Pod
metadata:
  name: demo
spec:
  containers:
  - name:demo-ctr
    image: polinux/stress
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
    livenessProbe: # liveness探针-command
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5 # 第1次执行探针时,延迟5s执行
      failureThreshold: 2 # 探针执行失败2次后容器状态变为失败
      periodSeconds: 5 # 每5s执行一次探针
    readinessProbe: # readinessProbe的属性和livenessProbe的属性一模一样
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    startupProbe:  # startupProbe
      httpGet:
        path: /healthz
        port: liveness-port
      failureThreshold: 30
      periodSeconds: 10  # 容器启动30*10=300s内liveness和readiness探针不会执行,300s后startup探针还没成功,容器会被kill掉重启

重启策略:restartPolicy

当一个容器执行完退出时,不管是成功还是失败,都会触发重启策略,根据restartPolicy的设置来决定要不要重启该容器,restartPolicy有以下3种取值:

  • Always:默认取值,不管是成功退出还是失败退出,都尝试重启该容器,Pod的阶段会保持为Running
  • OnFailure:失败的时候重启,Pod的阶段保持为Running,成功的时候不重启,Pod的阶段转为Succeeded
  • Never:不管失败还是成功都不重启,Pod的阶段转为Failed或者Succeeded 当一个Pod退出后要重启时,有一段指数级递增的延迟(10s,20s,40s…最大达到5分钟),当一个容器重启并运行10分钟不出问题后,这个延迟会重置。

Pod删除

因为Pod代表着一组运行在node上的进程,所以允许这些进程在不再需要的时候能优雅地退出很重要(而不是被一个KILL信号强制停止,没有机会进行资源清理)。
k8s的设计目标在于让用户可以发起删除请求和知道进程什么时候终止,并能够确保删除最终完成。当对一个Pod发起一个删除请求时,集群在强制删掉这个Pod前,会记录和追踪一段grace period(terminationGracePeriodSeconds, 默认是30s),在这段时间内,kubelet会尝试优雅地(graceful)关闭Pod。
一般的做法是,容器运行时(如Docker)会发送TERM信号给Pod中每个容器的主进程,一旦grace period结束,容器运行时会发送KILL给还没有成功结束的进程,然后Pod在API Server上被删除掉。如果kubelet或容器运行时的管理服务在等待这些进程优雅退出的时候重启了,那么集群会重新尝试整个删除流程,包括grace period。
如果Pod中的容器定义了preStop钩子,那么终止容器(给容器发送TERMKILL信号)前会先执行该钩子,如果grace period时间过了钩子还没执行完,kubelet会额外增加2s的时间让容器有机会优雅地退出。如果preStop钩子需要执行很长时间的话,一般建议把terminationGracePeriodSeconds调大。
当grace period开始时,Pod就会被从可用的服务列表中移除,服务请求不会再被转发到这个Pod上。
当所有容器(包括pause)都停掉以后,kubelet会触发API Server把这个Pod删除掉

Pod的回收

对于已完成的Pod(包括Failed和Succeeded的Pod),它们的API对象会保留在系统中。当系统中创建的Pod数量超出了指定阈值(kube-controller-manager中的terminated-pod-gc-threshold)时,控制面板会清理这些已完成的Pod(包括Failed和Succeeded的Pod)。

参考资料

https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/