- Authors

- Name
- Phillip Pham
- @ddppham
TL;DR
Ein Kubernetes Operator erweitert die Kubernetes-API um eigene Logik. Mit dem Operator SDK scaffoldest du ein Go-Projekt, definierst eine Custom Resource und implementierst den Reconcile-Loop. Dieser Guide zeigt den kompletten Weg vom leeren Verzeichnis bis zum laufenden Operator am Beispiel eines ConfigMap-Syncers.
Kubernetes Operator mit Go entwickeln
Operators sind das mächtigste Erweiterungskonzept in Kubernetes. Sie kombinieren Custom Resource Definitions (CRDs) mit einem Controller, der auf Änderungen reagiert und den gewünschten Zustand herstellt. Statt kubectl-Skripte zu pflegen, codierst du operatives Wissen direkt in den Cluster.
Prüfe zuerst die Voraussetzungen:
# Go 1.22+, Operator SDK 1.38+, kubectl
go version
operator-sdk version
kubectl cluster-info
Das Operator-Pattern
Ein Operator besteht aus zwei Teilen: einer Custom Resource Definition (CRD), die dein API-Objekt beschreibt, und einem Controller, der den Reconcile-Loop ausführt. Der Controller beobachtet die Custom Resources und gleicht den Ist-Zustand mit dem Soll-Zustand ab — genau wie ein eingebauter Kubernetes-Controller.
Der Reconcile-Loop läuft bei jeder Änderung an der Custom Resource, bei Änderungen an abhängigen Objekten und periodisch als Requeue. Idempotenz ist dabei Pflicht: Jeder Reconcile-Durchlauf muss ohne Seiteneffekte wiederholbar sein.
Projekt scaffolden
Das Operator SDK generiert die komplette Projektstruktur:
mkdir configmap-syncer && cd configmap-syncer
# Projekt initialisieren
operator-sdk init \
--domain kubernetes-administration.de \
--repo github.com/example/configmap-syncer
# API und Controller generieren
operator-sdk create api \
--group sync \
--version v1alpha1 \
--kind ConfigMapSync \
--resource --controller
Das erzeugt folgende Struktur:
| Verzeichnis | Inhalt |
|---|---|
api/v1alpha1/ | CRD-Typen (Go Structs) |
internal/controller/ | Reconcile-Logik |
config/crd/ | Generierte CRD-Manifeste |
config/rbac/ | RBAC-Rollen für den Operator |
CRD definieren
Bearbeite api/v1alpha1/configmapsync_types.go. Die Spec beschreibt, was der Operator tun soll — hier: eine ConfigMap in mehrere Namespaces synchronisieren.
type ConfigMapSyncSpec struct {
// SourceNamespace ist der Namespace der Quell-ConfigMap
SourceNamespace string `json:"sourceNamespace"`
// SourceName ist der Name der Quell-ConfigMap
SourceName string `json:"sourceName"`
// TargetNamespaces sind die Ziel-Namespaces
TargetNamespaces []string `json:"targetNamespaces"`
}
type ConfigMapSyncStatus struct {
// SyncedNamespaces zeigt erfolgreich synchronisierte Namespaces
SyncedNamespaces []string `json:"syncedNamespaces,omitempty"`
// LastSyncTime ist der Zeitpunkt der letzten Synchronisierung
LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"`
}
Nach der Änderung generierst du die CRD-Manifeste neu:
make manifests
make generate
Reconcile-Loop implementieren
Der Kern des Operators liegt in internal/controller/configmapsync_controller.go. Hier die vollständige Reconcile-Funktion:
func (r *ConfigMapSyncReconciler) Reconcile(
ctx context.Context, req ctrl.Request,
) (ctrl.Result, error) {
log := log.FromContext(ctx)
// 1. Custom Resource laden
var syncRes syncv1alpha1.ConfigMapSync
if err := r.Get(ctx, req.NamespacedName, &syncRes); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// 2. Quell-ConfigMap holen
var sourceCM corev1.ConfigMap
sourceKey := types.NamespacedName{
Namespace: syncRes.Spec.SourceNamespace,
Name: syncRes.Spec.SourceName,
}
if err := r.Get(ctx, sourceKey, &sourceCM); err != nil {
log.Error(err, "Quell-ConfigMap nicht gefunden")
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
}
// 3. In jeden Ziel-Namespace synchronisieren
synced := []string{}
for _, ns := range syncRes.Spec.TargetNamespaces {
targetCM := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: sourceCM.Name,
Namespace: ns,
},
}
result, err := controllerutil.CreateOrUpdate(
ctx, r.Client, targetCM,
func() error {
targetCM.Data = sourceCM.Data
targetCM.Labels = map[string]string{
"managed-by": "configmap-syncer",
}
return nil
},
)
if err != nil {
log.Error(err, "Sync fehlgeschlagen", "namespace", ns)
continue
}
log.Info("ConfigMap synchronisiert",
"namespace", ns, "result", result)
synced = append(synced, ns)
}
// 4. Status aktualisieren
now := metav1.Now()
syncRes.Status.SyncedNamespaces = synced
syncRes.Status.LastSyncTime = &now
if err := r.Status().Update(ctx, &syncRes); err != nil {
return ctrl.Result{}, err
}
return ctrl.Result{RequeueAfter: 5 * time.Minute}, nil
}
Wichtig: CreateOrUpdate ist idempotent. Existiert die ConfigMap bereits, wird sie aktualisiert. Existiert sie nicht, wird sie erstellt. Der RequeueAfter sorgt für periodische Synchronisation.
Operator deployen
Baue das Image und deploye den Operator im Cluster:
# Image bauen
make docker-build IMG=ghcr.io/example/configmap-syncer:v0.1.0
# In einen Cluster mit lokaler Registry laden (z.B. kind)
kind load docker-image ghcr.io/example/configmap-syncer:v0.1.0
# CRDs installieren und Operator deployen
make install
make deploy IMG=ghcr.io/example/configmap-syncer:v0.1.0
Teste den Operator mit einer Custom Resource:
apiVersion: sync.kubernetes-administration.de/v1alpha1
kind: ConfigMapSync
metadata:
name: app-config-sync
namespace: default
spec:
sourceNamespace: default
sourceName: app-config
targetNamespaces:
- staging
- production
- monitoring
kubectl apply -f config/samples/sync_v1alpha1_configmapsync.yaml
kubectl get configmapsync
kubectl describe configmapsync app-config-sync
Best Practices für Operator-Entwicklung
Finalizer einsetzen: Wenn dein Operator externe Ressourcen erstellt, brauchst du einen Finalizer zum Aufräumen. Registriere ihn im Reconcile-Loop und entferne ihn erst nach dem Cleanup.
Owner References nutzen: Setze die Custom Resource als Owner der erstellten Objekte. Kubernetes löscht abhängige Objekte dann automatisch per Garbage Collection.
RBAC minimal halten: Der generierte config/rbac/role.yaml enthält oft zu breite Berechtigungen. Beschränke den Operator auf die Ressourcen und Verben, die er tatsächlich braucht.
FAQ
Brauche ich Go für einen Kubernetes Operator?
Nein. Neben Go unterstützt das Operator SDK auch Ansible und Helm als Operator-Basis. Für volle Kontrolle über den Reconcile-Loop ist Go aber die beste Wahl, da die meisten Kubernetes-Libraries in Go geschrieben sind.
Wie debugge ich einen Operator lokal?
Starte den Controller außerhalb des Clusters mit make run. Er verbindet sich über deine kubeconfig und führt den Reconcile-Loop lokal aus. Das ermöglicht normales Go-Debugging mit Breakpoints.
Was passiert bei einem Fehler im Reconcile-Loop?
Der Controller-Runtime requeued das Objekt automatisch mit exponentiellem Backoff. Du kannst auch explizit ctrl.Result{RequeueAfter: duration} zurückgeben, um den nächsten Versuch zu steuern.
Wie teste ich einen Operator?
Das Operator SDK generiert ein internal/controller/suite_test.go mit envtest-Setup. Envtest startet einen lokalen API-Server ohne etcd und ermöglicht Integration-Tests ohne echten Cluster.
Nächster Schritt: Wenn dein Operator produktionsreif ist, veröffentliche ihn auf OperatorHub.io. Das Operator Lifecycle Manager (OLM) übernimmt dann Installation, Updates und Lifecycle-Management automatisch.
Kubernetes-Expertise gesucht?
Managed Services, Beratung, Training oder Security – wir unterstützen deutsche Unternehmen bei allen Kubernetes-Themen.
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
Apache Kafka auf Kubernetes mit Strimzi betreiben
Apache Kafka mit dem Strimzi Operator auf Kubernetes deployen und verwalten. Komplette Anleitung für Cluster, Topics und Skalierung.
PostgreSQL Operator: CloudNativePG vs. Crunchy vs. Zalando
Drei PostgreSQL-Operatoren für Kubernetes im praktischen Vergleich: Features, Failover-Verhalten und Backup-Strategien für produktionsreife Deployments.
Kubernetes in Deutschland: ChromaDB Vector-Store für schnelle KI-Prototypen
ChromaDB Vector-Store für KI-Prototypen auf Kubernetes in Deutschland? Erfahren Sie, wie der deutsche Mittelstand agile RAG-Anwendungen kostengünstig implementiert und dabei bestehende Kubernetes-Ressourcen optimal nutzt.
Kubernetes Zertifizierung im Lebenslauf richtig platzieren
Steigere deine Karrierechancen im deutschen Mittelstand! Erfahre, wie du deine Kubernetes-Zertifikate (CKA, CKAD, CKS) strategisch im Lebenslauf und auf LinkedIn positionierst, um Recruiter von deiner Cloud-Native-Expertise und deinem Praxisbezug zu überzeugen.
KubeCon Europa 2026: Kubernetes Deutschland – Dein ultimativer Guide zum Event
Entdecke, warum die KubeCon Europa 2026 für **Kubernetes Deutschland** und den deutschen Mittelstand entscheidend ist. Dieser ultimative Guide zeigt, wie du maximale Wertschöpfung erzielst, von strategischen Sessions und Networking bis hin zu Compliance-relevanten Einblicken für deine Cloud Native Strategie.