Ein Kubernetes Operator ist ein spezifisches Stück Software, das das Wissen eines menschlichen Operators in einer Software automatisiert. Ein Operator erweitert Kubernetes, um Anwendungen und deren Lebenszyklus auf Kubernetes zu verwalten. Dabei handelt es sich um ein Controller-Pattern, das von Kubernetes CRDs (Custom Resource Definitions) und Controllern verwendet wird.
Ein Kubernetes Operator besteht in der Regel aus drei Hauptkomponenten:
Eine CRD definiert die Struktur und Eigenschaften einer benutzerdefinierten Ressource. Hier ein Beispiel für eine einfache CRD:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: myresources.example.com
spec:
group: example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
name:
type: string
scope: Namespaced
names:
plural: myresources
singular: myresource
kind: MyResource
shortNames:
- mrIn diesem Beispiel definieren wir eine benutzerdefinierte Ressource
MyResource innerhalb der Gruppe example.com.
Die Ressource hat ein Feld name vom Typ
string.
Ein Controller überwacht die benutzerdefinierte Ressource und führt Aktionen durch, um den gewünschten Zustand zu erreichen. Hier ein vereinfachtes Beispiel in Go:
package main
import (
"context"
"fmt"
"os"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
type MyResourceReconciler struct {
client client.Client
scheme *runtime.Scheme
}
func (r *MyResourceReconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
fmt.Println("Reconciling MyResource:", req.Name)
return reconcile.Result{}, nil
}
func main() {
cfg, err := config.GetConfig()
if err != nil {
fmt.Println("Error getting config:", err)
os.Exit(1)
}
mgr, err := manager.New(cfg, manager.Options{})
if err != nil {
fmt.Println("Error creating manager:", err)
os.Exit(1)
}
r := &MyResourceReconciler{
client: mgr.GetClient(),
scheme: mgr.GetScheme(),
}
c, err := controller.New("myresource-controller", mgr, controller.Options{
Reconciler: r,
})
if err != nil {
fmt.Println("Error creating controller:", err)
os.Exit(1)
}
fmt.Println("Starting manager")
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
fmt.Println("Error starting manager:", err)
os.Exit(1)
}
}In diesem Beispiel: