Is it possible to set the name of an external metric for a HorizontalPodAutoscaler from a configmap? GKE

7/11/2020

I am modifying a deployment which autoscales using a HorizontalPodAutoscaler (HPA). This deployment is part of a pipeline in which workers read messages from pubsub subscriptions, do some work and publish to the next topic. Right now I use a configmap to define the pipeline for the deployments (the configmap contains input subscription and output topics). The HPA autoscales based on the number of messages on the input subscription. I would like to be able to pull the subscription name for the HPA from a configmap if possible? Is there a way to do this?

example HPA:

apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: my-deployment-hpa
  namespace: default
  labels:
    name: my-deployment-hpa
spec:
  minReplicas: 1
  maxReplicas: 10
  metrics:
    - external:
        metricName: pubsub.googleapis.com|subscription|num_undelivered_messages
        metricSelector:
          matchLabels:
            resource.labels.subscription_id: "$INPUT_SUBSCRIPTION"
        targetAverageValue: "2"
      type: External
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-deployment

The value from the HPA currently $INPUT_SUBSCRIPTION could ideally come from a configmap.

-- Morris Hopkins
google-cloud-pubsub
google-kubernetes-engine
kubernetes

1 Answer

8/31/2020

Posting this answer as a community wiki for a better visibility as well as the answer was provided in the comments.

Answering the question from the post:

I would like to be able to pull the subscription name for the HPA from a configmap if possible? Is there a way to do this?

As pointed by user @Abdennour TOUMI there is no possibility to set the metric used by HPA with a ConfigMap:

Unfortunately, you cannot.. but you can using prometheus-adapter + HPA . Check this tuto: itnext.io/...


As for a manual workaround you could use a script that will extract needed metric name from the configMap and use a template to replace and apply new HPA.

With a configMap like:

apiVersion: v1
kind: ConfigMap
metadata:
  name: example
data:
  metric_name: "new_awesome_metric" # <-
  not_needed: "only for example" 

And following script:

#!/bin/bash

# variables
hpa_file_name="hpa.yaml"
configmap_name="example"
string_to_replace="PLACEHOLDER"

# extract the metric name used in a configmap
new_metric=$(kubectl get configmap $configmap_name -o json | jq '.data.metric_name')

# use the template to replace the $string_to_replace with your $new_metric and apply it
sed "s/$string_to_replace/$new_metric/g" $hpa_file_name | kubectl apply -f -

This script will need to have a hpa.yaml with the template to apply it as resource (example from question could be used with a change:

  • resource.labels.subscription_id: PLACEHOLDER

For more reference this HPA definition could be based on this guide:

Cloud.google.com: Kubernetes Engine: Tutorials: Autoscaling-metrics: PubSub

-- Dawid Kruk
Source: StackOverflow