Loading

k8s回调函数

回调函数

Kubernetes 为容器提供了生命周期回调。 回调使容器能够了解其管理生命周期中的事件,并在执行相应的生命周期回调时运行在处理程序中实现的代码。Kubernetes 支持 PostStart 和 PreStop 事件。 当一个容器启动后,Kubernetes 将立即发送 PostStart 事件;在容器被终结之前, Kubernetes 将发送一个 PreStop 事件。

PostStart

PostStart回调在容器创建后立即执行,但是PostStart并不能保证在容器ENTRYPOINT之前运行,所以PostStart的执行相对于容器的代码执行是异步的。

PostStart主要用于资源部署、环境准备等。

只有 PostStart 处理函数执行完毕,容器的状态才会变成 RUNNING。

PreStop

PreStop在容器终止前立即被调用,它是阻塞的,所以它必须在删除容器的调用触发之前完成。

PreStop主要用于优雅关闭应用程序、通知其他系统等。

如果钩子在执行期间挂起,Pod阶段将停留在Running状态并且不会达到failed状态。

另外,PreStop的执行现对于SIGTERM信息,也是异步的,k8s也不会等待PreStop执行完成。

Pod生命周期

pod的生命周期,它主要包含以下的过程:

  1. pod创建;
  2. 运行初始化容器(init container);
  3. 运行主容器(main container);
    • 容器启动后钩子(post start)、容器终止前钩子(pre stop),在启动后就执行post start
    • 容器的存活性检测(liveness probe)、就绪性检测(readiness probe)。
  4. pod终止过程,pod完全退出之前执行pre stop操作,也就是收尾工作。

pod生命周期

优雅关闭

PreStop是实现Pod优雅关闭的重要工具。

进行Pod优雅关闭的重要性主要体现在以下几个方面:

  1. 避免服务中断:通过优雅关闭,Pod可以在终止前完成当前正在处理的请求,确保服务不会因为Pod的突然终止而中断。
  2. 确保数据一致性:优雅关闭允许Pod在终止前通过PreStop Hook完成必要的数据持久化或事务处理,从而确保数据的一致性。
  3. 最小化用户体验影响:通过优雅关闭,可以避免将流量路由到已经被删除的Pod,减少用户请求处理失败的可能性。在滚动更新或扩展Pod时,优雅关闭能够确保服务的平滑过渡,对用户来说几乎是无感知的。
  4. 合理利用资源:优雅关闭允许Pod在终止前释放占用的资源,避免资源浪费和泄露,提高资源的利用率。

Pod终止过程:

  • 【第一步】用户发出删除 pod 命令
  • 【第二步】K8S 会给旧POD发送SIGTERM信号;将 pod 标记为“Terminating”状态;pod 被视为“dead”状态,此时将不会有新的请求到达旧的pod;
  • 【第三步】并且等待宽限期(pod.spec.terminationGracePeriodSeconds 参数定义,默认情况下30秒)这么长的时间
  • 第三步同时运行,监控到 pod 对象为“Terminating”状态的同时启动 pod 关闭过程
  • 第三步同时进行,endpoints 控制器监控到 pod 对象关闭,将pod与service匹配的 endpoints 列表中删除
  • 如果 pod 中定义了 preStop 处理程序,则 pod 被标记为“Terminating”状态时以同步的方式启动执行preStop;若宽限期结束后,preStop 仍未执行结束,第二步会重新执行并额外获得一个2秒的小宽限期(最后的宽限期,所以定义preStop 注意时间,和terminationGracePeriodSeconds 参数配合使用),
  • Pod 内对象的容器收到 TERM 信号
  • 宽限期结束之后,若存在任何一个运行的进程,pod 会收到 SIGKILL 信号
  • Kubelet 请求 API Server 将此 Pod 资源宽限期设置为0从而完成删除操作

[!NOTE]

如果应用程序完成关闭并在terminationGracePeriod完成之前退出,Kubernetes会立即进入下一步。

总的来说,Pod优雅关闭是Kubernetes中一个重要的功能,它结合了PreStop Hook和宽限期等机制,确保Pod在终止前能够优雅地完成必要的清理工作,从而保持服务的稳定性和可用性、确保数据一致性、提升用户体验和合理利用资源。在进行Pod管理时,应该充分了解和利用Pod优雅关闭的功能。

PostStart对比初始化容器

PostStart容器是在一个Pod中,所有容器启动之后启动的一个容器。与Init Container不同,PostStart容器不需要先于其他容器启动,它的主要作用是在所有容器启动之后,完成一些额外的任务。

可以使用PostStart容器来进行一些初始化或准备工作,例如配置一些环境变量或启动一个后台服务。PostStart容器的输出将被记录在Pod的日志中。

Init Container用于在启动其他容器之前,执行一些必要的任务。例如,加载一些配置文件或检查一些网络连接。Init Container是按顺序启动的,并且只有在所有的Init Container都成功完成之后,才会启动其他容器。

PostStart容器则用于在所有其他容器启动之后,执行一些附加的任务。例如,进行一些初始化或准备工作。PostStart容器在所有其他容器启动之后启动,且所有容器启动完毕之前,Pod将一直处于容器启动中的状态。

应用实战

PostStart做准备工作,PreStop优雅关闭Nginx

使用官网案例,PostStart 命令在容器的 /usr/share 目录下写入文件 message。 命令 PreStop 负责优雅地终止 nginx 服务。

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
      preStop:
        exec:
          command: ["/bin/sh","-c","nginx -s quit; while killall -0 nginx; do sleep 1; done"]

使用 shell 连接到 Pod 里的容器:

kubectl exec -it lifecycle-demo -- /bin/bash

在 shell 中,验证 postStart 处理函数创建了 message 文件:

root@lifecycle-demo:/# cat /usr/share/message

命令行输出的是 postStart 处理函数所写入的文本:

Hello from the postStart handler

设置宽限期,优雅关闭Nginx

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        lifecycle:
          preStop:
            exec:
              command: ["/usr/sbin/nginx", "-s", "quit"]
      terminationGracePeriodSeconds: 120  # 设置优雅终止的超时时间为 120 秒(2 分钟)
posted @ 2025-03-10 14:26  VitoChen  阅读(72)  评论(0)    收藏  举报