TL;DR
Consumidor de fila parado não usa CPU, então o HPA de CPU não vê o trabalho acumulado. O KEDA escala pelo sinal certo: o número de mensagens esperando. Testamos com RabbitMQ e um consumidor com mínimo de 0 réplicas e 1 réplica a cada 10 mensagens. Com 45 mensagens na fila, o KEDA ativou o Deployment e o HPA que ele cria subiu para 4 réplicas em 10 s e para 5 em 20 s (45 ÷ 10, arredondado para cima). Com a fila vazia, voltou a 0 em 26 s, dentro do cooldownPeriod de 30 s configurado. O padrão do KEDA é 300 s.
Por que a fila, e não a CPU
O HPA padrão escala pelo uso de CPU ou memória das réplicas que já existem. Para consumidores de fila, isso falha nos dois extremos: com zero réplicas não há o que medir, e um consumidor esperando I/O pode ter uma fila enorme e CPU baixa. O KEDA lê a métrica da própria fila e cria um HPA alimentado por ela, além de ligar e desligar o Deployment entre 0 e 1 réplica, que o HPA sozinho não faz.
O teste com RabbitMQ
Um RabbitMQ 4, uma fila pedidos e um Deployment processador que começa com 0 réplicas. O ScaledObject pede 1 réplica a cada 10 mensagens, no máximo 10. Publicamos 45 mensagens:
kubectl -n loja exec deploy/rabbitmq -- rabbitmqctl list_queues name messages consumers Listing queues for vhost / ...
name messages consumers
pedidos 45 0 kubectl -n loja get deploy processador -o jsonpath='{.spec.replicas}' t+10s réplicas=4
t+20s réplicas=5 kubectl -n loja get scaledobject,hpa NAME SCALETARGETNAME MIN MAX READY ACTIVE TRIGGERS
processador processador 0 10 True True rabbitmq
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
keda-hpa-processador Deployment/processador 11250m/10 (avg) 1 10 4 O alvo 11250m/10 é a média por réplica: 45 mensagens divididas por 4 réplicas dá 11,25, acima de 10, então o HPA ainda sobe mais uma. Com 5 réplicas, dá 9. Depois esvaziamos a fila:
kubectl -n loja exec deploy/rabbitmq -- rabbitmqctl purge_queue pedidos
kubectl -n loja get events --field-selector involvedObject.name=processador --sort-by=.lastTimestamp Normal KEDAScaleTargetActivated scaledobject/processador Scaled apps/v1.Deployment loja/processador from 0 to 1
Normal ScalingReplicaSet deployment/processador Scaled up replica set processador-579f95f986 from 1 to 4
Normal ScalingReplicaSet deployment/processador Scaled up replica set processador-579f95f986 from 4 to 5
Normal KEDAScaleTargetDeactivated scaledobject/processador Deactivated apps/v1.Deployment loja/processador from 5 to 0 O Deployment voltou a 0 réplicas 26 s depois de a fila esvaziar.
A configuração
apiVersion: v1
kind: Secret
metadata:
name: rabbitmq-keda
stringData:
host: http://usuario:senha@rabbitmq.loja.svc:15672/
---
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: rabbitmq
spec:
secretTargetRef:
- { parameter: host, name: rabbitmq-keda, key: host }
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: processador
spec:
scaleTargetRef:
name: processador
minReplicaCount: 0
maxReplicaCount: 10
pollingInterval: 10
cooldownPeriod: 30
triggers:
- type: rabbitmq
metadata:
protocol: http
queueName: pedidos
mode: QueueLength
value: "10"
authenticationRef:
name: rabbitmq - value: mensagens por réplica. Meça quantas uma réplica processa por minuto e escolha um valor que esvazie a fila no tempo que você aceita.
- pollingInterval e cooldownPeriod: padrão de 30 s e 300 s na documentação do KEDA. Os valores curtos do teste servem para demonstrar; em produção, cooldown curto faz o consumidor subir e descer a cada rajada.
- maxReplicaCount: limite também o que a fila aguenta do outro lado, como o banco onde o consumidor grava.
Azure Service Bus
O scaler azure-servicebus segue o mesmo desenho. A métrica é o número de mensagens ativas na fila, e o parâmetro é messageCount, com padrão de 5 (documentação do KEDA, scaler "Azure Service Bus"). Este trecho não foi testado por nós:
triggers:
- type: azure-servicebus
metadata:
queueName: pedidos
messageCount: "10"
authenticationRef:
name: servicebus Perguntas frequentes
Por que não usar o HPA de CPU para consumidores de fila?
Porque consumidor parado não usa CPU. Com 45 mensagens esperando e nenhuma réplica, não há CPU para medir, e o HPA nunca sobe. O tamanho da fila é o sinal que diz quanto trabalho existe.
O KEDA substitui o HPA?
Não; ele cria e alimenta um HPA. No nosso teste, o KEDA ativou o Deployment de 0 para 1 e o HPA que ele criou (keda-hpa-processador) subiu de 1 para 4 e depois para 5. Para voltar a zero, quem age de novo é o KEDA.
Quanto tempo leva para voltar a zero?
O cooldownPeriod, que é de 300 s por padrão (documentação do KEDA). No teste usamos 30 s e o Deployment voltou a zero 26 s depois de a fila esvaziar. Para produção, 300 s evita subir e descer a cada rajada.
E o Azure Service Bus?
O scaler azure-servicebus funciona do mesmo jeito, com messageCount (padrão 5) no lugar de value, e autenticação por connection string ou identidade do pod. Não reproduzimos com Service Bus neste guia; o trecho abaixo segue a documentação do KEDA.