Cloud native | Ausführliche Erläuterung der Entwicklung und Anwendung des Kubernetes Operators im Projekt

Inhaltsverzeichnis

1. Nutzungsszenarien

(1) Verarbeitungslogik im Client-Go

(2) Verarbeitungslogik in der Controller-Laufzeit

2. Verwenden Sie Controller-Runtime, um Bedienerprojekte zu entwickeln

(1) Framework-Code generieren

(2) Definieren Sie das crd-Feld

(3) CRD-Datei generieren

(4) Initialisieren Sie den Manager

(5) Konfigurieren Sie den Controller

(6) Webhook konfigurieren


1. Nutzungsszenarien

Controller-Runtime ist ein Framework, das vom Kubernetes-Controller-Modell abgeleitet ist. Ein Regelkreis ist ein nicht endender Regelkreis, der zur Regelung des Systemzustands dient. Ein Controller verfolgt mindestens einen Typ von Kubernetes-Ressourcen. Diese Objekte verfügen über ein Spezifikationsfeld, das den gewünschten Zustand darstellt. Der Controller der Ressource ist dafür verantwortlich, sicherzustellen, dass ihr aktueller Zustand dem gewünschten Zustand nahe kommt.

Daraus können wir schließen, dass bei der Entwicklung der Controller-Laufzeit die folgenden Punkte beachtet werden müssen.

  1. Controller-Laufzeit muss das Kubernetes-Objekt kontinuierlich überwachen. (implementiert durch den Listen-/Überwachungsmechanismus)

  2. Die Controller-Laufzeit muss bestimmte Mechanismen bereitstellen, um den Status (tatsächlichen Status) des Kubernetes-Objekts aufrechtzuerhalten, bis es mit der Spezifikation (erwarteter Status) übereinstimmt. (umgesetzt durch Reconcile)

(1) Verarbeitungslogik im Client-Go

In client-go wird ein Kubernetes-Objekt in ein Paar Informertypen gekapselt. Der Informertyp umfasst Reflector, DeltaFIFO, Indexer und EventHandler.

  • Reflector: API-Schnittstelle zum Aufrufen von Kubernetes. Der Informant überwacht das Kubernetes-Objekt über zwei Kubernetes-API-Schnittstellen. Wenn das Auflisten/Überwachen fehlschlägt, wird es automatisch erneut auflisten/überwachen

  • Listenschnittstelle: Holen Sie sich die gesamte Menge der im Informer definierten Kubernetes-Objektdaten über http-Anfragen in das deltaFIFO

  • Überwachungsschnittstelle: Starten Sie die Überwachung ab der maximalen lokal gespeicherten Ressourcenversion. Wenn eine Überwachungsanforderung gesendet wird, antwortet der API-Server mit einem Änderungsstream. Diese Änderungen listen die Ergebnisse von Vorgängen (z. B. ADDED, MOD-IFIED, DELETED, BOOKMARK, ERROR) auf, die nach der von Ihnen als Überwachungsanforderungsparameter angegebenen „resourceVersion“ aufgetreten sind.

  • DeltaFIFO: Speichert jedes ausstehende Kubernetes-Objekt. Es gibt zwei Datenstrukturen zum Speichern von Kubernetes-Objekten in DeltaFIFO, eine ist ein eindimensionales Array zum Speichern von Objektschlüsselwerten und die andere ist eine Kartenstruktur zum Speichern von Datenströmen.

  • Warteschlange: Eindimensionales Array, jedes Kubernetes-Objekt entspricht einem Schlüssel (Namespace/Name). Die geänderten Daten, die mehrmals in die Warteschlange eingereiht wurden, werden zusammengeführt und gespeichert, und wenn sie aus der Warteschlange entfernt werden, wird das gesamte Objekt verarbeitet.

  • Elemente: Speichert den Änderungsstrom von Kubernetes-Objekten. (Hinzugefügt, aktualisiert, gelöscht, ersetzt, synchronisiert) Beim Start des Informers werden die Daten kontinuierlich aus dem deltaFIFO zur Verarbeitung gelesen.

  • Indexer: Das vom DeltaFIFO erhaltene Kubernetes-Objekt wird in der Speicherzuordnung gespeichert.

  • EventHandler: Das von DeltaFIFO erhaltene Kubernetes-Objekt wird je nach Änderungsereignistyp des Objekts unterschiedlich verarbeitet. Im Allgemeinen wird der Schlüsselwert an die Arbeitswarteschlange übergeben. Anschließend wird es von einem benutzerdefinierten Controller verarbeitet.

