Veröffentlicht am

OpenCost: Kubernetes-Kosten pro Team aufschlüsseln

Teilen:
Authors

Kubernetes OpenCost: Open-Source FinOps und Kostenallokation fuer Teams

TL;DR

  • OpenCost ist ein CNCF-Sandbox-Projekt, das Kubernetes-Kosten in Echtzeit pro Namespace, Label, Pod und Container aufschluesselt -- vollstaendig Open Source und ohne Lizenzkosten.
  • Die Installation erfolgt per Helm mit nativer Prometheus-Integration. OpenCost liest Node-Preise, Resource Requests und tatsaechliche Nutzung und berechnet daraus Kosten pro Workload.
  • Cloud-Preise fuer AWS, Azure und GCP werden automatisch abgerufen. Fuer On-Prem-Cluster lassen sich Custom-Preise konfigurieren.
  • Grafana-Dashboards und die OpenCost-API ermoeglichen Showback-Reports pro Team, Abteilung oder Projekt.
  • Im Vergleich zu Kubecost deckt OpenCost den Kern-Anwendungsfall ab -- Kostenallokation und -transparenz -- ohne die Enterprise-Features und deren Kosten.

Warum Kostentransparenz in Kubernetes schwierig ist

In einer klassischen VM-Welt ist die Kostenzuordnung einfach: VM gehoert Team A, Team A zahlt. In Kubernetes teilen sich dutzende Teams denselben Cluster. Ein Node kostet 500 Euro pro Monat, aber darauf laufen Pods von fuenf verschiedenen Teams mit unterschiedlichem Ressourcenverbrauch.

Die Herausforderungen:

  • Shared Resources: Nodes, Load Balancer, Persistent Volumes und Ingress-Controller werden geteilt.
  • Dynamische Allokation: Pods werden erstellt, skaliert und geloescht. Die Zuordnung aendert sich staendig.
  • Request vs. Usage: Ein Pod reserviert 2 CPU, nutzt aber nur 0.3 CPU. Wer zahlt die ungenutzten 1.7 CPU?
  • Idle Costs: Nicht zugeordnete Kapazitaet muss fair verteilt werden.

OpenCost loest diese Probleme mit einem transparenten, Open-Source-Ansatz. Mehr zum Thema Kostenoptimierung: Kubernetes Kosten-Optimierung Praxis-Guide.

Installation via Helm

Voraussetzung: Ein laufender Prometheus im Cluster (kube-prometheus-stack oder standalone).

# Helm-Repository hinzufuegen
helm repo add opencost https://opencost.github.io/opencost-helm-chart
helm repo update

# Installation mit Prometheus-Endpoint
helm install opencost opencost/opencost \
  --namespace opencost \
  --create-namespace \
  --set opencost.prometheus.internal.serviceName=prometheus-kube-prometheus-prometheus \
  --set opencost.prometheus.internal.namespaceName=monitoring \
  --set opencost.prometheus.internal.port=9090 \
  --set opencost.ui.enabled=true

Nach der Installation:

# Status pruefen
kubectl get pods -n opencost

# UI per Port-Forward zugaenglich machen
kubectl port-forward -n opencost svc/opencost 9090:9090

# API testen
curl http://localhost:9090/allocation/compute \
  -d window=24h \
  -d aggregate=namespace \
  -d step=1h

Die OpenCost-UI zeigt sofort die Kostenaufschluesselung nach Namespace, Controller und Pod.

Prometheus-Integration: Welche Metriken OpenCost nutzt

OpenCost liest keine eigenen Metriken, sondern nutzt bestehende Prometheus-Daten:

MetrikQuelleZweck
node_cpu_hourly_costOpenCost ExporterCPU-Preis pro Node
node_ram_hourly_costOpenCost ExporterRAM-Preis pro Node
node_gpu_hourly_costOpenCost ExporterGPU-Preis pro Node
container_cpu_allocationcAdvisorCPU-Requests pro Container
container_memory_allocation_bytescAdvisorRAM-Requests pro Container
container_cpu_usage_seconds_totalcAdvisorTatsaechliche CPU-Nutzung
container_memory_working_set_bytescAdvisorTatsaechlicher RAM-Verbrauch
kubecost_pv_infoOpenCost ExporterPersistent Volume Kosten

OpenCost exportiert zusaetzlich die Node-Preise, die es von der Cloud-API oder aus Custom-Pricing-Konfigurationen bezieht.

