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:

  • Suporte a métricas personalizadas: O KEDA oferece suporte a métricas personalizadas, permitindo que os usuários dimensionem seus aplicativos e serviços com base em métricas específicas, além de CPU e memória. Isso permite que os usuários personalizem a plataforma para atender às necessidades específicas de seus aplicativos.


  • Suporte a várias fontes de eventos: O KEDA é compatível com várias fontes de eventos, incluindo Kafka, RabbitMQ e Azure Service Bus. Isso permite que os usuários dimensionem seus aplicativos com base em eventos, em vez de apenas métricas.


  • Autenticação de recurso: O KEDA suporta autenticação de recursos, permitindo que os usuários autentiquem com segurança o acesso aos recursos de escalabilidade. Isso ajuda a proteger os recursos do cluster Kubernetes de acesso não autorizado.


  • Escalabilidade rápida: O KEDA oferece escalabilidade rápida e precisa. A plataforma utiliza tecnologias avançadas de escalabilidade em tempo real para garantir que os recursos sejam usados ​​de forma eficiente e eficaz. Isso permite que os usuários escalonem rapidamente com base em métricas personalizadas e outras condições.


  • Maior eficiência de recursos: O KEDA é altamente eficiente em termos de recursos, permitindo que os usuários dimensionem seus aplicativos com o mínimo de recursos necessários. Isso ajuda a economizar dinheiro e a melhorar o desempenho do cluster Kubernetes.


  • Melhor integração com provedores de nuvem: O KEDA oferece uma melhor integração com provedores de nuvem, incluindo Azure, AWS e Google Cloud. Isso permite que os usuários personalizem a plataforma para atender às necessidades específicas de seus negócios e aproveitem os recursos do provedor de nuvem.


  • Escalar pods para ZERO unidades: Diferente do HPA, o KEDA permite zerar as unidades de pods de um deploy e utilizar uma trigger para escalar de acordo com a demanda.


Vamos começar pela arquitetura do KEDA:


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

Vamos usar um cluster Kind para testar.

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 🙂

Instalando o KEDA:

# 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

Criando uma aplicação simples para testar

kubectl create deploy web --image nginx

Crie uma fila AWS SQS (standard queue)

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.

Hora da ação!

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.

Conclusão

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 

Referencias

https://blog.getup.io
https://keda.sh
https://kubernetes.io

Social

Fale conosco

Almeda Campinas 802, CJ 12, Jardim Paulista,

São Paulo - SP, 01404-001

Faça parte do time

Nossos conteúdos

Social

Fale conosco

Almeda Campinas 802, CJ 12, Jardim Paulista,

São Paulo - SP, 01404-001

Faça parte do time

Nossos conteúdos

Social

Fale conosco

Almeda Campinas 802, CJ 12, Jardim Paulista,

São Paulo - SP, 01404-001

Faça parte do time

Nossos conteúdos