【发布时间】:2021-10-11 17:02:39
【问题描述】:
TL;DR - gke 1.20 抢占式节点导致 pod 僵尸进入失败/关闭
几年来,我们一直在使用 GKE,其中包含混合了稳定和抢占式节点池的集群。最近,从 gke v1.20 开始,我们开始看到被抢占的 pod 进入了一种奇怪的僵尸状态,它们被描述为:
状态:失败
原因:关机
消息:节点正在关闭,正在驱逐 pod
当这种情况开始发生时,我们确信这与我们的 Pod 未能在抢占时正确处理 SIGTERM 有关。我们决定通过将服务软件归结为一个大部分时间处于休眠状态的简单服务来消除我们的服务软件作为问题的根源:
/* eslint-disable no-console */
let exitNow = false
process.on( 'SIGINT', () => {
console.log( 'INT shutting down gracefully' )
exitNow = true
} )
process.on( 'SIGTERM', () => {
console.log( 'TERM shutting down gracefully' )
exitNow = true
} )
const sleep = ( seconds ) => {
return new Promise( ( resolve ) => {
setTimeout( resolve, seconds * 1000 )
} )
}
const Main = async ( cycles = 120, delaySec = 5 ) => {
console.log( `Starting ${cycles}, ${delaySec} second cycles` )
for ( let i = 1; i <= cycles && !exitNow; i++ ) {
console.log( `---> ${i} of ${cycles}` )
await sleep( delaySec ) // eslint-disable-line
}
console.log( '*** Cycle Complete - exiting' )
process.exit( 0 )
}
Main()
此代码使用 tini init 构建到 docker 映像中,以生成在 nodejs 下运行的 pod 进程(fermium-alpine 映像)。无论我们如何调整信号处理,似乎 Pod 都不会真正干净地关闭,即使日志表明它们确实如此。
另一个奇怪的是,根据 Kubernetes Pod 日志,我们看到 pod 终止开始,然后被取消:
2021-08-06 17:00:08.000 EDT 停止容器 preempt-pod
2021-08-06 17:02:41.000 EDT 取消删除 Pod preempt-pod
我们还尝试添加一个 15 秒的 preStop 延迟,看看这是否有任何影响,但我们尝试的一切似乎都无关紧要 - 豆荚变成了僵尸。新副本在池中可用的其他节点上启动,因此它始终保持系统上成功运行的 pod 的最小数量。
我们还在使用 sim 维护事件测试抢占周期:
gcloud 计算实例模拟维护事件节点 ID
【问题讨论】:
标签: node.js kubernetes google-kubernetes-engine