Kubernetes 如果可能的话,防止杀死一些豆荚?

Kubernetes 如果可能的话,防止杀死一些豆荚?,kubernetes,autoscaling,Kubernetes,Autoscaling,我需要扩展一组运行基于队列的worker的pod。工人的工作可以持续很长时间(小时),不应该被打断。吊舱的数量取决于工作队列的长度。缩放可以使用使用自定义指标的水平自动缩放器,也可以使用更改副本数量的简单控制器 这两种解决方案的问题都是,缩小规模时,无法控制哪些pod被终止。在任何给定的时间,大多数工人都可能从事短期作业、空闲作业或(更罕见的)处理长期作业。我想避免杀害长期工作的工人,闲置或短期工作的工人可以被解雇而不会有任何问题 以低复杂性实现这一点的方法是什么?我能想到的一件事是根据POD的

我需要扩展一组运行基于队列的worker的pod。工人的工作可以持续很长时间(小时),不应该被打断。吊舱的数量取决于工作队列的长度。缩放可以使用使用自定义指标的水平自动缩放器,也可以使用更改副本数量的简单控制器

这两种解决方案的问题都是,缩小规模时,无法控制哪些pod被终止。在任何给定的时间,大多数工人都可能从事短期作业、空闲作业或(更罕见的)处理长期作业。我想避免杀害长期工作的工人,闲置或短期工作的工人可以被解雇而不会有任何问题

以低复杂性实现这一点的方法是什么?我能想到的一件事是根据POD的CPU使用情况来做这件事。不太理想,但可能已经足够好了。另一种方法是工作人员以某种方式公开优先级,指示他们是否是要删除的首选pod。然而,每当一个工人开始新的工作时,这个优先级可能会改变

最终,所有作业都将是短期运行的,这个问题将消失,但这是目前的长期目标。

在吊舱运行期间,Kubernetes向吊舱的容器发送SIGTERM信号。您可以使用该信号优雅地关闭应用程序。问题在于Kubernetes不会永远等待您的应用程序完成,而您的应用程序可能需要很长时间才能退出。
在这种情况下,我建议您使用,这是在Kubernetes向容器发送KILL信号之前完成的。有一个关于如何使用处理程序的示例:


有一种解决方法可以在一定程度上控制pod的终止。 不太确定它是否是最佳实践,但至少你可以尝试并测试它是否适合你的应用程序

  • 使用
    terminationGracePeriodSeconds:3600
    增加
    Deployment
    宽限期,其中
    3600
    是应用程序中可能最长任务的时间(以秒为单位)。这确保了POD不会在宽限期结束时终止。详细阅读有关pod终止过程的说明
  • 定义一个
    preStop
    处理程序。有关生命周期挂钩的更多详细信息,请参见。在我的例子中,我使用下面的脚本创建了一个文件,该文件稍后将用作终止pod的触发器(可能有更优雅的解决方案)。
  • 一旦满足条件,立即停止应用程序的运行。当应用程序退出时,pod也会终止。无法使用
    preStop
    shell脚本中的
    PID 1
    结束进程,因此您需要向应用程序添加一些逻辑以终止自身。在我的例子中,它是一个NodeJS应用程序,有一个调度器每30秒运行一次,检查是否满足两个条件<代码>!isNodeBusy标识是否允许它完成应用程序和
    fs.existsSync('/home/node/app/preStop')
    是否触发了
    preStop
    钩子。对于你的应用程序来说,这可能是不同的逻辑,但你得到了基本的想法。
    schedule.scheduleJob('*/30 * * * * *', () => {
      if(!isNodeBusy && fs.existsSync('/home/node/app/preStop')){
        process.exit();
      }
    });
    

  • 请记住,此解决方法仅适用于
    自愿中断
    ,对于
    非自愿中断
    显然没有帮助。更多信息,请参见。

    由于长时间运行的作业无法从保存状态恢复,因此此操作不适用于设想的解决方案;它们必须重新开始,您不必在preStop命令中保存状态,实际上您可以在容器内的自定义脚本中执行任何操作。示例:
    命令:[“/bin/sh”,“/myscript.sh;]
    。您可以在此脚本中检查工作人员是空闲还是忙。如果忙,请等待一段时间,然后再次检查工作人员的状态。达到空闲状态后,脚本将完成,Kubernetes将杀死pod。如果我没有正确理解您的意思,请纠正我。我发现此应用程序存在两个问题roach:k8s文档说:“用户应该让他们的钩子处理器尽可能轻。但是,在某些情况下,长时间运行的命令是有意义的,例如在停止容器之前保存状态。”-这可能会阻塞很长时间(小时)。其次,它也会在给定的宽限期后放弃。虽然这个数字可能会设置得很高,但这似乎再次是一个不好的做法。您是否有使用此策略的经验,并且它是否有效?请参阅可能的相关问题:
    lifecycle:
      preStop:
        exec:
          command: ["/bin/sh", "-c", "touch /home/node/app/preStop"]
    
    
    schedule.scheduleJob('*/30 * * * * *', () => {
      if(!isNodeBusy && fs.existsSync('/home/node/app/preStop')){
        process.exit();
      }
    });