# Prometheus ServiceMonitor fuer OpenCost
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: opencost
  namespace: opencost
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: opencost
  endpoints:
    - port: http
      interval: 30s
      path: /metrics

Kostenallokation pro Namespace, Label und Team

Die maechtigste Funktion: Kosten nach beliebigen Dimensionen aggregieren.

Per Namespace

# Kosten der letzten 7 Tage, aggregiert nach Namespace
curl -s "http://localhost:9090/allocation/compute?window=7d&aggregate=namespace" | \
  python3 -m json.tool

Beispiel-Output:

production:    CPU 245.60 EUR  RAM 189.30 EUR  PV 45.00 EUR  Total 479.90 EUR
staging:       CPU  62.40 EUR  RAM  48.20 EUR  PV 12.00 EUR  Total 122.60 EUR
monitoring:    CPU  31.20 EUR  RAM  95.60 EUR  PV 80.00 EUR  Total 206.80 EUR
__idle__:      CPU 112.80 EUR  RAM  67.90 EUR  PV  0.00 EUR  Total 180.70 EUR

Per Label (Team-Zuordnung)

Die empfohlene Methode: Ein Label wie team oder cost-center an alle Workloads vergeben.

# Deployment mit Kosten-Labels
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
  namespace: production
  labels:
    app: order-service
    team: commerce
    cost-center: cc-4200
spec:
  template:
    metadata:
      labels:
        app: order-service
        team: commerce
        cost-center: cc-4200
    spec:
      containers:
        - name: order-service
          image: registry.example.com/order-service:v2.3.1
          resources:
            requests:
              cpu: 500m
              memory: 512Mi
            limits:
              cpu: "1"
              memory: 1Gi
# Kosten nach Team aggregieren
curl -s "http://localhost:9090/allocation/compute?window=30d&aggregate=label:team"

# Kosten nach Cost-Center aggregieren
curl -s "http://localhost:9090/allocation/compute?window=30d&aggregate=label:cost-center"

Fuer die Durchsetzung von Labels per Policy: Kubernetes Resource Management.

Cloud-Kosten-Integration

AWS

# values.yaml fuer AWS-Preise
opencost:
  exporter:
    cloudProviderApiKey: ""
    defaultClusterId: "production-eks"
    aws:
      enabled: true
      spotDataRegion: "eu-central-1"
      spotDataBucket: "my-cur-bucket"
      spotDataPrefix: "cur-reports"
      accountId: "123456789012"

Azure

opencost:
  exporter:
    cloudProviderApiKey: ""
    defaultClusterId: "production-aks"
    azure:
      enabled: true
      subscriptionId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

On-Premises Custom Pricing

Fuer Bare-Metal- oder private Cloud-Cluster:

# custom-pricing.yaml als ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: opencost-custom-pricing
  namespace: opencost
data:
  default.json: |
    {
      "provider": "custom",
      "description": "On-Prem Rechenzentrum Frankfurt",
      "CPU": "0.031",
      "RAM": "0.004",
      "GPU": "0.95",
      "storage": "0.00012",
      "spotCPU": "0.015",
      "spotRAM": "0.002",
      "zoneNetworkEgress": "0.01",
      "regionNetworkEgress": "0.01",
      "internetNetworkEgress": "0.12"
    }
kubectl apply -f custom-pricing.yaml

# Helm-Upgrade mit Custom-Pricing
helm upgrade opencost opencost/opencost \
  --namespace opencost \
  --set opencost.exporter.cloudProviderApiKey="" \
  --set opencost.customPricing.enabled=true \
  --set opencost.customPricing.configmapName=opencost-custom-pricing

Grafana-Dashboards

OpenCost liefert Prometheus-Metriken, die direkt in Grafana visualisiert werden koennen. Dashboards lassen sich per ConfigMap mit dem Label grafana_dashboard: "true" automatisch provisionieren.

Nuetzliche PromQL-Queries fuer eigene Panels:

# Tageskosten pro Namespace
sum(rate(opencost_allocation_cost_total{}[24h])) by (namespace) * 86400

# CPU-Effizienz pro Team (Nutzung vs. Request)
sum(container_cpu_usage_seconds_total{}) by (label_team)
  /
sum(container_cpu_allocation{}) by (label_team) * 100

# Top 10 teuerste Deployments
topk(10, sum(opencost_allocation_cost_total{}) by (controller))

