How do I cool pods with KEDA / How to write a new scaler

Melisa Tanrıverdi
5 min readMar 27, 2021

Overview

This Keda scaler compares the temperature value which is we will get using the metaweather API[1] with the threshold value which is we will determine in our YAML file. According to this increases the number of pods if the temperature value is greater than the threshold value and reduces the number of pods in the opposite case. We will follow Keda’s documentation[2] step by step as we create a new scaler. This scaler was written in version 2.2.0.

The requirements

  • I will progress by locally in this article, you can install Minikube here[3].

After deploying KEDA you can use the following command to ensure that everything has deployed. You should be able to see KEDA Operator and the KEDA Metrics API in this point.

kubectl get pods -n keda

Let’s get started

  • First create a new directory, download the KEDA’s code and YAML file from here[4]. Make sure the code and the YAML file should be in the same directory.
  • We should create the new scaler struct under the pkg/scalers directory. So create a file for your scaler under the pkg/scalers.
  1. We should define the main pieces of data that we expect the user to supply so the scaler runs properly. For example this scaler needs to connect to an external source based on a connection string, we expect the user to supply this connection string in the configuration (YAML file) within the ScaledObject under trigger. This data will be passed to your constructing function as map[string]string.
  2. Then I started to writing the function that the scaler should basically do. It is a simple function that pull the temperature from the API and returns that value.

3. Functions

  • ParseMetadata: This function parses the user-defined metadata variables from the YAML file.
  • NewScaler: This function creates http client. Then, parses the metadata with parseMetadata function and assign these values to metadata struct variables.

We should implement the methods defined in the scaler interface section now. The scalers in KEDA are implementations of a KEDA Scaler Go interface declared in pkg/scalers/scaler.go.

  • IsActive: For some reason, the scaler might need to declare itself as in-active, and the way it can do this is through implementing the function IsActive.

KEDA polls ScaledObject object according to the pollingInterval configured in the ScaledObject; it checks the last time it was polled, it checks if the number of replicas is greater than 0, and if the scaler itself is active. So if the scaler returns false for IsActive, and if current number of replicas is greater than 0, and there is no configured minimum pods, then KEDA scales down to 0.

Depending on the output of this function pods scaled up or down according to minReplicaCount and maxReplicaCount that user specified in YAML file. In our case scaler returns true if temperature > threshold.

  • Close: After each poll on the scaler to retrieve the metrics, KEDA calls this function for each scaler to give the scaler the opportunity to close any resources, like http clients for example.
  • GetMetrics: This is the key function of a scaler; it returns a value that represents a current state of an external metric (e.g. length of a queue). The return type is an ExternalMetricValue struct. Kubernetes HPA (Horizontal Pod Autoscaler) will poll GetMetrics regularly through KEDA's metric server (as long as there is at least one pod), and compare the returned value to a configured value in the ScaledObject configuration.

In our scaler temperature is the value that represents a current state of an external metric.

  • GetMetricSpecForScaling: KEDA works in conjunction with Kubernetes Horizontal Pod Autoscaler (HPA). When KEDA notices a new ScaledObject, it creates an HPA object that has basic information about the metric it needs to poll and scale the pods accordingly. To create this HPA object, KEDA invokes GetMetricSpecForScaling.

TargetValue is the value of the metric we want to reach at all times at all costs. As long as the current metric doesn't match TargetValue, HPA will increase the number of the pods until it reaches the maximum number of pods allowed to scale to.

In our case our target value is threshold.

4. Now we need to change the buildScaler function inpkg/scaling/scale_handler.goby adding another switch case that matches our scaler. Scalers in the switch are ordered alphabetically, you should follow the same pattern.

When we apply to the YAML file the trigger type which is we specified as weather matches that switch case and it invokes the NewWeatherScaler. Thus our scaler is initialized.

It’s time for the YAML file

If you have a difficult to understand the terms you can check my previous article[5] which I tried to explain the fields of a YAML file. As I mentioned there ScaledObject maps an event source to the deployment that you want to scale. The scaled object controller also creates the HPA for you.

This is a code snippet of the one I use in my scaler. Let’s start examine.

The spec part means KEDA will check the trigger source on ScaledObject every 3 seconds (pollingInterval) and according to that it scales pods between 1 (minReplicaCount) and 4 (maxReplicaCount). It will wait 5 seconds after the last trigger activated before scaling back down to minReplicaCount (coolDownPeriod).

spec.scaleTargetRef.name is the reference to the name of the Deployment that you want to scale. The ScaledObject and the deployment referenced in name need to be in the same namespace.

scaleTargetRef:

name: my-deploy to be in the same namespace.

Trigger is the list of triggers to use to activate the scaling. We determined weather as trigger type related our scaler.

Metadata is the part that we supply from user and parse using the parseMetadata function.

It’s Time to Deploy

  • First, you should run minikube start.
  • Run make build from the root of KEDA.
  • Run make deploy in the same directory.

You can debug your code using the following command:

kubectl logs -f your-keda-operator -n keda

Check kubectl get pod -n kedato learn name of your KEDA operator.

  • Run IMAGE_REGISTRY=docker.io IMAGE_REPO=melisa make publishfrom the root of the source code, where melisa is your Docker Hub repo, this will create and publish images with your build of KEDA into your repo. You can refer the guide for local deployment[6] for more details.
  • Run IMAGE_REGISTRY=docker.io IMAGE_REPO=melisa make deploy,this will deploy KEDA to your cluster.

Let’s see some action !

  • Deploy the YAML file

kubectl apply -f pkg/scalers/weather_scaler.yaml

You should see the my-deploy soon after.

kubectl get pods

As you see the_temp value is 11.50 now and we specified threshold value as 1 in YAML file. Scaler is active and there are 4 pods up because of the temperature value greater than threshold value.

  • Let’s check ScaledObject:
  • You can see that HPA is also created:

You can find the complete code in the following Github repository[7].

Thanks for reading, I hope you found this article useful.

--

--