(2) Verarbeitungslogik in der Controller-Laufzeit

Definieren Sie den Informer entsprechend dem zu überwachenden Kubernetes-Objekt

Definieren Sie die EventHandler-Verarbeitungslogik. Speichern Sie den Schlüsselwert im Informer-Eventhandler in der Arbeitswarteschlange. Der Schlüsselwert wird in der Arbeitswarteschlange dedupliziert. Um die gleichzeitige Verarbeitung desselben Objekts in einer Arbeitswarteschlange zu vermeiden.

Nehmen Sie den Schlüsselwert aus der Arbeitswarteschlange und verarbeiten Sie ihn im Abgleich.

Die benutzerdefinierte Struktur implementiert die Reconcile-Methode. Bei dieser Methode wird der Zustand des Kubernetes-Objekts koordiniert, um es näher an den gewünschten Zustand zu bringen.

Einführung in das Controller-Laufzeit-Framework

Einführung in das Controller-Laufzeit-Framework 

Die oberste Ebene der Controller-Laufzeit wird vom Manager gekapselt. manager enthält die folgenden Informationen

  • Cluster: Wird zur Kommunikation mit dem Kubernetes-Cluster verwendet. Enthält die kubeconfig-Konfigurationsinformationen von Kubernetes, die mit dem Apiserver von Kuberenetes verbundenen Clientinformationen, die beim Betreiber registrierten Kubernetes-Objektschemainformationen, die zum Abrufen der RESTMapper-Informationen von gvk und gvr sowie die vom Informer gespeicherten Indexerinformationen verwendet werden Lesen mit Kubernetes-Objekten, Client-Informationen zum Schreiben und Veröffentlichen von Ereignissen.

  • Controller: Wird für die Konfiguration und den Start des Informers sowie für die Definition des Abgleichs verwendet

  • Cache: Cache-Informer-Informationen. Enthält die Definition des Informers und das Lesen von Indexerdaten.

  • Webhook: Wird zum Veröffentlichen von drei Arten von Webhook-Diensten in Kubernetes verwendet.

  • Wahl: Aktiv- und Standby-Konfiguration für den Bediener

  • prometheus: Datendienst zur Veröffentlichung von prometheus

  • Sonde: Definiert den Sondendienst des Betreibers, einschließlich zweier Arten von Sondendaten: Gesundheitssonde und Überlebenssonde

2. Verwenden Sie Controller-Runtime, um Bedienerprojekte zu entwickeln

(1) Framework-Code generieren

Die offizielle Empfehlung besteht darin, das Kubebuilder-Plugin zu verwenden, um das Controller-Laufzeit-Framework automatisch zu generieren.

Projekt-Framework generieren: kubebuilder init --domain demo --plugins=go/v4-alpha

Generieren Sie die API, die dem crd-Objekt von Kubernetes entspricht (das Standardobjekt von Kubernetes kann ignoriert werden): kubebuilder create api --group webapp --version v1 --kind Guestbook

Webhook-Servicecode generieren: kubebuilder create webhook --group webapp --version v1 --kind Guestbook --defaulting --programmatic-validation

