#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 :)"