Skip to main content
RunBook Academy

KubernetesLXXXIII · Vertical Pod Autoscaling ConceptsVertical Pod Autoscaler

VPA admission controller — the mutating webhook

Advanced⏱ ~12 minkubectlvpa

What you'll learn

  • Explain how the VPA admission controller sets the requests
  • Identify the mutating webhook configuration
  • Diagnose admission controller failures
  • Configure the admission controller for production

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

The VPA admission controller is a mutating webhook that runs in the cluster. It intercepts the pod creation and sets the resource requests to the VPA-recommended values. This lesson walks the admission controller, the webhook configuration, and the failure modes.

The admission controller

The VPA admission controller is a mutating webhook:

flowchart LR
    A[Pod creation] --> B[API server]
    B --> C[Admission controller]
    C --> D[Set resource requests]
    D --> E[Mutated pod]
    E --> F[Kubelet]
    F --> G[Pod with VPA-recommended requests]

The mutation is transparent to the pod spec. The Deployment’s pod template is not modified; the mutation happens at pod creation time.

The webhook configuration

The mutation is configured via a MutatingWebhookConfiguration:

apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: vpa-webhook
webhooks:
- name: vpa.k8s.io
  clientConfig:
    service:
      name: vpa-admission-controller
      namespace: kube-system
      path: /
      port: 8000
  rules:
  - operations: ["CREATE"]
    apiGroups: [""]
    apiVersions: ["v1"]
    resources: ["pods"]
  namespaceSelector:
    matchLabels:
      vpa-enabled: "true"
  failurePolicy: Ignore
  sideEffects: None
  admissionReviewVersions: ["v1"]

The webhook matches pods with the vpa-enabled: "true" label.

The mutation

The pod creation:

# Pod spec (in Deployment)
spec:
  containers:
  - name: nginx
    image: nginx:1.25
    resources:
      requests:
        cpu: 100m
        memory: 128Mi

The mutated pod:

# Mutated pod (after VPA admission)
spec:
  containers:
  - name: nginx
    image: nginx:1.25
    resources:
      requests:
        cpu: 150m  # VPA-recommended
        memory: 200Mi  # VPA-recommended

The mutation changes the requests to the VPA-recommended values.

The verify

kubectl get pod nginx-1-abc -o jsonpath='{.spec.containers[0].resources.requests}'
{"cpu":"150m","memory":"200Mi"}

The output confirms the VPA-recommended requests are applied.

The interaction with the Pod spec

The VPA admission controller interacts with the Pod spec:

sequenceDiagram
    participant D as Deployment
    participant API as API server
    participant VPA as VPA admission
    participant K as Kubelet
    D->>API: create pod
    API->>VPA: mutate pod
    VPA->>VPA: get recommended requests
    VPA->>VPA: set resources.requests
    VPA-->>API: mutated pod
    API->>K: schedule pod
    Note over K: Pod has VPA-recommended requests

The mutation happens between the API server and the kubelet.

The failurePolicy

The webhook’s failurePolicy determines the behavior on failure:

failurePolicy: Ignore
  • Ignore: if the webhook is unreachable, the pod is created without the VPA mutation.
  • Fail: if the webhook is unreachable, the pod is rejected.

Ignore is the production default. The VPA mutation is not critical; the pod can run without it.

The namespace selector

The webhook’s namespace selector limits the mutation to specific namespaces:

namespaceSelector:
  matchLabels:
    vpa-enabled: "true"

Only namespaces with the vpa-enabled: "true" label have the VPA mutation applied.

kubectl label namespace default vpa-enabled=true

The label is applied to the namespace.

The admission controller deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vpa-admission-controller
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: vpa-admission-controller
  template:
    metadata:
      labels:
        app: vpa-admission-controller
    spec:
      containers:
      - name: admission-controller
        image: registry.k8s.io/autoscaling/vpa-admission-controller:v0.13.x
        ports:
        - containerPort: 8000

The admission controller is a single replica. The webhook is HA by virtue of the API server’s retry behavior.

The failure modes

The common failure modes:

Admission controller unavailable

Error from server: failed calling webhook "vpa.k8s.io": connection refused

The admission controller is not running. Verify the pod status:

kubectl get pods -n kube-system -l app=vpa-admission-controller

Wrong namespace selector

Pod created without VPA mutation

The namespace selector is misconfigured. Verify the namespace labels.

Wrong container name

VPA recommendation does not apply to the container

The VPA targets a specific container. Verify the containerPolicies configuration.

flowchart LR
    A[Admission controller issue] --> B{Type?}
    B -->|Unavailable| C[Check pod status]
    B -->|Namespace selector| D[Check namespace labels]
    B -->|Wrong container| E[Check containerPolicies]

Cross-course references

  • The HPA course (Part LXXXII) covers the horizontal alternative.
  • The Prometheus course covers VPA metrics.
  • The Observability course covers VPA monitoring.

Quiz

Knowledge check · 4 questions

  1. Q1. Where does the VPA admission controller mutate the pod spec?

  2. Q2. failurePolicy: Fail on the VPA webhook can block pod creation if the admission controller is unavailable.

  3. Q3. Walk the diagnosis of pods that are not being mutated by the VPA admission controller.

    Deployment nginx with VPA. The pods are created with the original requests, not the VPA-recommended requests. The team is investigating.

  4. Q4. What is the role of the namespace selector in the VPA admission controller?

Passing score: 75%. Answers are checked in this browser.

Production discipline

  • Deploy the admission controller as a single replica. HA is via the API server’s retry.
  • Use failurePolicy: Ignore. Avoid blocking pod creation.
  • Set the namespace selector. Limit the VPA’s scope.
  • Verify the namespace labels. The label must be present.
  • Test the VPA on staging. Catch the mutation issues before production.
  • Document the admission controller config. The selector, the failurePolicy, the namespace.

The VPA admission controller is the mutation engine. Operating it well is deploying the controller, setting the selector, and testing the mutation.