Die generierte Codeverzeichnisstruktur ist wie folgt

  • API: Enthält die API-Definition von crd und die Webhook-Datei. Die erforderlichen Felder müssen in „guestbook_types.go“ ergänzt werden. Generieren Sie dann die erforderlichen Dateien über die Befehle im Makefile (die Yaml-Datei, die im Kubernetes-Cluster bereitgestellt werden kann, die Go-Datei, die die in client-go definierte Objektmethode implementiert).

  • bin: Das beim Generieren der Datei verwendete Tool. Controller-Gen (CRD-zugehörige Dateien generieren) und Kustomize (Bereitstellungsdateien für Betreiberprojekte generieren)

  • config: Die Konfigurationsdatei, die bei der Ausführung von kustomize verwendet wird.

  • Controller: Controller-Beispieldatei. Enthält eine benutzerdefinierte Reconcile-Struktur, implementiert die Reconcile-Methode zum Koordinieren von Kubenetes-Ressourcen und definiert die Informer-Methode.

  • Hack: Die Konfigurationsdatei, die verwendet wird, wenn Controller-Gen ausgeführt wird.

  • dockerignore Dockerfile: Operator-Projekt-Image-Datei generieren

  • main.go: Startdatei

  • Makefile: Kapselt einige Make-Befehle. Enthält Befehle zum Generieren von Code, zum Bereitstellen von Bedienerprojektbefehlen usw.

  • PROJEKT: Projektkonfigurationsinformationsdatei, die nach der Ausführung des kubebuider-Befehls generiert wird

(2) Definieren Sie das crd-Feld

Ergänzen Sie die Datei „guestbook_types.go“. In dieser Datei müssen zwei Arten von Daten ergänzt werden.

  • Felder in Struktur

Das gewünschte Statusfeld ist in der Spezifikation definiert. Das eigentliche Statusfeld wird im Status definiert.

Das JSON-Tag nach dem Feld wird verwendet, um das entsprechende Feld der CRD-Datei in Kubernetes zu generieren. omitepty gibt an, ob das Feld erforderlich ist oder nicht.

  • Kubebuilder-Notizen

Wird zum Generieren von CRD-Dateien und Deepcopy-Dateien verwendet, die das in client-go definierte runtime.Object implementieren.

Die Kubebuilder-Anmerkungen auf der offiziellen Website zeigen vier Verwendungsmöglichkeiten von Anmerkungen:

- Validierung (im Feld definiert, wird zum Generieren der Feldvalidierung für CRD-Dateien verwendet)

- Zusätzliche Druckerspalten (definiert in der Struktur, entsprechend spec.ver-sions.additionalPrinterColumns in der crd-Datei)

- Unterressourcen (definiert in der Struktur, entsprechend .spec.version.subresources der crd-Datei)

- Mehrere Versionen (in der Struktur definiert, die angegebene Version ist in der Mehrfachversion definiert, entsprechend der Felddefinition spec.versions.storage in der CRD-Datei)

⚠️Zwischen den in der Struktur definierten Kommentaren und Kommentaren dürfen keine Leerzeilen stehen

(3) CRD-Datei generieren

Führen Sie make manifest aus, um WebhookConfiguration, ClusterRole und Custom-ResourceDefinition zu generieren

  • WebhookConfiguration: Wird gemäß der Annotation //+kubebuilder:webhook generiert, normalerweise in der Datei „guestbook_webhook.go“.
  • ClusterRole: Wird gemäß der Annotation //+kubebuilder:rbac generiert, die im Allgemeinen in der Datei „controllers/guestbook_controller.go“ definiert ist
  • CustomResourceDefinition: Wird gemäß den Dateien „guestbook_types.go“ und „groupversion_in-fo.go“ generiert.

Führen Sie make generic aus , um die Datei zz_generated.deepcopy.go zu generieren

Datei zz_generated.deepcopy.go: implementiert die Methode in runtime.Object für die Typkonvertierung im Client-Go-Abhängigkeitspaket. Generiert gemäß //+kubebuilder:object Annotation.

(4) Initialisieren Sie den Manager

Initialisieren Sie den Manager in der Datei main.go.

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
   Scheme: scheme,
   MetricsBindAddress:     metricsAddr,
   Port:                   9443,
   HealthProbeBindAddress: probeAddr,
   LeaderElection: enableLeaderElection,
   LeaderElectionID: "aefd3536.demo",
})

Controller konfigurieren

