The module lifecycle stageExperimental
The module has requirements for installation

Enabling AutoVPA for all namespaces

To enable the AutoVPA controller for all namespaces in the cluster, set settings.autovpa.enabled to true without specifying additional filters:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: adaptive-resource-management
spec:
  version: 1
  enabled: true
  settings:
    autovpa:
      enabled: true

In this mode, AutoVPA creates VPA objects for workloads in every namespace except system namespaces (see Excluded namespaces).

Enabling AutoVPA for specific namespaces using a label selector

To limit AutoVPA to namespaces matching a label selector, use the namespaceLabelSelector parameter:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: adaptive-resource-management
spec:
  version: 1
  enabled: true
  settings:
    autovpa:
      enabled: true
      namespaceLabelSelector:
        matchLabels:
          env: prod

AutoVPA will only manage namespaces that have the env: prod label.

Enabling AutoVPA for namespaces with a special label

To manage only namespaces explicitly marked with the autovpa.deckhouse.io/enabled: "true" label, use the onlySpecialLabel parameter:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: adaptive-resource-management
spec:
  version: 1
  enabled: true
  settings:
    autovpa:
      enabled: true
      onlySpecialLabel: true

Then add the label to the desired namespaces:

d8 k label namespace my-namespace autovpa.deckhouse.io/enabled=true

When onlySpecialLabel: true (or namespaceLabelSelector is set), the module builds the list of managed namespaces and passes it to the controller. After adding or removing the autovpa.deckhouse.io/enabled label, wait until ModuleConfig reaches the Ready state and the autovpa-controller Deployment is updated (check the --include-namespaces argument) before expecting VPA objects in a newly labeled namespace.

Combining a label selector with the special label

When both onlySpecialLabel and namespaceLabelSelector are set, the resulting list of managed namespaces is the union of both sets:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: adaptive-resource-management
spec:
  version: 1
  enabled: true
  settings:
    autovpa:
      enabled: true
      onlySpecialLabel: true
      namespaceLabelSelector:
        matchLabels:
          team: backend

In this example, AutoVPA will manage namespaces that either have the team: backend label or the autovpa.deckhouse.io/enabled: "true" label (or both).

Namespace selection behavior summary

onlySpecialLabel namespaceLabelSelector Managed namespaces
false not set All namespaces except kube-* and d8-* (see Excluded namespaces)
false set Only namespaces matching the selector
true not set Only namespaces with the autovpa.deckhouse.io/enabled: "true" label
true set Union: namespaces matching the selector + namespaces with the special label

How AutoVPA applies changes

AutoVPA reconciles VPA objects in a namespace when one of these events occurs:

Event source Triggers reconcile? Typical case
Pod created, updated, or deleted Yes Workload rollout, pod restart
Namespace created or updated (labels, annotations) Yes Namespace-level tuning, opt-out label
VPA created, updated, or deleted on the same workload (not managed by AutoVPA) Yes See Coexistence with other VPAs
Workload metadata changed (annotations or labels only, no pod changes) No
ModuleConfig changed Indirectly Module updates the managed namespace list and restarts the controller

Workload objects (Deployment, StatefulSet, DaemonSet, Job) are not watched directly. During reconcile, the controller discovers top-level controllers from running Pods and reads their current annotations through the API.

Practical implications:

  • Namespace annotations and labels take effect after a namespace update event.

  • Workload annotations are applied during reconcile, but reconcile is not triggered by workload metadata changes alone.

  • After changing a workload annotation, restart the workload if you need the VPA updated immediately:

    kubectl rollout restart deployment/<name> -n <namespace>
  • Workloads with no running Pods (scaled-to-zero Deployment, completed Job) are not reconciled until a Pod appears again.

Excluded namespaces

Regardless of ModuleConfig settings, AutoVPA never manages namespaces whose names start with kube- or d8-. This cannot be overridden with labels or namespaceLabelSelector.

In the “all namespaces” mode, tenant application namespaces are managed; Kubernetes and Deckhouse system namespaces are excluded automatically.

