The module lifecycle stage: Experimental
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: trueIn 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: prodAutoVPA 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: trueThen add the label to the desired namespaces:
d8 k label namespace my-namespace autovpa.deckhouse.io/enabled=trueWhen 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: backendIn 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:
- Annotation takes precedence over label with the same key.
- 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: deckhousemodule: adaptive-resource-managementsource: 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 |