我需要缩放一组运行基于队列的工作进程的pod。工作进程的作业可以运行很长时间(数小时),并且不应中断。pod的数量基于工作进程队列的长度。缩放可以使用使用自定义指标的水平自动缩放器,也可以使用更改副本数量的简单控制器。
这两种解决方案的问题是,在缩小规模时,无法控制终止的pod。在任何给定时间,大多数工作进程可能都在处理短时间运行的作业、空闲作业或(更罕见的情况下)处理长时间运行的作业。我希望避免删除长时间运行的作业工作进程,空闲或短时间运行的作业工作进程可以毫无问题地终止。
有什么方法可以以低复杂性完成此操作?我能想到的一件事是基于pod的CPU使用率来完成此操作。虽然不理想,但这可能已经足够好了。另一种方法可以是,工作进程以某种方式公开一个优先级,指示它们是否是要删除的首选pod。不过,每次工作进程选择一个新作业时,此优先级都可能发生变化。
最终所有的工作都将是短期的,这个问题将消失,但这是一个长期的目标,现在。
6条答案
按热度按时间llmtgqce1#
在终止pod的过程中,Kubernetes会向pod的容器发送SIGTERM信号。您可以使用该信号正常关闭应用程序。问题是Kubernetes不会一直等待应用程序完成,在您的情况下,应用程序可能需要很长时间才能退出。
在这种情况下,我建议你使用preStop钩子,它在Kubernetes向容器发送KILL信号之前完成。
ddarikpa2#
有一种变通方法可以对pod的终止给予一些控制。不太确定这是否是最好的做法,但至少你可以尝试一下,测试它是否适合你的应用程序。
1.将
Deployment
宽限期增加terminationGracePeriodSeconds: 3600
,其中3600
是应用程序中可能的最长任务的时间(以秒为单位)。这可确保pod不会在宽限期结束时终止。请详细阅读有关pod终止过程的文档。1.定义一个
preStop
处理程序。关于生命周期钩子的更多细节可以在docs和示例中找到。在我的例子中,我使用下面的脚本创建了一个文件,该文件稍后将用作终止pod的触发器(可能有更好的解决方案)。1.一旦满足条件,立即停止应用运行。当应用退出时,pod也会终止。无法从
preStop
shell脚本使用PID 1
结束进程,因此您需要向应用添加一些逻辑来终止自身。在我的示例中,它是一个NodeJS应用,存在每30秒运行一次的调度程序,并检查是否满足两个条件。!isNodeBusy
标识是否允许结束应用程序,以及fs.existsSync('/home/node/app/preStop')
标识是否触发了preStop
挂钩。对于您的应用程序来说,逻辑可能会有所不同,但您已经了解了基本概念。请记住,此变通方法仅适用于
voluntary disruptions
,显然对involuntary disruptions
没有帮助。更多信息请参见docs。5kgi1eie3#
我认为,使用
Deployment
或类似工具运行此类工作负载,并使用HorizontalPodAutoscaler
进行扩展是错误的做法。1.定义一个控制器(可能是
Deployment
),其任务是定期创建KubernetesJob
对象。Job
的规范中应该包含一个.spec.parallelism
值,该值等于您可以接受的最大并发执行数。1.然后,由
Job
派生的Pods
运行您的处理逻辑,它们应该各自从队列中提取一条消息,处理它,然后从队列中删除它(如果成功)。Job
必须以正确的状态(成功或失败)退出,这确保了Job
能够识别处理何时完成,因此不会启动额外的Pods
。使用这种方法,
.spec.parallelism
根据要完成的工作量控制自动缩放,而缩小是使用Job
的一个自动优势。oalqel3c4#
从1.22版本开始,有一个测试版功能可以帮助你做到这一点。你可以添加注解
controller.kubernetes.io/pod-deletion-cost
,其值在[-2147483647, 2147483647]
范围内,这将导致具有较低值的pod首先被杀死。默认值为0,因此一个pod上的任何负值都将导致一个pod在缩减过程中被杀死,例如:kubectl annotate pods my-pod-12345678-abcde controller.kubernetes.io/pod-deletion-cost=-1000
链接到有关此功能实现的讨论:Scale down a deployment by removing specific pods (PodDeletionCost) #2255
文档链接:复制副本集/ Pod删除成本
x6h2sr285#
您正在寻找Pod Priority and Preemption。通过为您的pod配置高优先级
PriorityClass
,您可以确保它们不会被删除,从而为其他优先级较低的pod腾出空间。1.建立新的
PriorityClass
1.在pod中设置新的
PriorityClass
PriorityClass
中的value: 1000000
配置机架的调度优先级,值越高表示机架越重要。lo8azlld6#
对于那些在节点缩小时面临Pod被杀死问题的人来说-
这是Cluster Autoscaler的预期功能,因为CA将尝试优化单元,以便可以使用最小的群集大小。但是,您可以通过为作业单元创建具有
maxUnavailable=0
的PodDisruptionBudget来保护作业单元不被逐出(被终止)。