- 简述
- 应用
钩子的概念在科技界是众所周知的。事件通常会触发钩子,它们允许开发人员对这些事件做出反应并运行一些自定义代码。让我们来看一个带有按钮和文本框的简单用户界面。开发人员可能有兴趣处理多个事件(即,每当事件发生时运行一些代码)。这些事件之一可能是onClick事件。您可以编写一个 onClick 处理程序,每当用户单击按钮时都会调用该处理程序。
另一个流行的钩子例子是webhooks。例如,您的电子商务网站可以定义 Webhook,每当发生销售时,该 Webhook 可以向您发送带有购买信息的 JSON 有效负载到您指定的 URL。您编写一个处理程序(在这种情况下,它可能是一个无服务器函数)并将您的无服务器函数设置为事件的处理程序。这允许您松散地耦合功能并处理发生在不同系统上的事件。
同样,Kubernetes 提供了所谓的容器钩子。容器钩子允许您对容器生命周期事件做出反应。您可以使用两个挂钩,即PostStart和PreStop。
Kubernetes 会PostStart在容器创建后立即执行钩子。但是,不能保证钩子在容器的 ENTRYPOINT 命令被调用之前运行(它们异步触发)。请注意,如果挂钩处理程序挂起,它将阻止容器进入运行状态。
KubernetesPreStop在容器终止之前调用钩子。要使容器停止,钩子需要完成执行。如果处理程序中的代码挂起,您的 Pod 将保持 Terifying 状态,直到它被杀死。
如果任何一个钩子处理程序失败,容器将被杀死。如果您决定使用这些钩子,请尝试使您的代码尽可能轻量级,以便您的容器可以快速启动/停止。
至于处理程序,您可以使用在容器内执行的命令(例如myscript.sh)或将 HTTP 请求发送到容器上的特定端点(例如/shutdown)。
使用钩子的最常见场景是在容器终止之前执行一些清理或保存状态 (PreStop) 或在容器启动后配置应用程序启动 (PostStart)。
我们已经讨论了 init 容器,两者之间存在差异:
-
初始化容器有自己的镜像,而生命周期钩子在父容器内执行
-
Init 容器是在 Pod 级别定义的,而生命周期钩子是在每个容器中定义的
-
Init 容器保证在应用程序容器启动之前执行,而 PreStart 钩子可能不会在调用 ENTRYPOINT 之前执行
看一个例子,看看这些生命周期处理程序是如何工作的。
apiVersion: v1
kind: Pod
metadata:
name: hooks-pod
spec:
containers:
- name: hooks-pod
image: kennethreitz/httpbin
lifecycle:
postStart:
exec:
command:
["/bin/sh", "-c", "echo Hello postStart! > /var/tmp/hello.txt"]
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"]
在这个 Pod YAML 中,我们定义了两个钩子。在 preStart 钩子中,我们正在写“Hello postStart!” 到容器中的文件 ( /var/tmp/hello.txt)。将上述 YAML 内容保存到hooks-pod.yaml并创建 Pod:
$ kubectl apply -f hooks-pod.yaml pod/hooks-pod created
Pod 运行后,我们可以检查hello.txt容器内文件的内容:
$ kubectl exec -it hooks-pod -- cat /var/tmp/hello.txt Hello postStart!
如果删除 Pod,您还会注意到 Kubernetes 删除它需要额外的 10 秒。
参考资料:
https://www.learncloudnative.com/blog/2021-05-03-container-lifecycle-hooks



