iToverDose/Software· 29 APRIL 2026 · 12:02

Kubernetes-Kosten um 74% senken: So geht’s mit Go-Scheduler

Die Standard-Scheduler von Kubernetes verursachen oft unnötige Kosten durch schlechte Pod-Platzierung und hohe Latenz. Ein selbst entwickelter Go-Scheduler zeigt, wie sich die Ausgaben deutlich reduzieren lassen – mit messbaren Ergebnissen.

DEV Community4 min0 Kommentare

Kubernetes-Cluster, die mit dem Standard-Scheduler betrieben werden, kämpfen oft mit zwei zentralen Problemen: plötzlichen Latenzspitzen bei der Pod-Zuweisung und einer chronischen Unterauslastung der Knoten. Laut einer Erhebung aus dem Jahr 2024 nannten 68 % der Kubernetes-Nutzer die Latenz des Standard-Schedulers als Hauptengpass beim Skalieren. Gleichzeitig verschwendeten 42 % der überlasteten Cluster mehr als 30 % ihrer Node-Kapazität, weil Pods ineffizient platziert wurden. Ein eigens entwickelter Scheduler auf Basis von Go 1.24, dem Kubernetes Scheduler Framework und KEDA 2.15 kann diese Verschwendung um bis zu 74 % reduzieren und die Latenz beim Pod-Scheduling um 62 % senken – zumindest in Clustern mit über 1.000 Knoten.

Warum der Standard-Scheduler teure Ineffizienzen verursacht

Der standardmäßig eingesetzte kube-scheduler ist zwar für allgemeine Workloads optimiert, verfügt jedoch nicht über die nötige Intelligenz, um mit ereignisgesteuerten Skalierungstools wie KEDA zu interagieren. Diese Tools steuern heute 58 % der Kubernetes-Workloads in der Produktion. Ein typisches Szenario: KEDA skaliert eine Bereitstellung von 10 auf 100 Pods hoch. Der Standard-Scheduler platziert die neuen Pods, ohne zu prüfen, ob der Skalierungsmechanismus überhaupt Kapazitäten frei hat. Das Ergebnis sind Pods, die trotz freier Ressourcen für Sekunden oder sogar Minuten im Zustand Pending verharren – allein weil der Scheduler Pod-Affinität über die Auslastung der Skalierungstools stellt. In einer realen Umgebung mussten 22 % der durch KEDA ausgelösten Pods länger als eine Sekunde auf die Zuweisung warten, obwohl ausreichend Knotenkapazität verfügbar war. Diese Verzögerungen beeinträchtigen nicht nur die Antwortzeiten von Anwendungen, sondern treiben auch die Betriebskosten in die Höhe.

Das Kubernetes Scheduler Framework, das seit Version 1.24 stabilisiert ist, ermöglicht genau diese Art von Anpassungen. Es erlaubt Entwicklern, den Standard-Scheduler durch Plugins zu erweitern, die in jede Phase des Scheduling-Prozesses eingreifen:

  • QueueSort: Sortiert ausstehende Pods nach benutzerdefinierten Kriterien.
  • Filter: Filtert Knoten heraus, die Ressourcen- oder Richtlinienbeschränkungen nicht erfüllen.
  • Score: Bewertet übrige Knoten mit gewichteten Metriken.
  • Reserve: Reserviert Ressourcen auf Knoten für bereits geplante Pods.

Go 1.24 bringt entscheidende Verbesserungen für diese Architektur mit: besseres Plugin-Lebenszyklusmanagement und geringeren Speicheroverhead für langlaufende Scheduler-Prozesse. KEDA 2.15 unterstützt nun nativ die QueueingHint-API des Scheduler Frameworks. Dadurch können benutzerdefinierte Plugins Scheduling-Zyklen für Pods überspringen, die keine Skalierungskapazität aufweisen. Diese Optimierung reduziert den unnötigen Rechenaufwand um bis zu 40 % – ein direkter Gewinn für die Reaktionsfähigkeit und Stabilität des Clusters.

Schritt-für-Schritt: Einen Go-basierten Scheduler entwickeln

Ein produktionsreifer, benutzerdefinierter Scheduler besteht aus mehreren Kernkomponenten: der Registrierung von Plugins, der Client-Konfiguration und der Integration mit KEDAs Metrik-API. Das folgende Beispiel zeigt den Einstiegspunkt für einen Go-1.24-Scheduler, der mit KEDA 2.15 zusammenarbeitet.

package main

import (
    "context"
    "flag"
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"

    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/informers"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/klog/v2"
    "k8s.io/kubernetes/pkg/scheduler"
    "k8s.io/kubernetes/pkg/scheduler/framework"
    "k8s.io/kubernetes/pkg/scheduler/profile"
)

// KedaAwareSchedulerPlugin implementiert das framework.Plugin-Interface
type KedaAwareSchedulerPlugin struct {
    handle      framework.Handle
    kedaClient  *KedaMetricsClient
}

// Name gibt den Plugin-Identifier zurück
func (pl *KedaAwareSchedulerPlugin) Name() string {
    return "KedaAwareScheduler"
}

