Kubernetes resource requests and limits are notoriously hard to set correctly. Over-provisioning wastes cluster resources and money. Under-provisioning causes throttling and OOM kills. Three tools help optimize pod resource allocation: Descheduler (evicts misconfigured pods), Vertical Pod Autoscaler (adjusts resource requests), and Goldilocks (provides VPA recommendations with a dashboard).

This guide compares their approaches, deployment patterns, and when to use each.

Quick Comparison

FeatureDeschedulerVertical Pod Autoscaler (VPA)Goldilocks
GitHubkubernetes-sigs/deschedulerkubernetes/autoscaler (VPA subdir)FairwindsOps/goldilocks
Stars5,3978,842 (autoscaler repo)3,213
Primary FunctionEvict poorly scheduled podsAuto-adjust resource requestsVPA recommendations + UI
Action TypeEviction (reactive)Patch requests (proactive)Recommendations (passive)
Auto-Apply Changes✅ Evicts pods✅ Updates requests (auto mode)❌ Recommendations only
Historical Analysis❌ Current state only✅ Usage history analysis✅ Usage history + visualization
Dashboard UI❌ CLI/logs only❌ CLI/metrics only✅ Web UI with recommendations
Last Active2026-052026-052026-04

Kubernetes Descheduler: Evicting Misconfigured Pods

The Descheduler finds pods that violate scheduling policies and evicts them so the default scheduler can place them better. It does not schedule pods itself — it only triggers evictions.

Architecture

Descheduler runs as a CronJob or Deployment in the cluster. It periodically analyzes pod placement against strategies and evicts pods that violate policies. The kube-scheduler then re-schedules them.

Installation

1
2
3
4
5
6
# Install Descheduler via Helm
helm repo add descheduler https://kubernetes-sigs.github.io/descheduler/
helm install descheduler descheduler/descheduler \
  --namespace kube-system \
  --version 0.30.0 \
  -f descheduler-values.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# descheduler-values.yaml
kind: Deployment

deschedulerPolicy:
  strategies:
    RemoveDuplicates:
      enabled: true
    LowNodeUtilization:
      enabled: true
      params:
        nodeResourceUtilizationThresholds:
          thresholds:
            cpu: 20
            memory: 20
            pods: 20
          targetThresholds:
            cpu: 50
            memory: 50
            pods: 50
    RemovePodsViolatingInterPodAntiAffinity:
      enabled: true
    RemovePodsViolatingTopologySpreadConstraint:
      enabled: true
      params:
        nodeFit: true

dryRun: false

Strategy: RemovePodsViolatingNodeAffinity

1
2
3
4
5
6
7
deschedulerPolicy:
  strategies:
    RemovePodsViolatingNodeAffinity:
      enabled: true
      params:
        nodeAffinityType:
        - requiredDuringSchedulingIgnoredDuringExecution

Strategy: LowNodeUtilization (Consolidation)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
deschedulerPolicy:
  strategies:
    LowNodeUtilization:
      enabled: true
      params:
        nodeResourceUtilizationThresholds:
          thresholds:
            cpu: 10
            memory: 10
            pods: 5
          targetThresholds:
            cpu: 40
            memory: 40
            pods: 40
          numberOfNodes: 1  # Only act if underutilized nodes >= 1

Strategy: Pod Lifetime Eviction

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
deschedulerPolicy:
  strategies:
    PodLifeTime:
      enabled: true
      params:
        podLifeTime:
          maxPodLifeTimeSeconds: 604800  # 7 days
          includingInitPodTerminating: true
          states:
          - phase:
              values:
              - Running
              - Pending

Key Strengths

  • Rebalancing: Consolidates workloads to reduce node count and save costs
  • Anti-affinity enforcement: Ensures pods respect anti-affinity rules after cluster changes
  • Topology spread: Maintains even distribution across zones
  • Non-disruptive: Respects PDBs and gracefully evicts pods

Vertical Pod Autoscaler (VPA): Automatic Right-Sizing

VPA analyzes historical resource usage and adjusts container resource requests to match actual needs. It operates in three modes: Off (recommendations only), Initial (set on pod creation), and Auto (continuously update).

Installation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Clone the autoscaler repo and install VPA
git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler/
./hack/vpa-up.sh

# Or install via Helm (third-party chart)
helm repo add fairwinds-stable https://registry.fairwinds.com/charts/stable
helm install vpa fairwinds-stable/vpa \
  --namespace vpa \
  --create-namespace

VPA Resource Definition

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: nginx-vpa
  namespace: production
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  updatePolicy:
    updateMode: "Auto"  # Off | Initial | Auto
  resourcePolicy:
    containerPolicies:
    - containerName: nginx
      minAllowed:
        cpu: 100m
        memory: 64Mi
      maxAllowed:
        cpu: "2"
        memory: 2Gi
      controlledResources:
      - cpu
      - memory

VPA Recommendation Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
kubectl describe vpa nginx-vpa

# Status:
# Recommendation:
#   container: nginx
#   Target:
#     cpu:     250m
#     memory:  256Mi
#   Lower Bound:
#     cpu:     100m
#     memory:  128Mi
#   Uncapped Target:
#     cpu:     250m
#     memory:  256Mi

Key Strengths

  • Data-driven: Based on actual resource usage, not guesses
  • Auto mode: Continuously adjusts without manual intervention
  • Min/max bounds: Prevents extreme recommendations
  • Works with HPA: VPA for requests, HPA for replica count

Limitations

  • Pod restart required: Changing requests forces pod restart (except with in-place VPA on Kubernetes 1.27+)
  • Not for all workloads: StatefulSets and DaemonSets need careful configuration
  • History dependency: Needs time to build accurate recommendations

Goldilocks: VPA Recommendations with a Dashboard

Goldilocks wraps VPA with a web dashboard that displays resource recommendations across all namespaces. It runs VPA in “Off” mode (recommendations only) and visualizes the results.

Installation

1
2
3
4
5
6
7
# Install Goldilocks via Helm
helm repo add fairwinds-stable https://registry.fairwinds.com/charts/stable
helm install goldilocks fairwinds-stable/goldilocks \
  --namespace goldilocks \
  --create-namespace \
  --set installVPA=true \
  --set installMetricsServer=true
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# goldilocks-values.yaml
installVPA: true
installMetricsServer: true

goldilocks:
  flags:
    vpa-label-selector: "
    on-by-default: true
    include-namespaces: "production,staging"
    exclude-namespaces: "kube-system,monitoring"

dashboard:
  ingress:
    enabled: true
    className: nginx
    hosts:
    - host: goldilocks.example.com
      paths:
      - path: /
        pathType: Prefix

Accessing the Dashboard

1
2
3
4
# Port-forward to access locally
kubectl port-forward svc/goldilocks-dashboard -n goldilocks 8080:80

# Or access via ingress at goldilocks.example.com

The dashboard shows:

  • Current resource requests vs. VPA recommendations
  • Historical resource usage graphs
  • Namespace-level summaries
  • Cost impact of right-sizing

Key Strengths

  • Visualization: See all recommendations in one place
  • Safe by default: Recommendations only — no automatic changes
  • Multi-namespace: View recommendations across the entire cluster
  • Cost awareness: Understand the financial impact of over/under-provisioning

Choosing the Right Tool

ScenarioBest ChoiceWhy
Rebalance workloads across nodesDeschedulerEvicts and re-schedules pods
Automatically right-size resource requestsVPA (Auto mode)Adjusts requests based on usage
See recommendations before applyingGoldilocksDashboard + safe recommendations
Reduce cluster node countDeschedulerLowNodeUtilization consolidation
Prevent OOM killsVPALearns actual memory usage
Team collaboration on sizingGoldilocksVisual recommendations for review

Using Them Together