if err = (&controllers.GuestbookReconciler{
   Client: mgr.GetClient(),
   Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
   setupLog.Error(err, "unable to create controller", "controller", "Guestbook")
   os.Exit(1)
}

Konfigurieren Sie Webhooks

if err = (&webappv1.Guestbook{}).SetupWebhookWithManager(mgr); err != nil {
   setupLog.Error(err, "unable to create webhook", "webhook", "Guestbook")
   os.Exit(1)
}

Sonde konfigurieren

if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
   setupLog.Error(err, "unable to set up health check")
   os.Exit(1)
}
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
   setupLog.Error(err, "unable to set up ready check")
   os.Exit(1)
}

Start-Manager

if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
   setupLog.Error(err, "problem running manager")
   os.Exit(1)
}

(5) Konfigurieren Sie den Controller

In der Datei „guestbook_controller.go“ sind zwei Methoden definiert.

func (r *GuestbookReconciler) SetupWithManager(mgr ctrl.Manager) error {
   return ctrl.NewControllerManagedBy(mgr).
      For(&webappv1.Guestbook{}).
      WithEventFilter(predicate.Funcs{
         CreateFunc: func(_ event.CreateEvent) bool {
            return false
         },
      }).
      WithOptions(controller.Options{MaxConcurrentReconciles: 2}).
      Complete(r)
}

Wird in der Datei main.go aufgerufen, um den Informer zu definieren und den Informer im Manager zu konfigurieren

  • Kubernetes-Objekt im Informer

Das Framework bietet drei Methoden zum Definieren von Objekttypen:

  • Uhren(source.Source, handler.EventHandler, ...WatchesOption)
  • For(client.Object,...ForOption)
  • Besitzt(client.Object,...OwnsOption)

Unter diesen sind „For“ und „Owns“ gleichbedeutend mit „Watches“. Der zweite Parameter von For ist standardmäßig EnqueueRequestForObject. Der zweite Parameter von Owns ist standardmäßig EnqueueRequestForOwner

Beschreibung der Methodenparameter

  • Quelle: der erste Parameter, der Kubernetes-Objekttyp
  • EventHandler: Der zweite Parameter, die Daten aus dem DeltaFIFO, dem Vorgang, der vor dem Eintritt in die Arbeitswarteschlange ausgeführt wird. EnqueueRequestForObject bedeutet, direkt und ohne Verarbeitung in die Arbeitswarteschlange einzutreten. EnqueueRequestForOwner muss in Verbindung mit der For-Methode verwendet werden. Der Objekttyp, auf den von OwnerReference im Objekt in Owns verwiesen wird, muss mit dem in For definierten Objekttyp identisch sein, und der Controller in OwnerReference muss wahr sein.
  • Prädikat: Der dritte Parameter, die aus der Arbeitswarteschlange entnommenen Daten, der vor der Abgleichsverarbeitung ausgeführte Vorgang. Über den WithEventFilter des Builders können allen Objekten Prädikate hinzugefügt werden.

Beschreibung der EventHandler- und Predicate-Methode

Erstellen: Wird aufgerufen, wenn ein Kubernetes-Objekt hinzugefügt wird

Update: Wird aufgerufen, wenn das Kubernetes-Objekt aktualisiert wird

Löschen: Wird aufgerufen, wenn das Kubernetes-Objekt gelöscht wird

Generisch: Unbekannter Vorgang. Änderungsereignisse für Nicht-Kubernetes-Cluster. Nutzen Sie es selbst im Betreiber

  • Controller-Konfiguration

