FinOps dla Kubernetes: prawidłowa wielkość, instancje punktowe i redukcja kosztów
68% organizacji korzystających z Kubernetesa w produkcji wydaje o 20-40% więcej niż to konieczne (badanie kosztów CNCF 2026). Nie dlatego, że Kubernetes jest nieefektywny, ale dlatego, że obfite i łatwe udostępnianie, a odpowiednie dobranie rozmiaru wymaga dyscypliny operacyjnej. The wynik i klaster ze średnim wykorzystaniem procesora na poziomie 15-20% i pamięci na poziomie 30-40%: zasoby opłacone ale nie używaj.
FinOps dla Kubernetesa oraz praktyka mierzenia, optymalizacji i zarządzania wydatki klastra. W tym artykule zobaczymy, jak z niego korzystać Kubecost dla widoczność kosztów dla przestrzeni nazw, takich jak Umowa o partnerstwie pomaga w dopasowywaniu rozmiaru automatyczne żądania, jak Stolarz optymalizuje pakowanie bin węzłów z instancjami spot oraz jakie polityki należy wdrożyć na poziomie organizacji, aby utrzymać koszty pod kontrolą w czasie.
Czego się nauczysz
- Zainstaluj i skonfiguruj Kubecost pod kątem widoczności przestrzeni nazw/kosztów zespołu
- VPA w trybie wyłączonym: automatyczne zalecenia dotyczące zmiany rozmiaru bez zakłóceń
- Karpenter: Konsolidacja w celu optymalnego pakowania węzłów
- Wykrywaj instancje na AWS/GCP/Azure za pomocą Karpenter i zarządzaj przerwaniami
- ResourceQuota jako narzędzie do budżetowania zespołowego
- Powiadom Prometheusa o nieprawidłowościach w zakresie marnotrawstwa i kosztów
- Jak zbudować system obciążeń zwrotnych dla zespołów
- Punkt odniesienia: realne oszczędności możliwe do osiągnięcia przy każdej technice
Dlaczego Kubernetes ma tendencję do nadmiernej alokacji
Przed optymalizacją musisz zrozumieć przyczyny problemu:
- Konserwatywne żądania: Zespoły ustawiają żądania na wysokim poziomie, „aby były bezpieczne” (np. 1 procesor dla aplikacji korzystającej z 0,1). Żądania określają liczbę potrzebnych węzłów
- Limity = żądania: Wiele szablonów CI/CD ustawia limity równe żądaniom, tworząc systematyczne nadmierne udostępnianie
- Puste przestrzenie nazw: Przestrzeń nazw programistycznych z kapsułami „Hello World”, które działają 24 godziny na dobę, 7 dni w tygodniu
- Węzły oversize: Duże instancje w chmurze z niewydajnym pakowaniem bin (pod 2 vCPU w węźle 32 vCPU)
- Brak widoczności drużyn: Jeśli zespoły nie widzą swoich kosztów, nie mają motywacji do optymalizacji
Kubecost: Widoczność kosztów przestrzeni nazw
Kubecost Jest to najczęściej używane narzędzie FinOps w ekosystemie Kubernetes. Zbiera metryki z Prometheusa, pobiera ceny instancji w chmurze (AWS, GCP, Azure) i oblicz koszt przydzielony na przestrzeń nazw, wdrożenie, konto usługi i etykietę.
Instalacja Kubecostu
# Installa Kubecost con Helm
helm repo add kubecost https://kubecost.github.io/cost-analyzer/
helm repo update
helm install kubecost kubecost/cost-analyzer \
--namespace kubecost \
--create-namespace \
--set kubecostToken="your-token-here" \
--set prometheus.enabled=true \
--set grafana.enabled=true \
--set global.prometheus.enabled=false \
--set global.prometheus.fqdn="http://prometheus.monitoring.svc:9090"
# Port-forward per accedere alla UI
kubectl port-forward svc/kubecost-cost-analyzer 9090:9090 -n kubecost &
# Apri: http://localhost:9090
# Alternativa open-source senza token: OpenCost
helm install opencost opencost/opencost \
--namespace opencost \
--create-namespace
Skonfiguruj obciążenie zwrotne dla zespołów
# Kubecost usa i label Kubernetes per il cost allocation
# Configura label standard per tutti i workload:
# Nel values.yaml di ogni applicazione (Helm):
podLabels:
team: "team-alpha"
cost-center: "CC-2024-ENG"
environment: "production"
product: "checkout-service"
# Kubecost mostra automaticamente i costi aggregati per questi label.
# Es: costo totale team-alpha nel mese = CPU + Memoria + Storage + GPU + Networking
# API Kubecost per report automatici (da inviare via email settimanale):
curl "http://kubecost:9090/model/allocation?window=7d&aggregate=label:team&accumulate=true" \
| jq '.data[0] | to_entries[] | {team: .key, cost: .value.totalCost}'
VPA dla automatycznej zmiany rozmiaru
Il Pionowe automatyczne skalowanie podów (VPA) analizuje historyczne zużycie procesora i
Pamięć kapsuły i oblicza optymalne żądania. W trybie Off (zalecenie
bez automatycznego stosowania) jest najbezpieczniejszym narzędziem do zmiany rozmiaru: zapewnia
dokładne liczby bez ryzyka zakłóceń.
# Installa VPA
git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler
./hack/vpa-up.sh
# Oppure con Helm
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm install vpa fairwinds-stable/vpa \
--namespace vpa \
--create-namespace
---
# vpa-recommendation.yaml - modalita Off: solo raccomandazioni
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: api-service-vpa
namespace: team-alpha
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: api-service
updatePolicy:
updateMode: "Off" # non applica automaticamente, solo raccomanda
resourcePolicy:
containerPolicies:
- containerName: api
minAllowed:
cpu: 50m
memory: 64Mi
maxAllowed:
cpu: "4"
memory: 8Gi
# Leggi le raccomandazioni dopo 24-48 ore:
kubectl describe vpa api-service-vpa -n team-alpha
# Output:
# Container Recommendations:
# Container Name: api
# Lower Bound:
# Cpu: 120m
# Memory: 256Mi
# Target: <-- usa questi valori nelle requests
# Cpu: 250m
# Memory: 512Mi
# Upper Bound:
# Cpu: 800m
# Memory: 1500Mi
# Uncapped Target:
# Cpu: 230m
# Memory: 480Mi
Skrypt do zbiorczej analizy Rightsizing
# Trova tutti i Deployment con requests > 2x il consumo reale
kubectl get vpa -A -o json | jq -r '
.items[] |
.metadata.namespace + "/" + .metadata.name + ": " +
(.status.recommendation.containerRecommendations[]? |
"target CPU=" + .target.cpu + " Mem=" + .target.memory)
'
# Script bash per generare report di rightsizing
#!/bin/bash
echo "=== Rightsizing Recommendations ==="
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
echo "--- Namespace: $ns ---"
kubectl get vpa -n "$ns" -o custom-columns=\
"NAME:.metadata.name,\
TARGET-CPU:.status.recommendation.containerRecommendations[0].target.cpu,\
TARGET-MEM:.status.recommendation.containerRecommendations[0].target.memory" \
2>/dev/null
done
Karpenter: Konsolidacja i instancje punktowe
Karpenter optymalizuje koszty w dwóch kierunkach: użytkowania przypadki punktowe dla obniżyć koszt na węzeł o 60-70%, np skonsolidować węzły usunąć te niewykorzystane (pakowanie do pojemników).
NodePool z funkcją Spot i konsolidacją
# karpenter-cost-optimized.yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: cost-optimized
spec:
template:
spec:
nodeClassRef:
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
name: default
requirements:
# Tipi di istanza ottimali per bin-packing (diverse size)
- key: node.kubernetes.io/instance-type
operator: In
values:
- m7i.xlarge # 4 vCPU, 16GB ~$0.20/h on-demand, ~$0.05/h spot
- m7i.2xlarge # 8 vCPU, 32GB
- m7i.4xlarge # 16 vCPU, 64GB
- m7i.8xlarge # 32 vCPU, 128GB
- c7i.2xlarge # CPU-optimized per workload compute-intensive
- r7i.2xlarge # Memory-optimized per carichi con alta RAM
# Mix spot e on-demand con peso
- key: karpenter.sh/capacity-type
operator: In
values:
- spot # priorita spot (economico)
- on-demand # fallback on-demand
disruption:
consolidationPolicy: WhenUnderutilized
consolidateAfter: 1m # consolida subito i nodi sottoutilizzati
limits:
cpu: "1000" # max 1000 vCPU totali
memory: "4000Gi" # max 4TB RAM totale
---
# Configurazione spot interruption handler
# Necessario per gestire le interruzioni spot (AWS invia 2 min di preavviso)
helm install aws-node-termination-handler \
eks/aws-node-termination-handler \
--namespace kube-system \
--set enableSqsTerminationDraining=true \
--set queueURL=https://sqs.eu-west-1.amazonaws.com/123456789/NodeTerminationHandler
Analiza oszczędności z Karpenter
# Verifica quale percentuale dei nodi sono spot
kubectl get nodes -o json | jq '
[.items[] |
{type: .metadata.labels["karpenter.sh/capacity-type"],
instance: .metadata.labels["node.kubernetes.io/instance-type"]}
] |
group_by(.type) |
map({type: .[0].type, count: length})'
# Output esempio:
# [{"type": "on-demand", "count": 3}, {"type": "spot", "count": 12}]
# 80% dei nodi sono spot -> risparmio medio 65% = -$2400/mese
# Kubecost: visualizza costo spot vs on-demand storicamente
# Vai in Cost Allocation > Filter by node type
Budżet przestrzeni nazw: ResourceQuota jako narzędzie FinOps
ResourceQuotas służą nie tylko do izolacji technicznej — są także narzędziem zarządzania finansami. Przypisując kwoty na podstawie budżetów, tworzysz system zachęty, które motywują zespoły do optymalizacji:
# budget-quota-team.yaml
# Calcola le quote basandoti sul budget mensile del team
# Budget: 500 EUR/mese (circa 1500 CPU-hours a 0.033 EUR/CPU-hour)
# Assumendo utilizzo medio 50%: requests max = 2000 CPU-hours / 720 ore = 2.8 vCPU mean
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-alpha-budget-quota
namespace: team-alpha
annotations:
finops/monthly-budget-eur: "500"
finops/last-reviewed: "2026-01-15"
finops/owner: "alice@company.com"
spec:
hard:
# Basato su budget EUR/mese
requests.cpu: "6" # ~500 EUR/mese a tasso medio spot
requests.memory: "12Gi" # proporzionale
requests.storage: "200Gi"
---
# Alert quando il team si avvicina al budget
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: finops-budget-alerts
namespace: monitoring
spec:
groups:
- name: finops
rules:
- alert: TeamBudgetUsageHigh
expr: |
kubecost_namespace_allocation_cpu_cost_hourly * 24 * 30 +
kubecost_namespace_allocation_memory_cost_hourly * 24 * 30 > 400
for: 1h
labels:
severity: warning
annotations:
summary: "Team {{ $labels.namespace }}: costo mensile proiettato > 400 EUR"
Strategie oszczędności dla różnych obciążeń
| Typ obciążenia | Strategia | Oczekiwane oszczędności |
|---|---|---|
| Internetowy interfejs API (bezstanowy) | Punktowy + HPA + prawidłowa wielkość VPA | 50-65% |
| Zadania wsadowe ML | Punkt + punkt kontrolny + skala do zera | 60-70% |
| Bazy danych (stanowe) | Rezerwacja na żądanie + prawidłowa wielkość | 20-30% |
| Biegacze CI/CD | Punktowy + skala do zera (KEDA) | 70-80% |
| Usługi krytyczne 24 godziny na dobę, 7 dni w tygodniu | Zarezerwowane instancje + prawidłowa wielkość | 30-40% |
Optymalizacja zadań CI/CD za pomocą KEDA + Spot
# Runners CI/CD sono idle la maggior parte del tempo:
# scala a 0 quando non ci sono job, usa spot
# KEDA ScaledJob per runner GitHub Actions
apiVersion: keda.sh/v1alpha1
kind: ScaledJob
metadata:
name: github-actions-runner
namespace: actions-runners
spec:
jobTargetRef:
template:
spec:
containers:
- name: runner
image: summerwind/actions-runner:latest
resources:
limits:
cpu: "2"
memory: "4Gi"
nodeSelector:
karpenter.sh/capacity-type: spot # usa spot per runners
tolerations:
- key: "spot"
operator: "Exists"
effect: "NoSchedule"
pollingInterval: 30
minReplicaCount: 0 # scala a 0 quando nessun job
maxReplicaCount: 20 # massimo 20 runner paralleli
triggers:
- type: github-runner
metadata:
owner: "myorg"
repos: "myrepo"
targetWorkflowQueueLength: "1"
Panel FinOps z Grafaną
# PromQL queries per dashboard FinOps Kubernetes
# Costo orario totale del cluster
sum(
kube_pod_container_resource_requests{resource="cpu"} * 0.033 +
kube_pod_container_resource_requests{resource="memory"} / 1073741824 * 0.004
) by (namespace)
# Efficienza CPU per namespace (utilizzo reale / requested)
sum(rate(container_cpu_usage_seconds_total[5m])) by (namespace) /
sum(kube_pod_container_resource_requests{resource="cpu"}) by (namespace) * 100
# Pod con requests molto piu alte del consumo reale (spreco > 70%)
(
kube_pod_container_resource_requests{resource="cpu"} -
rate(container_cpu_usage_seconds_total[24h])
) / kube_pod_container_resource_requests{resource="cpu"} > 0.7
# Importa il dashboard Grafana Kubecost: ID 11270
Najlepsze praktyki FinOps dla Kubernetes
Miesięczna lista kontrolna FinOps
- Przejrzyj zalecenia VPA: Przeanalizuj zalecenia VPA i zastosuj odpowiednie zmiany w przypadku 10 największych odpadów
- Sprawdź bezczynne węzły: Węzły z wykorzystaniem procesora i pamięci < 10% przez 24 godziny muszą zostać zakończone (Karpenter robi to automatycznie)
- Sprawdź zasięg spotu: Celem jest 70–80% węzłów niestanowych w instancjach punktowych
- Raporty dotyczące obciążeń zwrotnych: Wysyłaj miesięczny raport kosztów na zespół poprzez Kubecost API → e-mail lub Slack
- Przejrzyj ResourceQuota: Zwiększaj limity tylko z uzasadnieniem biznesowym, a nie domyślnie
- Skalowanie do zera dla środowisk deweloperskich: Środowiska programistyczne powinny być zamykane poza godzinami pracy (koszt -65%)
Wnioski i dalsze kroki
FinOps dla Kubernetes to nie jednorazowa optymalizacja: to ciągły proces, który wymaga widoczności (Kubecost), inteligentnych rekomendacji (VPA), wydajnego udostępniania (Stolarz z działem handlowym) i zarządzanie organizacją (ResourceQuota jako budżet). Wdrażanie wszystkich tych technik razem organizacje zazwyczaj osiągają oszczędności rzędu 35–55% rachunku za chmurę Kubernetes w ciągu pierwszych 3–6 miesięcy.
Następnym krokiem jest włączenie FinOps Kubernetes do cyklu rozwojowego: programistów powinni poznać szacowany koszt wdrożenia przed przejściem do produkcji — podejście „przesunięcie w lewo” stosowane do kosztów.







