Модуль Kubernetes с горизонтальным автоматическим масштабированием для безопасного слива, сельдерей рабочий масштабируется в середине работы

#kubernetes #rabbitmq #google-kubernetes-engine #autoscaling #horizontal-pod-autoscaling

# #kubernetes #rabbitmq #google-kubernetes-engine #автоматическое масштабирование #горизонтальный модуль-автоматическое масштабирование

Вопрос:

У меня есть кластер Kubernetes на GKE. Среди прочего, в моем текущем макете есть модуль (worker-pod), сконфигурированный с помощью автоскалера горизонтального модуля, который масштабируется по внешней метрике, предоставляемой в Stackdriver с помощью BindPlane от BlueMedora.

Автоматическое масштабирование работает отлично, но иногда, когда приходит время уменьшать масштаб, модули опорожняются во время выполнения задачи, которая никогда не завершается.

Модуль запускает рабочий модуль сельдерея, в то время как очередями заданий управляет другой модуль с RabbitMQ, я не уверен, стоит ли это исправлять на стороне K8s или RabbitMQ.

Как я могу избежать того, чтобы HPA уменьшал размер модуля, пока он выполняет задачу?

Моя спецификация модуля (упрощенная):

 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
 

Ответ №1:

Чтобы исправить это, у вас есть несколько подходов, во-первых, чтобы избежать потери сообщений для обработки, вам нужно использовать ручные подтверждения RabbitMQ, которые вам нужно подтвердить после успешного выполнения работы, если это не удастся, задача будет отправлена в очередь, а затем обработана повторно.

Во-вторых, по сути, когда запускается автоматическое масштабирование (уменьшение масштаба), ему будет отправлен сигнал SIGTERM и ждать, пока переменная (в podSpec):

terminationGracePeriodSeconds: 90

Таким образом, вы можете поработать с этой переменной и установить ее немного выше, чтобы она могла корректно завершать работу после выполнения задачи.

По истечении времени terminationGracePeriodSeconds модуль получит сигнал SIGKILL, который уничтожит модуль.

Кроме того, вы можете обрабатывать эти сигналы с помощью 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 :)"