Die Konfiguration wird über builder.WithOptions definiert. Die folgenden Konfigurationen können im Controller definiert werden.

  • MaxConcurrentReconciles: Daten aus der Arbeitswarteschlange können mit mehreren Coroutinen verarbeitet werden. Standardeinstellung
  • Reconciler: Der Koordinator muss die Reconciler-Methode implementieren. Standardmäßig ist „Reconcile“ in der Datei „guest-book_controller.go“ definiert
  • RateLimiter: Die aktuelle Begrenzungsrichtlinie der Arbeitswarteschlange. Standardmäßig gibt es zwei aktuelle Begrenzungsstrategien. Token-Bucket-Richtlinie (BucketRateLimiter): Die Standardanzahl der Token beträgt 100. Pro Sekunde können 10 Token abgehoben werden. Backoff-Strategie (ItemExponentialFailureRateLimiter): Wenn der Abgleich einen Fehler zurückgibt, betreten Sie die Warteschlange erneut. Die Zeit, das Team das nächste Mal zu verlassen, erhöht sich entsprechend der Exponentialpotenz von 2. Anfänglich 5 ms, maximal 1000 s.
  • LogConstructor: Das aus dem Kontext beim Abgleich erhaltene Protokoll logr. Der Standardwert ist das in mgr definierte Protokoll.
  • CacheSyncTimeout: Zeitüberschreitung bei der Informer-Synchronisierung. Wenn der Informer eine Liste/Überwachung durchführt, ist die Synchronisierung des Informers nur dann erfolgreich, wenn alle von der Listenschnittstelle aufgerufenen Daten mit dem Indexer des Informers synchronisiert sind.
  • RecoverPanic: Legt fest, ob die Wiederherstellung automatisch erfolgen soll, wenn der Abgleich abnormal ist.
func (r *GuestbookReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
   _ = log.FromContext(ctx)
 
   // TODO(user): your logic here
 
   return ctrl.Result{}, nil
}

Die Reconcile-Methode ist eine benutzerdefinierte Logik. Bei der Implementierung benutzerdefinierter Logik müssen Sie den Auswirkungen des Zwischenzustands nicht zu viel Aufmerksamkeit schenken, sondern lediglich sicherstellen, dass der aktuelle Zustand dem gewünschten Zustand so nahe wie möglich kommt. Im Ergebnis des Reconcile-Rückgabewerts können Sie außerdem festlegen, ob erneut in die Warteschlange eingetreten werden soll und wann die Warteschlange aus der Warteschlange entfernt werden soll.

(6) Webhook konfigurieren

Das Framework stellt drei Webhooks bereit:

Säumiger

func (r *Guestbook) Default() {
   guestbooklog.Info("default", "name", r.Name)
 
   // TODO(user): fill in your defaulting logic.
}

Entspricht dem MutatingAdmissionWebhook-Objekt in Kubernetes.

Validator

func (r *Guestbook) ValidateCreate() error {
   guestbooklog.Info("validate create", "name", r.Name)
 
   // TODO(user): fill in your validation logic upon object creation.
   return nil
}
 
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *Guestbook) ValidateUpdate(old runtime.Object) error {
   guestbooklog.Info("validate update", "name", r.Name)
 
   // TODO(user): fill in your validation logic upon object update.
   return nil
}
 
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *Guestbook) ValidateDelete() error {
   guestbooklog.Info("validate delete", "name", r.Name)
 
   // TODO(user): fill in your validation logic upon object deletion.
   return nil
}

Entspricht dem ValidatingWebhookConfiguration-Objekt in Kuberenetes.

Konvertierung.Webhook

Entspricht dem Webhook, der in spec.convertion in crd definiert ist

zentrale Version

// Hub 标注为中心版本
func (r *Guestbook) Hub() {
 
}

andere Versionen

func (r *Guestbook) ConvertTo(dst conversion.Hub) error {
   // todo 当前版本向中心版本转换
   return nil
}
func (r *Guestbook) ConvertFrom(src conversion.Hub) error {
   // todo 中心版本向当前版本转换
   return nil
}

Dann ist das Obige die Entwicklung und Anwendung des k8s-Operators im Projekt, ich hoffe, es wird Ihnen hilfreich sein ~

Dies ist das Ende dieses Teilens. Weitere technische Kenntnisse finden Sie im offiziellen Konto von „Digital China Cloud Base“.

Copyright-Erklärung: Der Artikel wurde vom Team der Digital China Wuhan Cloud Base zusammengestellt und ausgegeben. Bitte geben Sie die Quelle für den Nachdruck an.

Ich denke du magst

Origin blog.csdn.net/CBGCampus/article/details/130614915
Empfohlen
Rangfolge