缩小规模时,防止杀死一些吊舱吗?

时间:2019-04-24 18:05:18

标签: kubernetes autoscaling

我需要扩展一组运行基于队列的工作程序的容器。工人的工作可以长时间(数小时)运行,并且不会被打断。窗格的数量基于工作队列的长度。缩放可以是使用具有自定义指标的水平自动缩放器,也可以是更改副本数量的简单控制器。

任一解决方案的问题是,按比例缩小时,无法控制终止哪个pod。在任何给定时间,大多数工人都可能从事短期工作,闲置或(长期工作)处理长期工作。我想避免杀死长期工作的工作人员,可以将闲置或短期工作的工作人员终止而不会出现问题。

如何以低复杂度做到这一点?我能想到的一件事是基于Pod的CPU使用率来执行此操作。不理想,但可能足够好。另一种方法可能是,工作人员以某种方式公开优先级,以指示他们是否是要删除的首选容器。但是,每次工人找到新工作时,此优先级可能会改变。

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

2 个答案:

答案 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终止进行一些控制。 尚不确定它是否是最佳实践,但至少您可以尝试一下并测试它是否适合您的应用。

  1. 通过Deployment增加terminationGracePeriodSeconds: 3600宽限期,其中3600是应用程序中最长任务的时间,以秒为单位。这样可以确保在宽限期结束前不会终止Pod。详细阅读docs有关吊舱终止过程的信息。
  2. 定义一个preStop处理程序。有关生命周期挂钩的更多详细信息,可以在docsexample中找到。就我而言,我使用下面的脚本来创建文件,该文件以后将用作终止pod的触发器(可能有更优雅的解决方案)。
    lifecycle:
      preStop:
        exec:
          command: ["/bin/sh", "-c", "touch /home/node/app/preStop"]
    
    
  3. 满足条件后立即停止运行您的应用。当应用退出时,广告连播也会终止。无法使用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 disruptionsdocs中的更多信息。