vertical-pod-autoscaler/docs/sidecar-containers.md
In this document, "sidecar container" refers to any additional Container that isn't the main application Container in a Pod. This is distinct from the native Kubernetes sidecar pattern, which makes use of initContainers. Our usage here applies to all additional regular containers only, as VPA does not support initContainers yet.
The Vertical Pod Autoscaler (VPA) has specific behavior when dealing with these additional containers that are injected into pods via admission webhooks.
To understand why sidecar handling is important, let's first look at how VPA manages containers by default. This default behavior is at the root of why special consideration is needed for sidecars.
When you create a VPA resource for a pod, it automatically attempts to manage ALL containers in that pod - not just the ones you explicitly configure. This happens because:
containerPolicy with mode: Auto to any container not explicitly configuredThis default "manage everything" approach can cause problems with sidecars because:
Example of a VPA resource that explicitly configures one container but affects all:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: main-container
minAllowed:
cpu: 100m
memory: 50Mi
# Note: Other containers will still get the default Auto mode
VPA uses a special annotation to track which containers were present in the pod before any webhook injections:
apiVersion: v1
kind: Pod
metadata:
annotations:
vpaObservedContainers: "main-container,logging-sidecar"
This annotation is crucial because:
The order of webhook execution is determined alphabetically by webhook names. For example:
webhooks:
- name: a.sidecar-injector.kubernetes.io # Executes first
- name: b.vpa.kubernetes.io # Executes second
- name: c.another-sidecar.kubernetes.io # Executes third
Without proper handling of sidecar containers, the following problematic sequence could occur:
If you know that you only use sidecar injecting webhooks which don't reconcile Container resources, you can choose to have VPA manage sidecar resources. Ensure your webhook names follow this pattern, resulting in the VPA admission-controller webhook to be executed last:
webhooks:
- name: sidecar-injector.kubernetes.io # Executes first
- name: zz.vpa.kubernetes.io # Executes last
This ensures:
vpaObservedContainers annotation includes all containersConfigure the VPA webhook to reinvoke after sidecar injection:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: vpa-webhook-config
webhooks:
- name: vpa.kubernetes.io
reinvocationPolicy: IfNeeded
rules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
This configuration:
When using Istio, which injects proxy sidecars:
# Istio sidecar injector webhook
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: istio-sidecar-injector
webhooks:
- name: a.sidecar-injector.istio.io # Alphabetically first
# VPA webhook configuration
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: vpa-webhook-config
webhooks:
- name: z.vpa.kubernetes.io # Alphabetically last
reinvocationPolicy: IfNeeded
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: web-app-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: web-app
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: main-container
minAllowed:
cpu: 100m
memory: 128Mi
- containerName: logging-sidecar # Explicitly configure sidecar
minAllowed:
cpu: 50m
memory: 64Mi