Kedify OTel Scaler Migration
This guide will help you with setting up Prometheus Scaler that will be autoscaling the target deployment based on application-specific metrics. In the second part of the guide, we will migrate the Prometheus Scaler to lightweight OpenTelemetry (OTel) Scaler.
1. Prepare Helm Charts and Cluster
Section titled “1. Prepare Helm Charts and Cluster”# Add the repos and update themhelm repo add kedacore https://kedacore.github.io/chartshelm repo add prometheus-community https://prometheus-community.github.io/helm-chartshelm repo update kedacore prometheus-community# Create k3d clusterk3d cluster create --port "8080:30080@loadbalancer" --k3s-arg "--disable=traefik@server:*"2. Install KEDA and Prometheus Stack
Section titled “2. Install KEDA and Prometheus Stack”Install KEDA
helm upgrade -i keda kedacore/keda --namespace keda --create-namespaceInstall Prometheus Stack
helm upgrade -i kube-prometheus-stack prometheus-community/kube-prometheus-stack --namespace monitoring --create-namespace3. Deploy Application that Exposes Prometheus Metrics
Section titled “3. Deploy Application that Exposes Prometheus Metrics”Deploy the work-simulator application, which exposes Prometheus metrics for business logic.
kubectl apply -f https://raw.githubusercontent.com/kedify/examples/refs/heads/main/samples/work-simulator/config/manifests.yamlkubectl expose svc work-simulator --name work-simulator-np --type NodePort --overrides '{ "apiVersion": "v1","spec":{"ports": [{"port":8080,"protocol":"TCP","targetPort":8080,"nodePort":30080}]}}'This will deploy the application and expose it on node port 30080 (which should be mapped to host’s port 8080 by k3d).
Deploy the ServiceMonitor to configure Prometheus scraping:
kubectl apply -f https://raw.githubusercontent.com/kedify/examples/refs/heads/main/samples/work-simulator/config/servicemonitor.yamlYou can verify the metrics are correctly scraped by locating the new target in Prometheus UI. First we will port forward the proper service and then access it on http://localhost:9090.
kubectl port-forward service/kube-prometheus-stack-prometheus -n monitoring 9090:90904. Deploy ScaledObject for Autoscaling
Section titled “4. Deploy ScaledObject for Autoscaling”Create a ScaledObject to define the scaling behavior.
kubectl apply -f https://raw.githubusercontent.com/kedify/examples/refs/heads/main/samples/work-simulator/config/so.yamlVerify the ScaledObject:
kubectl get scaledobject work-simulator-scaledobjectYou should see an output where READY is True.
5. Generate Load
Section titled “5. Generate Load”Use hey to generate load:
hey -z 2m -c 50 http://localhost:8080/work-z 2m: Number of minutes that we will send requests.-c 50: Number of concurrent workers.
Or use a simple curl:
curl -s http://localhost:8080/workMonitor the scaling behavior:
watch kubectl get deployment work-simulatorYou should see the number of replicas increase as load is applied. Once the load is processed, the replicas will scale back down to 1.
6. Migrate from Prometheus to OTel Collector & OTel Scaler
Section titled “6. Migrate from Prometheus to OTel Collector & OTel Scaler”Uninstall the Prometheus
Section titled “Uninstall the Prometheus”We want the OTel collector to be scraping the metrics from our work-simulator app and sending them to KEDA OTel Scaler.
In this setup we don’t need the Prometheus stack anymore. However, OTel Operator can work with CRDs from Prometheus Operator (PodMonitor & ServiceMonitor) so
let’s leave the Helm Charts installed and let’s only scale the deployments to 0.
for kind in deploy statefulset; do for name in $(kubectl get ${kind} -nmonitoring --no-headers -o custom-columns=":metadata.name"); do kubectl scale ${kind} ${name} -nmonitoring --replicas=0 donedonekubectl -nmonitoring patch daemonset kube-prometheus-stack-prometheus-node-exporter -p '{"spec": {"template": {"spec": {"nodeSelector": {"non-existing": "true"}}}}}'7. Install KEDA OTel Scaler, OTel Operator & OTel Collector
Section titled “7. Install KEDA OTel Scaler, OTel Operator & OTel Collector”cat <<VALUES | helm upgrade -i otel-scaler oci://ghcr.io/kedify/charts/otel-add-on --version=v0.0.11 -f -otelOperator: enabled: trueotelOperatorCrs:- enabled: true targetAllocatorEnabled: true # not necessary, but let's ignore {Pod,Service}Monitors from other namespaces targetAllocator: prometheusCR: allowNamespaces: [default]VALUES8. Migrate the ScaledObject
Section titled “8. Migrate the ScaledObject”When using the Prometheus scaler as a trigger for the ScaledObject (SO), it has slightly different fields under the metadata section. To migrate from it to another scaler, apply this SO, this will also unpause it, because the annotation that pauses the ScaledObject is not present:
apiVersion: keda.sh/v1alpha1kind: ScaledObjectmetadata: name: work-simulator-scaledobjectspec: scaleTargetRef: kind: Deployment name: work-simulator minReplicaCount: 1 maxReplicaCount: 10 advanced: restoreToOriginalReplicaCount: true horizontalPodAutoscalerConfig: behavior: scaleDown: stabilizationWindowSeconds: 5 triggers: # was type: prometheus - type: external metadata: scalerAddress: keda-otel-scaler.default.svc:4318 # was serverAddress: http://kube-prometheus-svc..cluster.local:9090 metricQuery: sum(work_simulator_inprogress_tasks{job="work-simulator"}) # <- was query: .., the PromQL query itself is the same targetValue: '5' # <- was threshold: "5"kubectl apply -f https://kedify.io/assets/yaml/how-to/otel-scaler-migration/new-so.yamlTo verify that new setup with OpenTelemetry works, generate some load as in Step 5.
hey -z 2m -c 50 http://localhost:8080/workConclusion
Section titled “Conclusion”With using the OTel Operator, we can migrate the existing monitoring infra smoothly, because TargetAllocator feature allows reusing the
Prometheus’ CRDs. Configuration of OpenTelemetry Collector also allows using the dynamic target allocation based on annotations (example).
Now, let’s check the resource savings after dropping in the OTel stuff:
kubectl top pods -n monitoringNAME CPU(cores) MEMORY(bytes)alertmanager-kube-prometheus-stack-alertmanager-0 2m 49Mikube-prometheus-stack-grafana-746fbdb8d8-p9vjp 52m 388Mikube-prometheus-stack-kube-state-metrics-779d68fc98-sqlhz 2m 23Mikube-prometheus-stack-operator-75dbf947f8-9rj8h 5m 32Mikube-prometheus-stack-prometheus-node-exporter-pzcvt 1m 20Miprometheus-kube-prometheus-stack-prometheus-0 19m 377Mikubectl top podsNAME CPU(cores) MEMORY(bytes)keda-otel-scaler-548967c87f-878fh 3m 32Mikeda-otel-scaler-collector-0 3m 55Mikeda-otel-scaler-targetallocator-ff5877d79-2rdjd 3m 35Miotel-operator-6545c6bddc-26765 3m 46Mi