EN

#GetReady 05 - Scale your applications using KEDA

KEDA simplifies scaling in Kubernetes, supporting custom metrics and external events for efficient resource management.

CTO

João Brito

KEDA is a scaling platform for Kubernetes that is changing how companies manage their resources within Kubernetes.

KEDA makes scaling simple and automated, allowing users to scale their applications and services efficiently and with minimal effort.

KEDA's major differentiator is its flexibility and adaptability. The platform can horizontally scale any workload, regardless of the type of application or service running. In addition, KEDA is compatible with a variety of cloud providers and monitoring tools, allowing users to customize the platform to meet the specific needs of their businesses.

If you don't want to scale your applications based solely on CPU and memory, but rather by observing other metrics or external events, this is the tool that will help you with horizontal scalability. Spinning up or down pods as your stack demands.

KEDA, Kubernetes Event-Driven Autoscaling, is an automatic pod autoscaler based on external events. We can easily scale our pods based on local CPU and memory metrics, but what about when we have an external event that precedes their usage? For example, a messaging queue, a database table, an ElasticSearch query, Kafka, Redis, Prometheus external to your cluster, and so on.

There are several technical advantages to using KEDA instead of the Horizontal Pod Autoscaler (HPA) to scale applications in Kubernetes. Here are some of them:

  • Support for custom metrics: KEDA supports custom metrics, allowing users to scale their applications and services based on specific metrics other than CPU and memory. This allows users to customize the platform to meet the specific needs of their applications.


  • Support for multiple event sources: KEDA is compatible with multiple event sources, including Kafka, RabbitMQ, and Azure Service Bus. This allows users to scale their applications based on events rather than just metrics.


  • Resource authentication: KEDA supports resource authentication, allowing users to securely authenticate access to scaling resources. This helps protect Kubernetes cluster resources from unauthorized access.


  • Fast scalability: KEDA offers fast and precise scalability. The platform uses advanced real-time scalability technologies to ensure resources are used efficiently and effectively. This allows users to scale quickly based on custom metrics and other conditions.


  • Greater resource efficiency: KEDA is highly resource-efficient, allowing users to scale their applications with the minimum resources required. This helps save money and improve the performance of the Kubernetes cluster.


  • Better integration with cloud providers: KEDA offers better integration with cloud providers, including Azure, AWS, and Google Cloud. This allows users to customize the platform to meet their specific business needs and leverage the cloud provider's resources.


  • Scale pods to ZERO units: Unlike HPA, KEDA allows turning down deploy pod units to zero and using a trigger to scale according to demand.


Let's start with KEDA's architecture:


Let's see how it actually works, for this we will install KEDA in a Kubernetes cluster and create a queue in SQS to use as a trigger

We will use a Kind cluster to test.

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 🙂

Installing KEDA:

# Add KEDA's helm repository 

helm repo add keda https://kedacore.github.io/charts

# Update your repositories

helm repo update

# Install KEDA chart

helm install keda keda/keda -n keda --create-namespace

Creating a simple application to test

kubectl create deploy web --image nginx

Create an AWS SQS queue (standard queue)

In AWS Console -> AWS SQS -> Standard Queue, copy the region and the queue URL.

Creating a KEDA object, ScaledObject and its authentication in 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 # Optional. Default: apps/v1

    kind: Deployment # Optional. Default: Deployment

    name: web     # Mandatory. Must be in the same namespace as this ScaledObject

  pollingInterval: 5 # Polling interval

  cooldownPeriod: 10 # Optional. Default 300s

  idleReplicaCount: 0 # Optional. When idle, scales to 0 pod.

  minReplicaCount: 0 # Optional. Default 0

  maxReplicaCount: 3 # Optional. Default 100

  fallback: # Optional. Fallback strategy when metrics are not available

    failureThreshold: 5 # if metrics unavailable, keeps the replica count below

    replicas: 2 # item above

  triggers:

  - type: aws-sqs-queue

    authenticationRef:

      name: keda-trigger-auth-aws-credentials  # Authentication pointing to AWS access

    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

KEDA supports for the type ScaledObjects: Deployments, StatefulSets or CustomResources such as an ArgoRollout for example.

Let's explain the ScaledObject above:

1- The ScaledObject will be created in the default namespace.
2- It will manage the replicas of the 'web' Deployment.
3 - The event source will be an AWS SQS with the queue https://sqs.us-east-2.amazonaws.com/12345678909/my-sqs-keda in the us-east-2 region.
4- The queue length that triggers the scaling is 5, meaning when it reaches 5, it increases by 1 pod, this happens for every 5 backed up messages.
5- The idleReplicaCount is 0, which reduces to 0 pods if the queue is empty.
6- Fallback enabled means if there is a failure in obtaining the queue length, 2 running replicas will be maintained.
7- The triggerAuthentication is how this ScaledObject will gain access to the SQS queue, which in turn references a secret with AWS credentials. Thinking about security this is not the best way, there is a way to use IAM Role and assign to nodes or serviceAccount in the cluster, as documented here.

Finally, the creation of the ScaledObject creates a 'child' HPA object that controls the amount of pods based on the triggers section.

Action Time!

1 - Observe your web deployment

kubectl get deployments web -n default --watch

NAME       READY   UP-TO-DATE   AVAILABLE   AGE

web        0/0     0            0           4h52m

2 - Add some messages to the queue, more than 5 to see the pods scale;

Result: KEDA will scale your 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

Once the queue becomes idle, your deploy will automatically be scaled to 0.

Conclusion

We saw how KEDA creates the HPA and acts directly on it by scaling the pods, this can be observed in the namespace events and in the hpa description:

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

We used an SQS queue on AWS as an external object, but it could be any system or application that generates some metric that can be collected, including via Prometheus installed in your cluster receiving metrics of this same type from applications internal and external to the cluster. I also did a very practical Lab here on the blog last year: https://gtup.me/kubilab-keda01 

References

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

Newsletter Getup.

Atualizações sobre Kubernetes e Software Supply Chain Security todos os meses.

Operating Kubernetes in production for more than 13 years. With Quor, this experience extends to software supply chain security as well.