0

我在 GKE 上有一个 Kubernetes 集群。其中,我当前的布局有一个配置了 Horizo​​ntal pod autoscaler 的 Pod(worker-pod),它可以根据 BlueMedora 的 BindPlane 在 Stackdriver 上提供的外部指标进行缩放。

自动缩放工作完美,但有时当需要缩减时,Pod 在执行一项永远不会完成的任务时会被耗尽。

该 pod 正在运行一个 Celery 工作者,而作业队列由另一个使用 RabbitMQ 的 Pod 管理,我不确定是在 K8s 端还是 rabbitMQ 端解决这个问题。

我怎样才能避免 HPA 在他执行任务时缩小 pod?

我的吊舱规格(简化):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-worker
  labels:
    component: worker
spec:
  selector:
    matchLabels:
      app: pod-worker
  replicas: 1
  template:
    metadata:
      labels:
        app: pod-worker
        component: worker
    spec:
      containers:
      - name: worker
        image: custom-image:latest
        imagePullPolicy: Always
        command: ['celery']
        args: ['worker','-A','celery_tasks.task','-l','info', '-Q', 'default,priority','-c','1', '-Ofair']
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 150m
            memory: 200Mi
        env:
         - name: POD_NAME
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
      restartPolicy: Always
    
---
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: pod-worker
  labels:
    component: worker
spec:
  maxReplicas: 30
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: pod-worker
  metrics:
    - external:
        metricName: external.googleapis.com|bluemedora|generic_node|rabbitmq|cluster|messages
        targetAverageValue: "40"
      type: External
4

1 回答 1

4

要解决此问题,您有多种方法,首先,为避免丢失要处理的消息,您需要使用 RabbitMQ 手动 ACK,您需要在工作成功后进行 ACK,如果失败,则任务将被重新排队,然后重新处理。

其次,本质上,当自动缩放(缩减)开始时,它将被发送一个 SIGTERM 信号并等待变量(在 podSpec 中):

terminationGracePeriodSeconds: 90

因此,您可以修改该变量并将其设置为高一点,以便在任务完成后能够正常关闭。

在terminationGracePeriodSeconds 时间过去后,Pod 会收到一个SIGKILL 信号,该信号将杀死Pod。

此外,您可以使用 python 处理这些信号,这是一个小示例:

import signal
import time
class GracefulKiller:
  kill_now = False
  def __init__(self):
    signal.signal(signal.SIGINT, self.exit_gracefully)
    signal.signal(signal.SIGTERM, self.exit_gracefully)
  def exit_gracefully(self,signum, frame):
    self.kill_now = True
if __name__ == '__main__':
  killer = GracefulKiller()
  while not killer.kill_now:
    time.sleep(1)
    print("doing something in a loop ...")
  print "End of the program. I was killed gracefully :)"
于 2020-11-24T12:00:28.580 回答