我在 k8s 中有一个多容器 pod,我们称它们为 A 和 B。停止 Pod 时,A 必须在 B 之前停止,因为 A 需要 B 直到它关闭。
为此,我在 A 上注册了一个preStop
钩,以便 A 可以在 B 之前优雅地停止。
但是,我不确定这是否是一个好的解决方案,因为我错过了一些在 k8s 文档中找不到的信息:
多容器 Pod 停止时会发生什么情况?
- 所有容器
preStop
钩子都被调用,然后当它们全部覆盖时,所有容器都会收到SIGTERM
,或者 - 同时,所有容器如果有一个,则直接接收
preStop
,如果没有,则直接SIGTERM
?
在第二种情况下,preStop
对我想做的事情毫无用处,因为 B 会立即被杀死。
通常,在删除 Pod 期间,容器运行时会向每个容器中的主进程发送 TERM 信号。
根据官方文件:
如果 Pod 的一个容器定义了
preStop
钩子, 库贝莱特在容器内运行那个钩子。kubelet 触发容器运行时向每个容器内的进程 1 发送 TERM 信号。
这个数字可能会混淆 - 看起来 TERM 信号只有在钩子完成后才会发送preStop
。 我决定用下面的一个简单的例子来检查工作顺序。
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
restartPolicy: Never
volumes:
- name: config
configMap:
name: nginx-conf
containers:
- name: container-1
image: nginx
lifecycle:
preStop:
exec:
command: ["/bin/sleep","15"]
ports:
- containerPort: 80
- name: container-2
image: nginx
ports:
- containerPort: 81
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d
terminationGracePeriodSeconds: 30
容器-1preStop
钩子延迟 15 秒。 我已经连接到两个容器以查看 pod 删除期间的行为。
结果
删除容器后:
容器-1 工作了 15 秒,然后连接丢失
容器-2 立即失去连接
结论
如果容器有一个preStop
钩子,它将尝试执行它。只有这样,它才会收到 TERM 信号。在这种情况下的主要条件:宽限期尚未过期。
如果容器没有preStop
钩子,它将在命令删除 Pod 后立即收到 TERM 信号。因此,当preStop
钩子将针对另一个容器执行时,它不会等待。
注意:Pod 中的容器以不同的时间和任意顺序接收 TERM 信号。如果停机顺序 问题,请考虑使用
preStop
挂钩进行同步。