K8S之为容器生命周期设置postStart和preStop处理函数

1 本人基础环境

2 目的

介绍什么是容器的生命周期回调并演示如何为容器的生命周期事件挂接处理函数。Kubernetes 支持 postStart 和 preStop 事件。 当一个容器启动后,Kubernetes 将立即发送 postStart 事件;在容器被终结之前, Kubernetes 将发送一个 preStop 事件。容器可以为每个事件指定一个处理程序。

3 容器生命周期回调

3.1 概述

kubelet 管理的容器如何使用容器生命周期回调框架, 藉由其管理生命周期中的事件触发,运行指定代码。

3.2 容器回调

有两个回调暴露给容器:

PostStart
这个回调在容器被创建之后立即被执行。 但是,不能保证回调会在容器入口点(ENTRYPOINT)之前执行。 没有参数传递给处理程序。

PreStop
在容器因 API 请求或者管理事件(诸如存活态探针、启动探针失败、资源抢占、资源竞争等) 而被终止之前,此回调会被调用。 如果容器已经处于已终止或者已完成状态,则对 preStop 回调的调用将失败。 在用来停止容器的 TERM 信号被发出之前,回调必须执行结束。 Pod 的终止宽限周期在 PreStop 回调被执行之前即开始计数, 所以无论回调函数的执行结果如何,容器最终都会在 Pod 的终止宽限期内被终止。 没有参数会被传递给处理程序。

3.3 回调处理程序的实现

容器可以通过实现和注册该回调的处理程序来访问该回调。 针对容器,有三种类型的回调处理程序可供实现:

  • Exec - 在容器的 cgroups 和名字空间中执行特定的命令(例如 pre-stop.sh)。 命令所消耗的资源计入容器的资源消耗。
  • HTTP - 对容器上的特定端点执行 HTTP 请求。
  • Sleep - 将容器暂停一段指定的时间。 这是由 PodLifecycleSleepAction 特性门控默认启用的 Beta 级特性。

说明:
如果你想为 Sleep 生命周期回调设置零秒的睡眠持续时间(实际上是一个 no-op), 可以启用 PodLifecycleSleepActionAllowZero 特性门控。

3.4 回调处理程序执行

当调用容器生命周期管理回调时,Kubernetes 管理系统根据回调动作执行其处理程序, httpGettcpSocketsleep 由 kubelet 进程执行,而 exec 在容器中执行。

当容器创建时,会调用 PostStart 回调程序, 这意味着容器的 ENTRYPOINT 和 PostStart 回调会同时触发。然而, 如果 PostStart 回调程序执行时间过长或挂起,它可能会阻止容器进入 running 状态。

PreStop 回调并不会与停止容器的信号处理程序异步执行;回调必须在可以发送信号之前完成执行。 如果 PreStop 回调在执行期间停滞不前,Pod 的阶段会变成 Terminating 并且一直处于该状态, 直到其 terminationGracePeriodSeconds 耗尽为止,这时 Pod 会被杀死。 这一宽限期是针对 PreStop 回调的执行时间及容器正常停止时间的总和而言的。 例如,如果 terminationGracePeriodSeconds 是 60,回调函数花了 55 秒钟完成执行, 而容器在收到信号之后花了 10 秒钟来正常结束,那么容器会在其能够正常结束之前即被杀死, 因为 terminationGracePeriodSeconds 的值小于后面两件事情所花费的总时间(55+10)。

如果 PostStartPreStop 回调失败,它会杀死容器。

用户应该使他们的回调处理程序尽可能的轻量级。 但也需要考虑长时间运行的命令也很有用的情况,比如在停止容器之前保存状态。

3.5 回调递送保证(幂等性)

回调的递送应该是至少一次,这意味着对于任何给定的事件, 例如 PostStartPreStop,回调可以被调用多次。 如何正确处理被多次调用的情况,是回调实现所要考虑的问题。

通常情况下,只会进行单次递送。 例如,如果 HTTP 回调接收器宕机,无法接收流量,则不会尝试重新发送。 然而,偶尔也会发生重复递送的可能。 例如,如果 kubelet 在发送回调的过程中重新启动,回调可能会在 kubelet 恢复后重新发送。

4 定义 postStart 和 preStop 处理函数

创建一个包含一个容器的 Pod,该容器为 postStart 和 preStop 事件提供对应的处理函数。

下面是对应 Pod 的配置文件:

# pods/lifecycle-events.yaml
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"]

在上述配置文件中,你可以看到 postStart 命令在容器的 /usr/share 目录下写入文件 message。 命令 preStop 负责优雅地终止 nginx 服务。当因为失效而导致容器终止时,这一处理方式很有用。

创建 Pod:

kubectl apply -f https://k8s.io/examples/pods/lifecycle-events.yaml

在这里插入图片描述

验证 Pod 中的容器已经运行:

kubectl get pod lifecycle-demo

在这里插入图片描述

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

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

在这里插入图片描述
在 shell 中,验证 postStart 处理函数创建了 message 文件:

在这里插入图片描述
命令行输出的是 postStart 处理函数所写入的文本:

补充:
Kubernetes 在容器创建后立即发送 postStart 事件。 然而,postStart 处理函数的调用不保证早于容器的入口点(entrypoint) 的执行。postStart 处理函数与容器的代码是异步执行的,但 Kubernetes 的容器管理逻辑会一直阻塞等待 postStart 处理函数执行完毕。 只有 postStart 处理函数执行完毕,容器的状态才会变成 RUNNING。

Kubernetes 在容器结束前立即发送 preStop 事件。除非 Pod 宽限期限超时, Kubernetes 的容器管理逻辑会一直阻塞等待 preStop 处理函数执行完毕。

说明:
Kubernetes 只有在一个 Pod 或该 Pod 中的容器结束(Terminated) 的时候才会发送 preStop 事件, 这意味着在 Pod 完成(Completed) 时 preStop 的事件处理逻辑不会被触发。

5 FailedPostStartHook事件

回调处理程序的日志不会在 Pod 事件中公开。 如果处理程序由于某种原因失败,它将播放一个事件。 对于 PostStart,这是 FailedPostStartHook 事件,对于 PreStop,这是 FailedPreStopHook 事件。

接下来是一个 FailedPreStopHook 事件的复现过程

# demo-pod-with-hooks.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod-with-hooks
spec:
  containers:
  - name: demo-container
    image: nginx:alpine
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo 'PostStart hook executed' && touch /usr/share/nginx/html/poststart.txt"]
      preStop:
        exec:
          command: ["/bin/sh", "-c", "echo 'PreStop hook executing, but will fail' && exit 1"]
    ports:
    - containerPort: 80

创建pod

kubectl apply -f demo-pod-with-hooks.yaml

删除pod

kubectl delete pod demo-pod-with-hooks

查看事件

kubectl get events

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值