Kubernetes 吊舱预停止挂钩挂起在终止状态,仅在终止后2秒被终止
我在statefulset pod资源中定义了一个preStop钩子,它运行bash脚本,以确保在应用程序中的几个进程完成/取消/出错之前不会杀死pod。我没有定义终止时间。现在,当我删除pod时,我测试了作为preStop钩子一部分的脚本是否按预期运行。但是在添加terminationGracePeriodSeconds 10分钟后,首先bash脚本作为preStop钩子的一部分成功运行了几分钟,它应该会杀死pod。但吊舱挂在终止状态,10分钟后才被杀死Kubernetes 吊舱预停止挂钩挂起在终止状态,仅在终止后2秒被终止,kubernetes,sigterm,Kubernetes,Sigterm,我在statefulset pod资源中定义了一个preStop钩子,它运行bash脚本,以确保在应用程序中的几个进程完成/取消/出错之前不会杀死pod。我没有定义终止时间。现在,当我删除pod时,我测试了作为preStop钩子一部分的脚本是否按预期运行。但是在添加terminationGracePeriodSeconds 10分钟后,首先bash脚本作为preStop钩子的一部分成功运行了几分钟,它应该会杀死pod。但吊舱挂在终止状态,10分钟后才被杀死 为什么吊舱挂着?无法找到此问题的答案
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 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
**kubectl描述pod appx**
名称:appx
名称空间:默认值
优先级:0
节点:docker desktop/192.168.65.3
开始时间:2020年9月21日星期一07:30:55-0500
标签:app=appx
注释:
状态:正在运行
IP:x.x.x.x
控制人:StatefulSet/appx
容器:
附录X:
容器ID:docker://dfdgfgfgfgfgfgfg
图片:appx
图像ID:docker://sha256:49dfgfgfgfgfgfgfgfgfg96a6fc
端口:
主机端口:
状态:正在运行
开始时间:2020年9月21日星期一07:30:56-0500
准备好了吗
重新启动计数:0
条件:
类型状态
初始化为True
准备好了吗
集装箱准备好了吗
播客预定为真
卷数:
数据:
类型:EmptyDir(共享pod生存期的临时目录)
中等:
SizeLimit:
appx-token-xj6q9:
类型:Secret(由Secret填充的卷)
SecretName:appx令牌fhfdlf
可选:false
QoS等级:最佳努力
节点选择器:
容差:node.kubernetes.io/未就绪:不执行300秒
node.kubernetes.io/不可访问:不执行300秒
活动:
从消息中键入原因年龄
---- ------ ---- ---- -------
正常计划的2m43s默认计划程序已成功将默认/appx分配给docker desktop
正常拉动2m42s kubelet,机器上已存在docker桌面容器图像“appx”
正常创建2m42s kubelet,docker桌面创建容器appx
正常启动2m42s kubelet,docker桌面启动容器appx
preStop
hook和terminationgraceperiods
是异步的。这意味着一旦kubelet发现Pod被标记为终止,kubelet就开始本地Pod关闭过程。这意味着,如果容器未在宽限期内终止,则将发送SIGKILL信号,并将终止容器,而不管preStop钩子中的命令是否已完成
terminationGracePeriodSeconds
始终添加宽限期。它只是默认为30秒,正如我在评论中已经提到的那样。那么,如果terminationGracePeriodSeconds
小于完成预停止挂钩的时间,该怎么办
然后容器将在终止时间结束时终止,并且预停止挂钩将不会完成/运行。
当terminationGracePeriodSeconds设置为600s时,preStop钩子脚本挂起(目前尚不清楚它是否工作过,因为由于抢占式终止,它没有使用默认的30s terminationGracePeriodSeconds进行正确测试)。这意味着某些进程没有正确处理SIGTERM,这在preStop钩子中目前没有得到纠正,这意味着容器正在等待SIGKILL在10分钟终止时间结束后发送
如果您查看一下,您会发现,即使用户指定了一个预停止挂钩,他们也需要SIGTERM nginx以实现优雅的关闭
在这种情况下,尽管您已将terminationGracePeriodSeconds
设置为10分钟,但您的预停止挂钩已成功执行,Kubernetes在终止容器之前等待了10分钟,因为这正是您告诉他的。终止信号由kubelet发送,但没有传递给容器内的应用程序。最常见的原因是,当容器运行一个运行应用程序进程的shell时,该信号可能会被shell本身消耗/中断,而不是传递给子进程。此外,由于不清楚您的runscript.sh
在做什么,因此很难对哪些进程无法处理SIGTERM提出任何其他建议
在这种情况下你能做什么?提前结束的选项有:
- 减少终止时间(秒)
- 通过确保正确处理SIGTERM并确保所有正在运行的进程都在侦听终止,发送正常关闭的信号。如何做到这一点的例子如下。您可以看到,他们对NGINX使用“quit”命令