KEDA é uma plataforma de escalabilidade para o Kubernetes que está mudando como as empresas gerenciam seus recursos dentro do Kubernetes.
O KEDA torna a escalabilidade simples e automatizada, permitindo que os usuários dimensionem suas aplicações e serviços de forma eficiente e com o mínimo de esforço.
O grande diferencial do KEDA é a sua flexibilidade e adaptabilidade. A plataforma consegue escalar horizontalmente qualquer workload, independentemente do tipo de aplicação ou serviço em execução. Além disso, KEDA é compatível com uma variedade de provedores de nuvem e ferramentas de monitoramento, permitindo que os usuários personalizem a plataforma para atender às necessidades específicas de seus negócios.
Se você não quer escalar suas aplicações baseando-se somente em CPU e memória, mas observando outras métricas ou eventos externos, essa é a ferramenta que vai te ajudar na escalabilidade horizontal. Subindo ou descendo pods a medida que sua stack demanda.
KEDA, Kubernetes Event-Driven Autoscaling, é um dimensionador automático de pods baseado em eventos externos. Podemos escalar facilmente nossos pods baseados em métricas locais de CPU e memória, mas e quando temos algum evento externo que precede o seu uso? Por exemplo, uma fila de mensageria, uma tabela de banco de dados, uma query de ElasticSearch, Kafka, Redis, Prometheus externos ao seu cluster, e por aí vai.
Existem várias vantagens técnicas em usar o KEDA em vez do Horizontal Pod Autoscaler (HPA) para escalar aplicativos no Kubernetes. Aqui estão algumas delas:
Vamos ver como ele funciona de fato, para isso vamos instalar o KEDA em um cluster Kubernetes e criar uma fila no SQS para usarmos de trigger
cat <<EOF | kind create cluster –config – kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 name: demo nodes: – role: control-plane image: kindest/node:v1.24.7@sha256:577c630ce8e509131eab1aea12c022190978dd2f745aac5eb1fe65c0807eb315 – role: worker image: kindest/node:v1.24.7@sha256:577c630ce8e509131eab1aea12c022190978dd2f745aac5eb1fe65c0807eb315 EOF Creating cluster “demo” … ✓ Ensuring node image (kindest/node:v1.24.7) 🖼 ✓ Preparing nodes 📦 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 ✓ Joining worker nodes 🚜 Set kubectl context to “kind-demo” You can now use your cluster with: kubectl cluster-info –context kind-demo Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂 |
# Adicione o repositório helm do KEDA
helm repo add keda https://kedacore.github.io/charts |
# Atualize seus repositórios
helm repo update |
# Instale o chart do KEDA
helm install keda keda/keda -n keda –create-namespace |
kubectl create deploy web –image nginx |
No console da AWS -> AWS SQS -> Standard Queue, copie a regiao e a URL da fila.
Criando um objeto KEDA, ScaledObject e sua autenticação na AWS
cat <<EOF | kubectl apply -f – apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: aws-sqs-queue-scaledobject namespace: default spec: scaleTargetRef: apiVersion: apps/v1 # Opcional. Default: apps/v1 kind: Deployment # Opcional. Default: Deployment name: web # Mandatório. Deve estar no mesmo namespace desse ScaledObject pollingInterval: 5 # Intervalo de polling cooldownPeriod: 10 # Opcional. Default 300s idleReplicaCount: 0 # Opcional. Quando ociosa, escala para 0 pod. minReplicaCount: 0 # Opcional. Default 0 maxReplicaCount: 3 # Opcional. Default 100 fallback: # Opcional. Estratégia de Fallback qdo métricas ñ disp. failureThreshold: 5 # se métricas indisp., mantém a qtd. de réplicas abaixo replicas: 2 # item acima triggers: – type: aws-sqs-queue authenticationRef: name: keda-trigger-auth-aws-credentials # Autenticação que aponta o acesso à AWS metadata: queueURL: https://sqs.us-east-2.amazonaws.com/12345678909/my-sqs-keda queueLength: “5” awsRegion: “us-east-2” EOF |
cat <<EOF | kubectl apply -f – apiVersion: keda.sh/v1alpha1 kind: TriggerAuthentication metadata: name: keda-trigger-auth-aws-credentials namespace: default spec: secretTargetRef: – parameter: awsAccessKeyID # Required. name: test-secrets # Required. key: AWS_ACCESS_KEY_ID # Required. – parameter: awsSecretAccessKey # Required. name: test-secrets # Required. key: AWS_SECRET_ACCESS_KEY # Required. EOF |
cat <<EOF | kubectl apply -f – apiVersion: v1 kind: Secret metadata: name: test-secrets Namespace: default data: AWS_ACCESS_KEY_ID: <encoded-user-id> # Required. AWS_SECRET_ACCESS_KEY: <encoded-key> # Required. EOF |
O KEDA suporta para o tipo ScaledObjects: Deployments, StatefulSets ou CustomResources como um ArgoRollout por exemplo.
Vamos explicar o ScaledObject acima:
1- O ScaledObject vai ser criado no namespace default.
2- Ele vai gerenciar as réplicas do Deployment ‘web’.
3 – A fonte de eventos vai ser uma AWS SQS com a fila https://sqs.us-east-2.amazonaws.com/12345678909/my-sqs-keda na região us-east-2.
4- O tamanho da fila que dispara a escalada é 5, ou seja, chegou em 5, aumenta 1 pod, isso a cada 5 mensagens represadas.
5- o idleReplicaCount é 0, isso reduz para 0 pods caso a fila esteja vazia.
6- Fallback habilitado, significa se houver falha na obtenção do tamanho da fila será mantida 2 réplicas em execução.
7- O triggerAuthentication é a maneira como esse ScaledObject obterá acesso a fila SQS, que por sua vez faz referência a uma secret com credenciais AWS. Pensando em segurança isso não é a melhor maneira, há como utilizar IAM Role e atribuir a nodes ou a serviceAccount no cluster, como documentado aqui.
Por fim, a criação do ScaledObject, cria um objeto HPA ‘filho’ que controla a quantidade de pods baseados na seção triggers.
1 – Observe seu deployment web
kubectl get deployments web -n default –watch NAME READY UP-TO-DATE AVAILABLE AGE web 0/0 0 0 4h52m |
2 – Adicione algumas mensagens na fila, mais de 5 para ver escalar os pods;
Resultado: O KEDA vai escalar seus pods
kubectl get deployments web -n default –watchNAME READY UP-TO-DATE AVAILABLE AGE Web 0/0 0 0 4h52m web 0/1 0 0 4h54m web 0/1 0 0 4h54m web 0/1 0 0 4h54m web 0/1 1 0 4h54m web 1/1 1 1 4h54m web 1/2 1 1 4h54m web 1/2 1 1 4h54m web 1/2 1 1 4h54m Web 1/2 2 1 4h54m Web 2/2 2 2 4h54m |
Depois que fica ociosa a fila, seu deploy será escalado para 0 automaticamente.
Vimos como o KEDA cria o HPA e atua nele diretamente escalando os pods, isso pode ser observado nos eventos do namespace e na descrição do hpa:
kubectl get events -n default LAST SEEN TYPE REASON OBJECT MESSAGE 23s Normal SuccessfulRescale horizontalpodautoscaler/keda-hpa-aws-sqs-queue-scaledobject New size: 2; reason: external metric s0-aws-sqs-my-sqs-keda(&LabelSelector{MatchLabels:map[string]string{scaledobject.keda.sh/name: aws-sqs-queue-scaledobject,},MatchExpressions:[]LabelSelectorRequirement{},}) above target 68s Normal Killing pod/web-68bdbdcb94-48c54 Stopping container nginx 23s Normal Scheduled pod/web-68bdbdcb94-d9hql Successfully assigned default/web-68bdbdcb94-d9hql to demo-worker3 23s Normal Pulling pod/web-68bdbdcb94-d9hql Pulling image “nginx” 22s Normal Pulled pod/web-68bdbdcb94-d9hql Successfully pulled image “nginx” in 1.196212139s 22s Normal Created pod/web-68bdbdcb94-d9hql Created container nginx 21s Normal Started pod/web-68bdbdcb94-d9hql Started container nginx 39s Normal Scheduled pod/web-68bdbdcb94-lnsjj Successfully assigned default/web-68bdbdcb94-lnsjj to demo-worker4 38s Normal Pulling pod/web-68bdbdcb94-lnsjj Pulling image “nginx” 33s Normal Pulled pod/web-68bdbdcb94-lnsjj Successfully pulled image “nginx” in 5.913160223s 33s Normal Created pod/web-68bdbdcb94-lnsjj Created container nginx 32s Normal Started pod/web-68bdbdcb94-lnsjj Started container nginx 68s Normal SuccessfulDelete replicaset/web-68bdbdcb94 Deleted pod: web-68bdbdcb94-48c54 39s Normal SuccessfulCreate replicaset/web-68bdbdcb94 Created pod: web-68bdbdcb94-lnsjj 23s Normal SuccessfulCreate replicaset/web-68bdbdcb94 Created pod: web-68bdbdcb94-d9hql 39s Normal ScalingReplicaSet deployment/web Scaled up replica set web-68bdbdcb94 to 1 68s Normal ScalingReplicaSet deployment/web Scaled down replica set web-68bdbdcb94 to 0 23s Normal ScalingReplicaSet deployment/web Scaled up replica set web-68bdbdcb94 to 2 |
kubectl describe hpa Name: keda-hpa-aws-sqs-queue-scaledobject Namespace: default Labels: app.kubernetes.io/managed-by=keda-operator app.kubernetes.io/name=keda-hpa-aws-sqs-queue-scaledobject app.kubernetes.io/part-of=aws-sqs-queue-scaledobject app.kubernetes.io/version=2.9.1 scaledobject.keda.sh/name=aws-sqs-queue-scaledobject Annotations: <none> CreationTimestamp: Tue, 03 Jan 2023 10:17:30 -0300 Reference: Deployment/web Metrics: ( current / target ) “s0-aws-sqs-my-sqs-keda” (target average value): 3 / 5 Min replicas: 1 Max replicas: 3 Deployment pods: 2 current / 2 desired Conditions: Type Status Reason Message —- —— —— ——- AbleToScale True ReadyForNewScale recommended size matches current size ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from external metric s0-aws-sqs-my-sqs-keda(&LabelSelector{MatchLabels:map[string]string{scaledobject.keda.sh/name: aws-sqs-queue-scaledobject,},MatchExpressions:[]LabelSelectorRequirement{},}) ScalingLimited False DesiredWithinRange the desired count is within the acceptable range Events: Type Reason Age From Message —- —— —- —- ——- Normal SuccessfulRescale 34s horizontal-pod-autoscaler New size: 2; reason: external metric s0-aws-sqs-my-sqs-keda(&LabelSelector{MatchLabels:map[string]string{scaledobject.keda.sh/name: aws-sqs-queue-scaledobject,},MatchExpressions:[]LabelSelectorRequirement{},}) above target |
Usamos como objeto externo uma fila SQS na AWS, mas pode ser qualquer sistema ou aplicação que gere alguma métrica que possa ser coletada, inclusive via o Prometheus instalado em seu cluster recebendo métricas desse mesmo tipo de aplicações internas e externas ao cluster. Também fiz um Lab bem prático aqui no blog ano passado: https://gtup.me/kubilab-keda01
Já assinou a nossa Newsletter?
Artigos em destaque
O Kubernetes já faz muito por você e a Getup faz o resto. Oferecemos apoio técnico e estratégico para encontrar oportunidades na sua operação.