Annotations and labels for VPA tuning

By default, AutoVPA creates VPA objects in Off mode (recommendation-only). You can override VPA parameters using annotations or labels on a Namespace or on a workload (Deployment, StatefulSet, DaemonSet, or Job).

Resolution order:

  1. Annotation takes precedence over label with the same key.
  2. A workload-level setting overrides the namespace default.

Where to place annotations

Place tuning annotations on the workload object metadata (metadata.annotations or metadata.labels), not on the Pod template (spec.template.metadata).

Supported workload kinds: Deployment, StatefulSet, DaemonSet, Job. CronJob is included when it owns running Pods.

Available keys

Key Object Purpose Effect
autovpa.deckhouse.io/vpa-update-mode Namespace, workload VPA update mode Sets spec.updatePolicy.updateMode on the VPA created by AutoVPA. Allowed values: Off, Initial, Recreate, InPlaceOrRecreate. Default: Off. Modes other than Off require a working VPA updater in the cluster and may change pod resource requests/limits.
autovpa.deckhouse.io/vpa-resource-policy Namespace, workload Resource policy JSON object mapped to spec.resourcePolicy on the VPA (containerPolicies, minAllowed, maxAllowed, and other VPA resource-policy fields).
autovpa.deckhouse.io/vpa-min-replicas Namespace Minimum replicas for eviction Integer string mapped to spec.updatePolicy.minReplicas. Namespace level only.
autovpa.deckhouse.io/exclude-containers Namespace, workload Exclude containers Comma-separated sidecar container names excluded from VPA recommendations (like istio-proxy or linkerd-proxy).
autovpa.deckhouse.io/enabled Namespace (label) Opt-in / opt-out See Enabling AutoVPA for namespaces with a special label. When AutoVPA runs with --on-by-default, a namespace label autovpa.deckhouse.io/enabled=false excludes that namespace. When onlySpecialLabel: true, the module uses this label to build the managed namespace list.

Examples

Set a non-default update mode on a Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: my-namespace
  annotations:
    autovpa.deckhouse.io/vpa-update-mode: "InPlaceOrRecreate"
spec:
  # ...

Set a resource policy on a Namespace:

apiVersion: v1
kind: Namespace
metadata:
  name: my-namespace
  annotations:
    autovpa.deckhouse.io/vpa-resource-policy: >
      {"containerPolicies":[{"containerName":"app","minAllowed":{"cpu":"100m","memory":"128Mi"}}]}

Applying workload annotation changes

If a VPA already exists, changing autovpa.deckhouse.io/vpa-update-mode on the Deployment does not update the VPA by itself. Restart the workload or set the same annotation on the Namespace:

kubectl rollout restart deployment/my-app -n my-namespace
kubectl get vpa d8-autovpa-my-app -n my-namespace -o jsonpath='{.spec.updatePolicy.updateMode}{"\n"}'

Coexistence with other VPAs

If a workload is already targeted by a VPA that does not carry all marker labels:

  • heritage: deckhouse
  • module: adaptive-resource-management
  • source: autovpa

AutoVPA will not create its own VPA for that workload. If AutoVPA previously created a VPA for the workload, it removes it on the next reconcile.

To let AutoVPA manage the workload again, delete the existing VPA (if it was created manually or by another tool).

Created VPA objects

For a workload named my-app, AutoVPA creates:

Field Value
VPA name d8-autovpa-my-app
Labels heritage: deckhouse, module: adaptive-resource-management, source: autovpa
Default update mode Off (recommendation-only)

Use these labels to tell AutoVPA-managed VPAs apart from manually created ones.

Troubleshooting

Symptom Likely cause What to check
VPA not created Namespace not in scope ModuleConfig, namespace labels, kube-/d8- name prefix
VPA not created Another VPA already targets the workload kubectl get vpa -n <namespace>
updateMode unchanged after annotation change No reconcile triggered kubectl rollout restart or set the annotation on the Namespace
Namespace labeled but no VPA Controller not updated yet ModuleConfig Ready, --include-namespaces on autovpa-controller