我需要扩展一组运行基于队列的工作程序的容器。工人的工作可以长时间(数小时)运行,并且不会被打断。窗格的数量基于工作队列的长度。缩放可以是使用具有自定义指标的水平自动缩放器,也可以是更改副本数量的简单控制器。
任一解决方案的问题是,按比例缩小时,无法控制终止哪个pod。在任何给定时间,大多数工人都可能从事短期工作,闲置或(长期工作)处理长期工作。我想避免杀死长期工作的工作人员,可以将闲置或短期工作的工作人员终止而不会出现问题。
如何以低复杂度做到这一点?我能想到的一件事是基于Pod的CPU使用率来执行此操作。不理想,但可能足够好。另一种方法可能是,工作人员以某种方式公开优先级,以指示他们是否是要删除的首选容器。但是,每次工人找到新工作时,此优先级可能会改变。
最终所有工作都将是短暂的,这个问题将消失,但这是目前的长期目标。
答案 0 :(得分:2)
在容器process of termination期间,Kubernetes将SIGTERM信号发送到容器的容器。您可以使用该信号来正常关闭应用程序。问题在于,Kubernetes不会永远等待您的应用程序完成,因此您的应用程序可能需要很长时间才能退出。
在这种情况下,我建议您使用preStop hook,在Kubernetes将KILL信号发送到容器之前完成。 here有一个有关如何使用处理程序的示例:
apiVersion: v1 kind: Pod metadata: name: lifecycle-demo spec: containers: - name: lifecycle-demo-container image: nginx lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] preStop: exec: command: ["/bin/sh","-c","nginx -s quit; while killall -0 nginx; do sleep 1; done"]
答案 1 :(得分:1)
有一种解决方法可以对Pod终止进行一些控制。 尚不确定它是否是最佳实践,但至少您可以尝试一下并测试它是否适合您的应用。
Deployment
增加terminationGracePeriodSeconds: 3600
宽限期,其中3600
是应用程序中最长任务的时间,以秒为单位。这样可以确保在宽限期结束前不会终止Pod。详细阅读docs有关吊舱终止过程的信息。preStop
处理程序。有关生命周期挂钩的更多详细信息,可以在docs和example中找到。就我而言,我使用下面的脚本来创建文件,该文件以后将用作终止pod的触发器(可能有更优雅的解决方案)。
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "touch /home/node/app/preStop"]
PID 1
shell脚本中的preStop
结束该过程,因此您需要向应用程序添加一些逻辑以终止自身。就我而言,这是一个NodeJS应用程序,有一个调度程序每30秒运行一次,并检查是否满足两个条件。 !isNodeBusy
标识是否允许完成应用程序,以及fs.existsSync('/home/node/app/preStop')
标识是否触发了preStop
挂钩。对于您的应用,逻辑可能不同,但是您掌握了基本思想。
schedule.scheduleJob('*/30 * * * * *', () => {
if(!isNodeBusy && fs.existsSync('/home/node/app/preStop')){
process.exit();
}
});
请记住,此解决方法仅适用于voluntary disruptions
,显然不适用于involuntary disruptions
。 docs中的更多信息。