Skip to content

Autoscaling WorkloadDeployments #271

@nuhakala

Description

@nuhakala

Hello, it would be nice to be able to autoscale WorkloadDeployments with k8s builtin HPA. I was unaware of whether it is possible, so I tried to do it, but with no success. I am not an expert on k8s autoscaling so mostly debugged my deployments with the help of LLM and search engines. Here is what I learned:

  • In order to autoscale custom resources, one must define [https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#scale-subresource](/scale subresource).
  • There was no such subresource defined in WorkloadDeployment CR, so I added it there myself like this:
scale:
  specReplicasPath: .spec.replicas
  statusReplicasPath: .status.replicas
  labelSelectorPath: .status.labelSelector
  • With this addition I was able to scale workloaddeployment with kubectl scale workloaddeployment <name> --replicas 3
  • Now I tried to deploy an HPA to do autoscaling, after adding the scale subresource, the HPA resource found the workloaddeployment, but describing the HPA resource revealed:
Metrics:                                              ( current / target )
  "http_requests_per_second" (target average value):  <unknown> / 10
Min replicas:                                         1
Max replicas:                                         100
...
Conditions:
  Type           Status  Reason             Message
  ----           ------  ------             -------
  AbleToScale    True    SucceededGetScale  the HPA controller was able to get the target's current scale
  ScalingActive  False   InvalidSelector    the HPA target's scale is missing a selector
Events:
  Type     Reason                        Age   From                       Message
  ----     ------                        ----  ----                       -------
  Warning  SelectorRequired              4s    horizontal-pod-autoscaler  selector is required
  Warning  FailedComputeMetricsReplicas  4s    horizontal-pod-autoscaler  selector is required
  • Next I tried to scale it with KEDA, but it uses HPA under the hood and the HPA resource created by KEDA had exactly same event complaining that selector is required.
  • Then I found this https://github.com/kedacore/keda/issues/5898 stating that the /scale needs to be implemented correctly for it to work, so I concluded that autoscaling is not possible right now.

I was running my test on k0s cluster using nginx ingress controller and prometheus to create http_requests_per_second metric, so the used metric was external. I have tested it with regular container deployments, and it was working fine with them. Testing was done on ubuntu 24.04 lts (x86_64) and versions used in the test are:

export CONTAINERD_VERSION_STRING=2.2.0-2~ubuntu.24.04~noble
export K0S_VERSION=v1.32.11+k0s.0
export KEDA_VERSION=2.18.3
export WC_VERSION=v2.0.0-rc.6 # wasmcloud

Because there is no images for wasmcloud rc.6, I cloned the repo and built the images myself.

Finally, here is the manifest I used to deploy the workload and HPA:

apiVersion: runtime.wasmcloud.dev/v1alpha1
kind: WorkloadDeployment
metadata:
  name: wash-go-server
spec:
  replicas: 1
  template:
    spec:
      hostSelector:
        hostgroup: default
      components:
        - name: go-server
          image: 10.164.178.1:5000/wash-go-server:0.1.0
      hostInterfaces:
        - namespace: wasi
          package: http
          interfaces:
            - incoming-handler
          config:
            host: nuhakala.com
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: go-ingress
  annotations:
    "nginx.org/proxy-pass-headers": "Host"
spec:
  ingressClassName: nginx
  rules:
  - host: nuhakala.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: runtime-gateway
            port:
              number: 80
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: go-deploy-hpa-workload
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: runtime.wasmcloud.dev/v1alpha1
    kind: WorkloadDeployment
    name: wash-go-server
  minReplicas: 1
  maxReplicas: 100
  metrics:
  - type: External
    external:
      metric:
        name: http_requests_per_second
      target:
        type: Value
        averageValue: 10
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 60

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions