k8s-pod的生命周期

生命周期图

容器启动

1.pod容器启动之前,会有初始化容器(initContainer)会先进行环境的初始化
2.初始化后主容器(main container)开始启动
3.主容器启动之后会有一个post start之类的(启动后钩子函数)操作
4.post start执行之后就开始进行健康检查如:存活性探测(liveness probe)、就绪性探测(readiness probe)
容器终止
1可以在容器终止之前,设置pre stop操作(终止前钩子函数)
当出现特殊情况不能正常销毁pod时,大概会等待30秒之后强制终止
终止后容器是否能重启,取决于容器重启策略

容器重启策略

Always:表示容器挂了总是重启,这是默认策略
OnFailures:表示容器状态为错误时才重启,也就是容器正常终止时不重启
Never:表示容器挂了不予重启
对于Always这种策略,容器只要挂了,就会立即重启,这样是很耗费资源的。所以Always重启策略是这么做的:第一次容器挂了立即重启,如果再挂了就要延时10s重启,第三次挂了就等20s重启… 依次类推

 

pod生命周期的几个阶段

1.创建阶段在创建新Pod时
Kubernetes首先会检查使用的容器镜像是否存在,并检查Pod配置是否正确。如果一切正常,Kubernetes将创建一个名为“Pending”的初始状态。

2. 运行阶段一旦Pod处于Pending状态
Kubernetes将开始为它分配资源并启动容器。当所有容器都成功启动后,Pod将进入“Running”状态。

3. 容器故障恢复阶段在运行期间
如果某个容器意外终止,则Kubernetes将自动重启该容器。如果该容器无法自动重启,则Pod将进入“Failed”状态。

4. 更新阶段在进行更新操作时
Kubernetes首先会通过创建一个新的Pod来实现更新。然后,Kubernetes将停止旧Pod中的容器,并将它们迁移到新Pod中。一旦所有容器都成功迁移,旧Pod将被删除,“Rolling Update”过程就完成了。

5. 删除阶段当Pod不再需要时
可以通过删除Pod对象来释放资源。Kubernetes将删除所有关联的容器,并从集群中删除该Pod对象。

pod生命周期的几个状态

挂起(Pending):API Server已经创建了Pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中
运行中(Running):Pod已经被调度到某节点,并且所有容器都已经被kubelet创建完成
成功(Succeeded):Pod中的所有容器都已经成功删除并且不会被重启
失败(Failed):所有容器都已经删除,但至少有一个容器删除失败,即容器返回了非0值的退出状态
未知(Unknown):API Server无法正常获取到Pod对象的状态信息,通常由于网络通信失败所导致

Pod的创建过程

用户通过kubectl或其他的API客户端提交需要创建的Pod信息给API Server
API Server开始生成Pod对象的信息,并将信息存入etcd,然后返回确认信息至客户端
API Server开始反映etcd中的Pod对象的变化,其它组件使用watch机制来跟踪检查API Server上的变动
Scheduler发现有新的Pod对象要创建,开始为Pod分配主机并将结果信息更新至API Server
Node节点上的kubelet发现有Pod调度过来,尝试调度Docker启动容器,并将结果返回至API Server
API Server将接收到的Pod状态信息存入到etcd中

Pod的删除过程

用户向API Server发送删除Pod对象的命令
将Pod标记为terminating状态
kubelet在监控到Pod对象转为terminating状态的同时启动Pod关闭过程
端点控制器监控到Pod对象的关闭行为时,将其从所有匹配到此端点的service资源的端点列表中移除
如果当前Pod对象定义了preStop钩子处理器,则在其标记为terminating后会以同步的方式启动执行
Pod对象中的容器进程收到停止信号
宽限期结束后(默认30s,pod去执行一些清理动作),如果Pod中还存在运行的进程,那么Pod对象会收到立即删除的信号
kubectl请求API Server将此Pod资源的宽限期设置为0从而完成删除操作,此时Pod对于用户已经不可用

init container初始化容器

初始化容器是在Pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:

初始化容器必须运行完成直至结束,如果某个初始化容器运行失败,那么kubernetes需要重启它直至成功完成
初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行
初始化容器有很多的应用场景,下面列出的是最常见的几个:

提供主容器镜像中不具备的工具程序或自定义代码
初始化容器要先于应用容器串行启动并运行完成,可用于满足应用容器启动的先决要求

spec:
  containers:
    - name: nginx-container
      image: nginx:latest
  initContainers:
    - name: init-mysql
      image: busybox
      command: ['/bin/sh', '-c', 'until ping 192.168.23.188 -c 1; do echo waiting for mysql; sleep 3; done;']
    - name: init-redis
      image: busybox
      command: ['/bin/sh', '-c', 'until ping 192.168.23.189 -c 1; do echo waiting for redis; sleep 3; done;']

 

preStop

这个钩子在容器终止之前会被调用。它是阻塞的,意味着它是同步的, 所以它必须在删除容器的调用发出之前完成。主要用于优雅关闭应用程序、通知其他系统等。

配合参数 terminationGracePeriodSeconds 使用 默认容器变为删除中保留30s

应用场景

注册中心下线

数据清理

数据消费

例子

apiVersion: v1
kind: Pod
metadata:
  name: hook-demo2
  labels:
    app: hook
spec:
  containers:
  - name: hook-demo2
    image: nginx
    ports:
    - name: webport
      containerPort: 80
    volumeMounts:
    - name: message
      mountPath: /usr/share/
    lifecycle:
      preStop:
        exec:
          command: ['/bin/sh', '-c', 'echo hello preStop Handler > /usr/share/message']

 

PostStart

这个钩子在容器创建后会被执行。通常用于一些环境准备和资源部署等。不过需要注意的是如果钩子执行太长时间会导致容器不能正常运行,以至于被挂起的状态。

例子

apiVersion: v1
kind: Pod
metadata:
  name: hook-demo1
spec:
  containers:
  - name: hook-demo1
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo hello postStart handler > /usr/share/message"]

 

posted @ 2023-10-23 10:14  意犹未尽  阅读(32)  评论(0编辑  收藏  举报