Fuer die vollstaendige Monitoring-Strategie: Kubernetes Monitoring und Observability.

Showback-Reports und Budget-Alerts

Automatisierte Showback-Reports

#!/bin/bash
# showback-report.sh - Monatlicher Kostenbericht pro Team

MONTH=$(date -d "last month" +%Y-%m)
WINDOW="lastmonth"

echo "=== Kubernetes Kostenbericht $MONTH ==="

curl -s "http://opencost.opencost:9090/allocation/compute?window=$WINDOW&aggregate=label:team" | \
  python3 -c "
import json, sys
data = json.load(sys.stdin)
for entry in data.get('data', []):
    for team, costs in entry.items():
        total = costs.get('totalCost', 0)
        cpu = costs.get('cpuCost', 0)
        ram = costs.get('ramCost', 0)
        pv = costs.get('pvCost', 0)
        print(f'{team:20s}  CPU: {cpu:8.2f} EUR  RAM: {ram:8.2f} EUR  PV: {pv:8.2f} EUR  Total: {total:8.2f} EUR')
"

Budget-Alerts mit Prometheus

# PrometheusRule fuer Kosten-Alerts
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: opencost-budget-alerts
  namespace: monitoring
spec:
  groups:
    - name: opencost.budget
      rules:
        - alert: NamespaceBudgetExceeded
          expr: |
            sum(opencost_allocation_cost_total{}) by (namespace) > 1000
          for: 1h
          labels:
            severity: warning
          annotations:
            summary: "Namespace {{ $labels.namespace }} ueberschreitet Budget"
            description: "Kosten: {{ $value | humanize }} EUR (Budget: 1000 EUR)"
        - alert: ClusterCostAnomaly
          expr: |
            sum(rate(opencost_allocation_cost_total{}[1h])) * 720
            > 1.3 * sum(rate(opencost_allocation_cost_total{}[7d])) * 720
          for: 2h
          labels:
            severity: warning
          annotations:
            summary: "Cluster-Kosten 30% ueber Durchschnitt"

OpenCost vs. Kubecost: Vergleich

FeatureOpenCostKubecost FreeKubecost Enterprise
LizenzApache 2.0Proprietaer (Free Tier)Proprietaer
KostenallokationJaJaJa
Cloud-Kosten-IntegrationJaBegrenztJa (Out-of-Cluster)
Custom PricingJaJaJa
Multi-ClusterNein (pro Cluster)NeinJa
Savings RecommendationsNeinBegrenztJa
RBAC-basierte ReportsNein (API-basiert)NeinJa
SSO-IntegrationNeinNeinJa
Long-Term StoragePrometheus/ThanosEigener BackendEigener Backend
SupportCommunityCommunityKommerziell

Empfehlung: OpenCost reicht fuer die meisten Mittelstands-Teams, die Kostentransparenz und Team-Zuordnung brauchen. Kubecost Enterprise lohnt sich bei Multi-Cluster-Setups und dem Bedarf an automatischen Optimierungsempfehlungen.

Weitere FinOps-Strategien: Kubernetes Cost Management FinOps.

Best Practices

  1. Labels konsequent setzen: Ohne Labels wie team, cost-center oder project keine sinnvolle Zuordnung. Admission Controller (OPA Gatekeeper, Kyverno) koennen Labels erzwingen.

  2. Requests realistisch setzen: OpenCost berechnet Kosten primaer anhand von Resource Requests. Ueberdimensionierte Requests fuehren zu hohen zugeordneten Kosten, auch wenn die tatsaechliche Nutzung niedrig ist.

  3. Idle Costs verteilen: Die nicht zugeordneten Kosten sollten anteilig auf die Teams umgelegt werden -- sonst optimiert niemand.

  4. Monatliche Reviews einfuehren: Showback-Reports allein aendern nichts. Ein monatliches Review mit den Team-Leads schafft Bewusstsein und Handlungsdruck.

  5. Prometheus-Retention beachten: OpenCost nutzt historische Metriken. Die Default-Retention von 15 Tagen reicht fuer Monatsberichte nicht. Mindestens 45 Tage konfigurieren oder Thanos fuer Long-Term-Storage nutzen.

Verwandte Artikel


Wenn ihr OpenCost in eurem Cluster einfuehren wollt oder Unterstuetzung bei der FinOps-Strategie und Kostenallokation braucht, meldet euch unter /kontakt -- wir helfen von der Installation bis zu den monatlichen Showback-Reports.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen