Install Goldilocks on EKS to Right-Size Kubernetes Resources

5/5 - (1 vote)

Most EKS clusters waste money the same way: application teams guess CPU and memory requests, then never revisit them. Requests that are too high leave nodes half empty. Requests that are too low get throttled or OOM-killed. On a Karpenter cluster this is worse, because node size follows pod requests. Bad requests create the wrong nodes.

Goldilocks does not magically set the perfect values. It uses Kubernetes Vertical Pod Autoscaler (VPA) in recommendation mode and shows you Guaranteed / Burstable starting points in a dashboard. You still apply the numbers in Helm charts or manifests.

This guide is the runbook I use to install it on EKS.

What you get

PieceRole
metrics-serverExposes pod CPU and memory usage (kubectl top)
VPA recommenderWatches usage and writes a suggested request
Goldilocks controllerCreates a VPA object per workload in labeled namespaces
Goldilocks dashboardShows those suggestions in a UI

Important: leave VPA updater and admission controller disabled. Goldilocks should recommend. It should not evict pods or rewrite live specs.

Prerequisites

  • kubectl pointed at the target EKS cluster
  • Helm 3
  • Cluster-admin (or enough RBAC to install CRDs and cluster roles)
  • EKS already running workloads you care about (recommendations need real traffic)

Connect:

aws eks update-kubeconfig --name cluster-name --region region-name
kubectl get nodes

Example for a typical US cluster:

aws eks update-kubeconfig --name dev-cluster --region us-east-1

Step 1 — Confirm metrics-server

EKS usually already has metrics-server as an add-on.

kubectl get deployment metrics-server -n kube-system
kubectl top nodes
kubectl top pods -A | head

If metrics-server is missing:

helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
helm repo update

helm upgrade --install metrics-server metrics-server/metrics-server \
  --namespace kube-system

Do not install a second metrics-server if one already exists. Two copies fight over the Metrics API.

Step 2 — Install VPA (recommender only)

Install VPA as its own Helm release so you can upgrade it independently of Goldilocks.

helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm repo update

helm upgrade --install vpa fairwinds-stable/vpa \
  --namespace vpa \
  --create-namespace \
  --set recommender.enabled=true \
  --set updater.enabled=false \
  --set admissionController.enabled=false

Why those flags:

  • recommender=true — this is the only component Goldilocks needs
  • updater=false — no automatic pod restarts to apply new requests
  • admissionController=false — no mutating webhook on every pod create

Wait until it is healthy:

kubectl get pods -n vpa
kubectl get crd | grep verticalpodautoscaler

You should see CRDs such as verticalpodautoscalers.autoscaling.k8s.io.

Step 3 — Install Goldilocks

helm upgrade --install goldilocks fairwinds-stable/goldilocks \
  --namespace goldilocks \
  --create-namespace \
  --set dashboard.enabled=true \
  --set controller.enabled=true

Do not set vpa.enabled=true here if you already installed VPA in step 2. Two VPA installs will conflict.

Check pods:

kubectl get pods -n goldilocks
kubectl get svc -n goldilocks

Expect a controller and a dashboard, both Running.

Step 4 — Opt in namespaces

Goldilocks is opt-in. Nothing is monitored until you label a namespace.

Do not label system namespaces:

  • kube-system
  • karpenter
  • goldilocks
  • vpa
  • kube-public
  • kube-node-lease

Label application namespaces:

kubectl get ns

kubectl label namespace default goldilocks.fairwinds.com/enabled=true --overwrite
kubectl label namespace <your-app-ns> goldilocks.fairwinds.com/enabled=true --overwrite

After a minute, VPAs appear:

kubectl get vpa -A

Each VPA should show updateMode: Off (recommend only). Confirm one:

kubectl get vpa -n <your-app-ns> -o yaml | grep -A2 updatePolicy

Step 5 — Open the dashboard

Port-forward is enough for a first look:

kubectl -n goldilocks port-forward svc/goldilocks-dashboard 8080:80

Open http://localhost:8080.

You will see namespaces you labeled, then workloads, then QoS columns (typically Guaranteed and Burstable) with suggested CPU and memory.

First-hour numbers are noisy. VPA needs hours to days of production-like traffic before the recommendation is trustworthy. Low-traffic namespaces will look empty or jumpy. That is expected.

How to use the numbers

Treat the dashboard as a starting point, not an auto-apply button.

A practical workflow:

  1. Pick a deployment that has run for at least a day under real load.
  2. Note Goldilocks Burstable CPU/memory (good default for most HTTP apps).
  3. Update resources.requests in Helm values or the Deployment.
  4. Set limits only if you have a reason (memory limits prevent noisy-neighbor OOMs; CPU limits often cause throttling).
  5. Roll the deployment and watch p99 latency and restarts.
  6. Come back in a week.

On Karpenter, lower requests can shrink nodes. Apply changes in one namespace first, then watch kubectl get nodepool / node count before you roll this out everywhere.

Safety checklist

  • VPA updater stays off.
  • VPA admission webhook stays off.
  • Goldilocks is not enabled on kube-system or Karpenter.
  • You are not running two metrics-servers.
  • You wait for real traffic before trusting a recommendation.
  • You change requests in Git / Helm, not by hand on a live pod.

If someone later enables updater.enabled=true, VPA will evict pods to apply new requests. That is a production incident waiting to happen. Keep it off unless you have a dedicated rightsizing program.

Optional: expose the dashboard inside the cluster

Port-forward is fine for admins. If you already have an ingress controller (ALB / NGINX), you can enable ingress on the Helm chart instead of leaving the UI on localhost.

Example values:

dashboard:
  enabled: true
  ingress:
    enabled: true
    ingressClassName: alb   # or nginx
    hosts:
      - host: goldilocks.example.internal
        paths:
          - path: /
            type: Prefix

Keep this on a private hostname or VPN. The dashboard is operational data, not a public site.

Uninstall

helm uninstall goldilocks -n goldilocks
helm uninstall vpa -n vpa
kubectl delete namespace goldilocks vpa

VPAs in labeled app namespaces may remain. Clean them if you are fully removing the tool:

kubectl delete vpa -A --all
kubectl label namespace <your-app-ns> goldilocks.fairwinds.com/enabled-

Troubleshooting

Dashboard is empty
The namespace is not labeled, or the controller is not running. Check kubectl get pods -n goldilocks and kubectl get ns --show-labels.

No VPA objects
Controller RBAC failed, or the namespace label is missing. Check controller logs:

kubectl logs -n goldilocks deploy/goldilocks-controller

kubectl top fails
metrics-server is down or not installed. Goldilocks cannot work without it.

Recommendations look insane (tiny or huge)
The workload is idle, or it had a one-time spike. Wait for a full traffic cycle (weekday + peak) before changing production requests.

Pods restarting after install
You accidentally enabled the VPA updater or admission controller. Disable them immediately and roll back the Helm values in step 2.

Commands in one block

# kubeconfig
aws eks update-kubeconfig --name <cluster-name> --region <region>

# metrics-server check
kubectl get deployment metrics-server -n kube-system
kubectl top nodes

# VPA (recommend only)
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm repo update
helm upgrade --install vpa fairwinds-stable/vpa \
  --namespace vpa --create-namespace \
  --set recommender.enabled=true \
  --set updater.enabled=false \
  --set admissionController.enabled=false

# Goldilocks
helm upgrade --install goldilocks fairwinds-stable/goldilocks \
  --namespace goldilocks --create-namespace \
  --set dashboard.enabled=true \
  --set controller.enabled=true

# opt in
kubectl label namespace <your-app-ns> goldilocks.fairwinds.com/enabled=true --overwrite
kubectl get vpa -A

# UI
kubectl -n goldilocks port-forward svc/goldilocks-dashboard 8080:80

Takeaway

Goldilocks is the missing feedback loop for Kubernetes resource requests on EKS. Install metrics-server (if needed), install VPA as a recommender only, install Goldilocks, label application namespaces, and wait for real traffic. Then change requests in Git.

The tool is cheap to run and expensive to misuse. Keep the updater off, skip system namespaces, and treat the dashboard as advice — not an autoscaler.

Share On:

Leave a Comment