pod PreStop 钩子挂在 Terminating 状态,只有在 terminationGracePeriodSeconds 后才会被杀死
The pod PreStop hook is hanging in Terminating status and is killed only after terminationGracePeriodSeconds
我在 statefulset pod 资源中定义了一个 preStop 挂钩,它 运行 是一个 bash 脚本,以确保在应用程序中只有几个进程 finishes/cancels/errors 之前不会终止 pod。我没有定义 terminationGracePeriodSeconds。现在,当我删除 pod 时,我测试了作为 preStop 挂钩一部分的脚本如预期的那样 运行 。但是在添加 terminationGracePeriodSeconds 10 分钟后,首先 bash 脚本是 运行 作为 preStop 挂钩的一部分成功持续了几分钟,它应该会杀死 pod。但 pod 挂在 TERMINATING 状态,仅在 10 分钟后被杀死。
- 为什么 pod 挂了?无法为此找到答案。
- 当未添加 terminationGracePeriodSeconds 时,流程按预期工作,方法是在完成脚本后或在 30 秒(即 terminationGracePeriodSeconds)内终止 pod。但是当我添加 10 分钟或更长时间的宽限期时,它会等到那个时间然后杀死 pod。
如何解决这个问题。有没有办法将 SIGTERM 或 SIGKILL 发送到 pod。有任何想法吗?提前致谢!
STATEFULSET.YAML
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: appx
name: appx
spec:
serviceName: appx
replicas: 1
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
app: appx
template:
metadata:
labels:
app: appx
spec:
#removed some of the sensitive info
terminationGracePeriodSeconds: 600
containers:
- image: appx
imagePullPolicy: IfNotPresent
name: appx
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 30 && bash /var/tmp/runscript.sh; sleep10"]
KUBECTL 描述 POD
**kubectl describe pod appx**
Name: appx
Namespace: default
Priority: 0
Node: docker-desktop/192.168.65.3
Start Time: Mon, 21 Sep 2020 07:30:55 -0500
Labels: app=appx
Annotations: <none>
Status: Running
IP: x.x.x.x
Controlled By: StatefulSet/appx
Containers:
appx:
Container ID: docker://dfdgfgfgfgfgfgfg
Image: appx
Image ID: docker://sha256:49dfgfgfgfgfgfgfgfgfg96a6fc
Port: <none>
Host Port: <none>
State: Running
Started: Mon, 21 Sep 2020 07:30:56 -0500
Ready: True
Restart Count: 0
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
data:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
appx-token-xj6q9:
Type: Secret (a volume populated by a Secret)
SecretName: appx-token-fhfdlf
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m43s default-scheduler Successfully assigned default/appx to docker-desktop
Normal Pulled 2m42s kubelet, docker-desktop Container image "appx" already present on machine
Normal Created 2m42s kubelet, docker-desktop Created container appx
Normal Started 2m42s kubelet, docker-desktop Started container appx
preStop
hook 和 terminationGracePeriodSeconds
是异步的。这意味着一旦 kubelet 看到 Pod 已被标记为终止,kubelet 就会开始本地 Pod 关闭过程。这意味着如果容器没有在宽限期内终止,则无论 preStop 挂钩中的命令是否完成,都会发送一个 SIGKILL 信号并终止容器。
- When the terminationGracePeriodSeconds was not added, the flow was working as expected by killing the pod as soon as finishing the script
or within 30 sec which is the terminationGracePeriodSeconds. But when
I added the grace period of 10 min or more, it is waiting until that
time and then killing the pod.
terminationGracePeriodSeconds
始终添加宽限期。正如我在评论中提到的那样,它只是默认为 30 秒。那么,如果 terminationGracePeriodSeconds
小于完成 preStop 钩子的时间怎么办?
那么容器会在terminationGracePeriodSeconds
结束时终止,preStop hook不会finish/run.
当 terminationGracePeriodSeconds 设置为 600 秒时,preStop 挂钩脚本挂起(目前尚不清楚它是否曾经工作过,因为由于抢先终止而未使用默认的 30 秒 terminationGracePeriodSeconds 进行正确测试)。这意味着一些进程没有正确处理 SIGTERM,目前在 preStop 挂钩中没有更正,这意味着容器正在等待 SIGKILL 在 10 分钟的 terminationGracePeriod 结束后发送。
如果你看一下 here 你会发现即使用户指定了 preStop 挂钩,他们也需要 SIGTERM nginx 才能正常关闭。
在您将 terminationGracePeriodSeconds
设置为 10 分钟的情况下,即使您的 preStop 挂钩成功执行,Kubernetes 也会在终止您的容器之前等待 10 分钟,因为这正是您告诉他要做的。终止信号由 kubelet 发送,但没有传递给容器内的应用程序。最常见的原因是,当您的容器运行一个运行应用程序进程的 shell 时,信号可能是由 shell 本身 consumed/interrupted 而不是传递给子进程。此外,由于不清楚您的 runscript.sh
在做什么,因此很难就哪些进程无法处理 SIGTERM 提出任何其他建议。
在这种情况下你能做什么?提前结束的选项是:
- 减少终止GracePeriodSeconds
- 通过确保正确处理 SIGTERM 并且所有 运行 进程都在侦听终止来发送正常关闭的信号。如何做到这一点的例子是 here。你可以看到他们对 NGINX 使用了“退出”命令。
我在 statefulset pod 资源中定义了一个 preStop 挂钩,它 运行 是一个 bash 脚本,以确保在应用程序中只有几个进程 finishes/cancels/errors 之前不会终止 pod。我没有定义 terminationGracePeriodSeconds。现在,当我删除 pod 时,我测试了作为 preStop 挂钩一部分的脚本如预期的那样 运行 。但是在添加 terminationGracePeriodSeconds 10 分钟后,首先 bash 脚本是 运行 作为 preStop 挂钩的一部分成功持续了几分钟,它应该会杀死 pod。但 pod 挂在 TERMINATING 状态,仅在 10 分钟后被杀死。
- 为什么 pod 挂了?无法为此找到答案。
- 当未添加 terminationGracePeriodSeconds 时,流程按预期工作,方法是在完成脚本后或在 30 秒(即 terminationGracePeriodSeconds)内终止 pod。但是当我添加 10 分钟或更长时间的宽限期时,它会等到那个时间然后杀死 pod。
如何解决这个问题。有没有办法将 SIGTERM 或 SIGKILL 发送到 pod。有任何想法吗?提前致谢!
STATEFULSET.YAML
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: appx
name: appx
spec:
serviceName: appx
replicas: 1
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
app: appx
template:
metadata:
labels:
app: appx
spec:
#removed some of the sensitive info
terminationGracePeriodSeconds: 600
containers:
- image: appx
imagePullPolicy: IfNotPresent
name: appx
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 30 && bash /var/tmp/runscript.sh; sleep10"]
KUBECTL 描述 POD
**kubectl describe pod appx**
Name: appx
Namespace: default
Priority: 0
Node: docker-desktop/192.168.65.3
Start Time: Mon, 21 Sep 2020 07:30:55 -0500
Labels: app=appx
Annotations: <none>
Status: Running
IP: x.x.x.x
Controlled By: StatefulSet/appx
Containers:
appx:
Container ID: docker://dfdgfgfgfgfgfgfg
Image: appx
Image ID: docker://sha256:49dfgfgfgfgfgfgfgfgfg96a6fc
Port: <none>
Host Port: <none>
State: Running
Started: Mon, 21 Sep 2020 07:30:56 -0500
Ready: True
Restart Count: 0
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
data:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
appx-token-xj6q9:
Type: Secret (a volume populated by a Secret)
SecretName: appx-token-fhfdlf
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m43s default-scheduler Successfully assigned default/appx to docker-desktop
Normal Pulled 2m42s kubelet, docker-desktop Container image "appx" already present on machine
Normal Created 2m42s kubelet, docker-desktop Created container appx
Normal Started 2m42s kubelet, docker-desktop Started container appx
preStop
hook 和 terminationGracePeriodSeconds
是异步的。这意味着一旦 kubelet 看到 Pod 已被标记为终止,kubelet 就会开始本地 Pod 关闭过程。这意味着如果容器没有在宽限期内终止,则无论 preStop 挂钩中的命令是否完成,都会发送一个 SIGKILL 信号并终止容器。
- When the terminationGracePeriodSeconds was not added, the flow was working as expected by killing the pod as soon as finishing the script or within 30 sec which is the terminationGracePeriodSeconds. But when I added the grace period of 10 min or more, it is waiting until that time and then killing the pod.
terminationGracePeriodSeconds
始终添加宽限期。正如我在评论中提到的那样,它只是默认为 30 秒。那么,如果 terminationGracePeriodSeconds
小于完成 preStop 钩子的时间怎么办?
那么容器会在terminationGracePeriodSeconds
结束时终止,preStop hook不会finish/run.
当 terminationGracePeriodSeconds 设置为 600 秒时,preStop 挂钩脚本挂起(目前尚不清楚它是否曾经工作过,因为由于抢先终止而未使用默认的 30 秒 terminationGracePeriodSeconds 进行正确测试)。这意味着一些进程没有正确处理 SIGTERM,目前在 preStop 挂钩中没有更正,这意味着容器正在等待 SIGKILL 在 10 分钟的 terminationGracePeriod 结束后发送。
如果你看一下 here 你会发现即使用户指定了 preStop 挂钩,他们也需要 SIGTERM nginx 才能正常关闭。
在您将 terminationGracePeriodSeconds
设置为 10 分钟的情况下,即使您的 preStop 挂钩成功执行,Kubernetes 也会在终止您的容器之前等待 10 分钟,因为这正是您告诉他要做的。终止信号由 kubelet 发送,但没有传递给容器内的应用程序。最常见的原因是,当您的容器运行一个运行应用程序进程的 shell 时,信号可能是由 shell 本身 consumed/interrupted 而不是传递给子进程。此外,由于不清楚您的 runscript.sh
在做什么,因此很难就哪些进程无法处理 SIGTERM 提出任何其他建议。
在这种情况下你能做什么?提前结束的选项是:
- 减少终止GracePeriodSeconds
- 通过确保正确处理 SIGTERM 并且所有 运行 进程都在侦听终止来发送正常关闭的信号。如何做到这一点的例子是 here。你可以看到他们对 NGINX 使用了“退出”命令。