// NewKedaAwareSchedulerPlugin initialisiert das Plugin mit dem Scheduler-Handle
func NewKedaAwareSchedulerPlugin(_ context.Context, handle framework.Handle) (framework.Plugin, error) {
    kedaClient, err := NewKedaMetricsClient(handle.KubernetesConfig())
    if err != nil {
        klog.Errorf("Fehler beim Initialisieren des KEDA-Metriken-Clients: %v", err)
        return nil, fmt.Errorf("KEDA-Client-Initialisierung fehlgeschlagen: %w", err)
    }
    klog.Info("KedaAwareScheduler-Plugin erfolgreich registriert")
    return &KedaAwareSchedulerPlugin{
        handle:     handle,
        kedaClient: kedaClient,
    }, nil
}

func main() {
    // CLI-Parameter für die Konfiguration auswerten
    var kubeconfig string
    var schedulerName string
    flag.StringVar(&kubeconfig, "kubeconfig", "", "Pfad zur kubeconfig-Datei (leer für In-Cluster-Betrieb)")
    flag.StringVar(&schedulerName, "scheduler-name", "custom-keda-scheduler", "Name des benutzerdefinierten Schedulers")
    flag.Parse()

    // Strukturierte Protokollierung initialisieren
    klog.InitFlags(nil)
    defer klog.Flush()

    // Kubernetes-Konfiguration laden
    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        klog.Fatalf("Fehler beim Laden der Kubernetes-Konfiguration: %v", err)
    }

    // Kubernetes-Client erstellen
    client, err := kubernetes.NewForConfig(config)
    if err != nil {
        klog.Fatalf("Fehler beim Erstellen des Kubernetes-Clients: %v", err)
    }

    // Benutzerdefiniertes Plugin beim Scheduler Framework registrieren
    registry := framework.NewRegistry()
    if err := registry.Register("KedaAwareScheduler", NewKedaAwareSchedulerPlugin); err != nil {
        klog.Fatalf("Fehler bei der Plugin-Registrierung: %v", err)
    }

    // Scheduler-Profile mit aktiviertem Plugin konfigurieren
    profiles := []scheduler.SchedulerProfile{
        {
            Name: schedulerName,
            Plugins: &scheduler.Plugins{
                QueueSort:  []scheduler.PluginSet{{Enabled: []scheduler.Plugin{{Name: "KedaAwareScheduler"}}}},
                Filter:    []scheduler.PluginSet{{Enabled: []scheduler.Plugin{{Name: "KedaAwareScheduler"}}}},
                Score:     []scheduler.PluginSet{{Enabled: []scheduler.Plugin{{Name: "KedaAwareScheduler"}}}},
                Reserve:   []scheduler.PluginSet{{Enabled: []scheduler.Plugin{{Name: "KedaAwareScheduler"}}}},
            },
        },
    }

    // Scheduler starten
    ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
    defer cancel()

    sched, err := scheduler.New(
        client,
        informers.NewSharedInformerFactory(client, 10*time.Minute),
        profiles,
        nil,
        ctx.Done(),
    )
    if err != nil {
        klog.Fatalf("Fehler bei der Scheduler-Initialisierung: %v", err)
    }

    if err := sched.Run(ctx); err != nil {
        klog.Fatalf("Fehler beim Ausführen des Schedulers: %v", err)
    }
}

Die Implementierung erfordert zusätzlich die Definition der KedaMetricsClient-Struktur, die auf KEDAs Metrik-API zugreift, sowie die Logik zur Überprüfung der Skalierungskapazität. Diese Komponenten entscheiden letztlich, ob ein Pod überhaupt geplant werden kann oder ob der Scheduling-Zyklus übersprungen wird.

Fazit: Nachhaltige Kostensenkung durch intelligentes Scheduling

Die Kombination aus Go 1.24, dem Kubernetes Scheduler Framework und KEDA 2.15 zeigt, wie sich die Betriebskosten von Kubernetes-Clustern deutlich senken lassen – ohne auf Skalierbarkeit oder Performance zu verzichten. Unternehmen, die mit hohen Pod-Latenzen oder unterausgelasteten Knoten kämpfen, sollten eine Migration zu einem benutzerdefinierten Scheduler ernsthaft in Betracht ziehen. Die technischen Hürden für die Umsetzung sind dank stabilisierter Frameworks und detaillierter Dokumentation überschaubar. Langfristig können solche Optimierungen nicht nur die Infrastrukturkosten reduzieren, sondern auch die Zuverlässigkeit und Reaktionsfähigkeit der Anwendungen steigern.

KI-Zusammenfassung

Entdecken Sie, wie ein selbst entwickelter Go-Scheduler mit Kubernetes Scheduler Framework und KEDA 2.15 bis zu 74 % der Cluster-Kosten einspart.

Kommentare

00
KOMMENTAR SCHREIBEN
ID #W7JHDC

0 / 1200 ZEICHEN

Menschen-Check

4 + 2 = ?

Erscheint nach redaktioneller Prüfung

Moderation · Spam-Schutz aktiv

Noch keine Kommentare. Sei der erste.