Kubernetes maakt het makkelijk om resources toe te wijzen en moeilijk om te weten of die toewijzingen kloppen met de werkelijkheid. Een Google Cloud-onderzoek toonde aan dat slechts ongeveer 13% van de aangevraagde CPU in een typisch cluster daadwerkelijk wordt gebruikt. De rest is wel gealloceerd maar inactief — gereserveerd door de scheduler, kost nodecapaciteit en cloudbudget, maar doet geen nuttig werk.
De oorzaak is eenvoudig. Ontwikkelaars stellen resource requests hoog in omdat de kosten van te weinig toewijzen (OOMKills, throttling, mislukte deploys) zichtbaar en direct zijn, terwijl de kosten van te veel toewijzen (verspild cloudbudget) onzichtbaar zijn tot de maandelijkse factuur binnenkomt. Deze gids doorloopt de praktische stappen om dat gat te dichten.
Stap 1: kostenvisibiliteit krijgen met Kubecost of kubectl top
Je kunt niet rightsizen wat je niet kunt zien. Stel eerst een basislijn vast van wat het cluster daadwerkelijk gebruikt versus wat het toewijst, voordat je resource specs aanpast.
kubectl top: het startpunt zonder installatie
Als metrics-server draait (standaard op EKS, GKE en AKS), toont kubectl top realtime CPU- en geheugenverbruik:
# Per-pod verbruik in een namespace
kubectl top pods -n production
# Per-node verbruik over het hele cluster
kubectl top nodes
Vergelijk de output met wat er is aangevraagd:
# Toon requests naast daadwerkelijk verbruik
kubectl top pods -n production --containers \
| sort -k3 -h -r # sorteer op CPU-verbruik aflopend
kubectl top geeft een momentopname. Het toont geen kosten, historische trends of inactieve resources in één oogopslag. Daarvoor heb je een specifieke tool nodig.
Kubecost: kostentoewijzing en inactieve resources bijhouden
Kubecost is de meest gebruikte open-source Kubernetes-kostenmonitoringtool. De gratis tier (OpenCost) biedt kostentoewijzing per namespace, deployment en label. Kubecost 3.1 introduceerde Resource Quota Rightsizing, dat namespace-niveau quota-aanpassingen aanbeveelt op basis van daadwerkelijk gebruik.
Installeer met Helm:
helm repo add kubecost https://kubecost.github.io/cost-analyzer/
helm install kubecost kubecost/cost-analyzer \
-n kubecost --create-namespace \
--set kubecostToken="YOUR_TOKEN"
Na 24–48 uur dataverzameling toont het dashboard:
- Totale clusterkosten uitgesplitst per namespace, deployment en pod
- Inactieve kosten: het verschil tussen wat is gealloceerd en wat wordt gebruikt, uitgedrukt in euro's
- Efficiëntiescore: daadwerkelijk gebruik / aangevraagde resources als percentage
- Rightsizing-aanbevelingen: voorgestelde request/limit-wijzigingen per container
Het getal voor inactieve kosten is de belangrijkste metric voor een kostenoptimalisatiegesprek. Het beantwoordt "hoeveel betalen we voor resources die niets doen?"
Cloud-providerspecifieke tools
Elke cloudprovider biedt ingebouwde kostenvisibiliteit:
- AWS: AWS Cost Explorer met EKS-kostentoewijzingstags
- GCP: GKE-kostentoewijzing in Cloud Billing
- Azure: AKS-kostenanalyse in Azure Cost Management
Deze tools tonen kosten op nodeniveau maar niet verspilling op podniveau. Kubecost vult dat gat door kosten te koppelen aan individuele workloads.
Stap 2: rightsizing-aanbevelingen genereren met Goldilocks
Fairwinds Goldilocks installeert de VPA-Recommender in aanbevelingsmodus en voegt een webdashboard toe. Het maakt een VPA-object in Off-modus aan voor elke Deployment in gelabelde namespaces en toont de rightsizing-aanbevelingen met kopieerbare resources:-YAML.
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm install goldilocks fairwinds-stable/goldilocks \
-n goldilocks --create-namespace
# Goldilocks inschakelen voor een namespace
kubectl label namespace production goldilocks.fairwinds.com/enabled=true
Open het dashboard:
kubectl -n goldilocks port-forward svc/goldilocks-dashboard 8080:80
Na 7 dagen dataverzameling toont het dashboard per-Deployment aanbevelingen op drie percentiel-niveaus (ondergrens, doel, bovengrens). De target-waarde is wat VPA zou toepassen in een afdwingingsmodus — dit vertegenwoordigt het 90e percentiel van waargenomen gebruik.
De werkwijze is: installeer Goldilocks, wacht een week, beoordeel het dashboard, pas handmatig de aanbevelingen toe die zinvol zijn en herhaal maandelijks.
Voor workloads waarbij je geautomatiseerde rightsizing wilt in plaats van een dashboard, configureer VPA in afdwingingsmodus.
Stap 3: namespace resource quota's implementeren
ResourceQuota stelt een hard plafond in op het totaal van resource requests en limits binnen een namespace. Het voorkomt dat een enkel team of omgeving een onbegrensd deel van het cluster opeist.
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
limits.memory: 80Gi
pods: "100"
Stel quota's in op basis van de Kubecost- of Goldilocks-data uit stap 1 en 2. Als een namespace momenteel 20 CPU aanvraagt maar er 4 gebruikt, geeft een quota van 8–10 CPU het team 2–2,5x hun werkelijke gebruik als marge, terwijl de rest wordt vrijgemaakt voor andere workloads of nodeafbouw.
Controleer huidig gebruik tegen quota's:
kubectl describe resourcequota production-quota -n production
Stap 4: LimitRange gebruiken om standaarden af te dwingen
Een ResourceQuota begrenst het namespace-totaal maar voorkomt niet dat een enkele pod alles opeist. LimitRange stelt per-container standaarden en grenzen in.
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: production
spec:
limits:
- type: Container
default: # toegepast wanneer geen limit is opgegeven
cpu: "500m"
memory: 512Mi
defaultRequest: # toegepast wanneer geen request is opgegeven
cpu: "100m"
memory: 128Mi
max: # geen container mag dit overschrijden
cpu: "4"
memory: 8Gi
min: # geen container mag hieronder gaan
cpu: "50m"
memory: 64Mi
LimitRange is vooral waardevol voor development- en staging-namespaces waar ontwikkelaars deployen zonder expliciete resource specs. Zonder LimitRange krijgen pods geen requests en geen limits (BestEffort QoS), waardoor scheduling onvoorspelbaar wordt en kostentracking onmogelijk.
Stap 5: combineren met spot-instances en autoscaling
Rightsizing en governance verlagen de kosten per pod. De volgende laag verlaagt de kosten per node.
Spot-instances
Spot- en preemptible instances kosten 60–80% minder dan on-demand. Na rightsizing zijn workloads kleiner en passen ze waarschijnlijker op spot-instancetypen. Draai stateless, fouttolerante workloads op spot-nodes. Houd stateful workloads (databases, persistente queues) op on-demand nodes.
Cluster Autoscaler en Karpenter
Cluster Autoscaler verwijdert nodes die onderbenut zijn. Na rightsizing zijn eerder volle nodes mogelijk halfleeg geworden. De autoscaler consolideert pods op minder nodes en beëindigt de overtollige.
Karpenter (EKS) gaat verder: het selecteert het goedkoopste instancetype dat past bij de wachtende workload, combineert spot en on-demand, ARM en x86, over meerdere instancefamilies. Gerightsizte pods geven Karpenter meer flexibiliteit omdat kleinere resourceblokken op een breder scala aan instancetypen passen.
Het samengestelde effect
Deze lagen versterken elkaar. Een workload rightsizen van 1 CPU / 2 Gi naar 200m / 300 Mi betekent:
- De pod gebruikt 80% minder geplande capaciteit
- De scheduler plaatst meer pods per node
- De autoscaler verwijdert onderbenutte nodes
- Karpenter kiest kleinere, goedkopere instancetypen
- Spot-geschiktheid neemt toe omdat de workload onderbrekingen verdraagt
Een cluster dat agressief rightsizet en stateless workloads op spot draait, kan de computefactuur met 70–85% verlagen ten opzichte van dezelfde workloads op overbemeten on-demand nodes.
Een kostenreview-ritme opzetten
Kostenoptimalisatie is geen eenmalig project. Workloads veranderen, teams deployen nieuwe diensten en aanbevelingen verschuiven.
Wekelijks: bekijk de metric voor inactieve kosten in Kubecost. Als inactieve uitgaven boven een drempel stijgen (bijvoorbeeld 40% van het totaal), onderzoek welke namespaces gegroeid zijn.
Maandelijks: bekijk Goldilocks-aanbevelingen. Pas aanbevelingen toe die 4+ weken stabiel zijn. Controleer of namespace-quota's nog overeenkomen met de werkelijkheid.
Per kwartaal: audit de spot-instancedekking. Bekijk Karpenter- of Cluster Autoscaler-logs voor nodeconsolidatie-mogelijkheden. Herzie de instancefamily-diversificatie.
Bij elke nieuwe service-deploy: vereis resource requests in de Deployment-spec (dwing af via admission webhook of CI-beleid). Gebruik Goldilocks-aanbevelingen uit staging als beginwaarden voor productie.
Wat kostenoptimalisatie NIET is
- Niet gewoon hoge resource requests instellen om veilig te zitten. Te veel aanvragen is de belangrijkste oorzaak van verspilling. De scheduler reserveert wat je vraagt, ook als de pod het nooit gebruikt. Requests op 2x het werkelijke gebruik instellen betekent dat de helft van je cluster betaald maar inactief is.
- Niet iets dat autoscaling alleen oplost. HPA en Cluster Autoscaler reageren op vraag, maar kunnen te hoge requests niet corrigeren. Als een pod 1 CPU aanvraagt en 100m gebruikt, schaalt HPA die nooit omlaag — het is al 1 replica met 10% bezetting. Het rightsizen van de request is de voorwaarde.
- Niet cloudprovider-specifiek. Kubecost, Goldilocks, VPA, ResourceQuota en LimitRange werken op elk Kubernetes-cluster — EKS, GKE, AKS, on-premises of bare metal. De specifieke spot-instancemechanismen verschillen per provider, maar de rightsizing-werkwijze is universeel.