The most effective approach is to use all three:

  1. Goldilocks identifies right-sizing recommendations across namespaces
  2. VPA applies the recommendations (in Auto mode or after review)
  3. Descheduler ensures pods are well-distributed after resource changes
1
2
3
4
5
6
7
# Combined deployment strategy
# 1. Install metrics-server (required for VPA)
# 2. Install VPA in Off mode + Goldilocks for visibility
# 3. Review recommendations in Goldilocks dashboard
# 4. Enable VPA Auto mode for non-critical workloads
# 5. Install Descheduler for node consolidation
# 6. Run Descheduler nightly to rebalance after VPA changes

Why Resource Optimization Matters

In Kubernetes, every pod requests CPU and memory resources. These requests determine scheduling decisions, node capacity planning, and cluster autoscaling. But most teams set requests based on guesswork or copy-pasted values.

The consequences are significant:

  • Over-provisioning: Requesting 2 CPU when 200m is needed wastes 90% of allocated resources. Multiply this across hundreds of pods and you’re paying for idle capacity.
  • Under-provisioning: Requesting too little memory causes OOM kills. Requesting too little CPU causes throttling, increasing latency.
  • Node waste: Poorly sized pods prevent efficient bin-packing, leading to underutilized nodes that still cost money.

Resource optimization tools turn guesswork into data-driven decisions. VPA learns from actual usage, Descheduler corrects scheduling drift, and Goldilocks makes recommendations visible to the whole team.

For cluster-level autoscaling, see our Karpenter vs Cluster Autoscaler vs KEDA guide. For node management and health monitoring, the Node Problem Detector vs NFD vs Goldilocks article covers node-level optimization. For cluster management platforms, our Rancher vs KubeSpray vs Kind comparison covers the infrastructure layer.

Resource optimization tools turn guesswork into data-driven decisions. VPA learns from actual usage, Descheduler corrects scheduling drift, and Goldilocks makes recommendations visible to the whole team.

For cluster-level autoscaling, see our Karpenter vs Cluster Autoscaler vs KEDA guide. For node management and health monitoring, the Node Problem Detector vs NFD vs Goldilocks article covers node-level optimization. For cluster management platforms, our Rancher vs KubeSpray vs Kind comparison covers the infrastructure layer. Together, they form a continuous optimization loop that adapts to changing workload patterns.

Karpenter vs Cluster Autoscaler vs KEDA guide. For node management and health monitoring, the Node Problem Detector vs NFD vs Goldilocks article covers node-level optimization.

FAQ

Can VPA and HPA work together?

Yes, but with caveats. VPA should manage resource requests (cpu/memory) while HPA manages replica count. However, VPA and HPA should not both manage the same resource. The recommended pattern: VPA controls CPU/memory requests, HPA controls replicas based on custom metrics (RPS, queue depth, etc.).

Does Descheduler disrupt running applications?

Descheduler respects PodDisruptionBudgets (PDBs) and only evicts pods when safe to do so. The nodeFit parameter ensures pods are only evicted if there is a suitable node to reschedule them on.

How long does VPA need to generate accurate recommendations?

VPA typically needs 8-24 hours of historical data to generate initial recommendations. Accuracy improves over time as more usage data is collected. For workloads with variable patterns (batch jobs, cron jobs), VPA may need several days.

Can Goldilocks automatically apply recommendations?

No. Goldilocks runs VPA in “Off” mode, which means it only generates recommendations. To auto-apply, you need to switch VPA to “Auto” mode or use the kubectl patch command to apply the recommended values manually.

What happens if Descheduler evicts all pods on a node?

Descheduler’s strategies are designed to avoid this. The LowNodeUtilization strategy only acts when nodes are below a threshold, and the nodeFit parameter ensures pods have a place to go. PDBs also prevent mass evictions.

Is VPA safe for production workloads?

VPA’s “Initial” mode is safe — it only sets requests on pod creation. “Auto” mode triggers pod restarts when changing requests, which may cause brief downtime. For critical workloads, use “Initial” mode or review Goldilocks recommendations before applying.