Lasso ist ein Controller-Framework.
Lasso weist eine gewisse funktionale Parität mit dem Controller-Runtime-Projekt auf und könnte anstelle von Controller-Runtime verwendet werden.
Lasso ist auf niedrigem Niveau. Wenn Sie Ihre eigenen Controller verwalten möchten, können Sie es verwenden. Wenn Sie auf der Suche nach mehr Komfort und Funktionalität zum Erstellen eigener Ressourcentypen sind, empfehlen wir Ihnen Wrangler.
Kern-Controller-Framework, das von Wrangler und Norman verwendet wird.
Dieses Dokument wurde für zwei Zielgruppen geschrieben: für jemanden, der mit Kubernetes-Controllern noch nicht vertraut ist, und für jemanden, der mit Kubernetes-Controllern nicht vertraut ist, aber mit Lasso noch nicht vertraut ist.
Wenn Sie in die Kategorie „Jemand, der mit Kubernetes-Controllern nicht neu ist“ fallen, können Sie zu Lassos Wertversprechen springen.
Wenn Sie mit Kubernetes-Controllern noch nicht vertraut sind, wird empfohlen, keinen Abschnitt zu überspringen.
Wenn Ihnen grundlegende Kubernetes-Kenntnisse fehlen, empfiehlt es sich, zunächst andere Dokumentationen zu den Grundlagen zu konsultieren, beispielsweise die Kubernetes-Übersicht.
Hinweis: Dies wird ein sehr kurzer Crashkurs sein. Wir empfehlen Ihnen, nach anderen Ressourcen zu diesem Thema zu suchen, es gibt viele! Zwei empfohlene Ressourcen sind das Sample Controller Project und Introduction To Kubernetes Controller Frameworks.
Aus der Kubernetes-Dokumentation
In Kubernetes ist ein Controller ein Regelkreis, der den gemeinsamen Status des Clusters über den API-Server überwacht und Änderungen vornimmt, um den aktuellen Status in den gewünschten Zustand zu verschieben.
Das Wort „Controller“ wird allgemeiner verwendet, als die obige Definition vermuten lässt. In unseren eigenen Worten: Controller sind Schleifenhandler, die als Reaktion auf Kubernetes-Ressourcenereignisse reagieren. In Lasso verwenden wir das Wort „Controller“ auch, um die gesamte Struktur zu bezeichnen, die für die Registrierung dieses Schleifenhandlers und die Bereitstellung der benötigten Ressourcen verantwortlich ist. Kurz gesagt sind Controller Strukturen, die alles bündeln, was für die Interaktion mit und den Betrieb auf Kubernetes-Typen erforderlich ist.
Um das oben genannte Ziel zu erreichen, müssen einige Unterziele erfüllt werden:
Es gibt viele Frameworks, die dabei helfen, die oben genannten Ziele zu erreichen. Lasso ist einer von ihnen. Den meisten dieser Frameworks, einschließlich Lasso, ist gemeinsam, dass sie die Funktionalität vom Client aus nutzen, um diese Ziele zu erreichen. Sie könnten diese Ziele erreichen, indem Sie einfach client-go verwenden. Im weiteren Verlauf dieses Abschnitts werden wir im Handumdrehen durchgehen, wie ein Controller mithilfe von Client-Go-Konzepten zusammengestellt wird.
Ein Informer wird verwendet, um die oben genannten Ziele zu erreichen, die für einen Kubernetes-Controller erforderlich sind. Ein Informer verfügt über einen Event-Handler und einen Indexer. Der Indexer verfügt über einen Speicher und Zuordnungsfunktionen zum Indizieren von Objekten innerhalb des Speichers, sogenannte Indexer. Die zugrunde liegenden Strukturen sind unterschiedlich, aber zur Veranschaulichung wird unten eine Pseudostruktur gezeigt:
Informer
EventHandler
Indexer
Store
Indexers
Der EventHandler kann unterschiedliche Logik zum Erstellen, Aktualisieren und Löschen von Ereignissen haben. Beim Event-Handler kommt der Controller ins Spiel. Sie verwenden ihn, um die Event-Handler zum Erstellen, Aktualisieren und Löschen zu konfigurieren.
Der Indexer wird als Cache verwendet.
Im Speicher speichert der Indexer Objekte.
Bei den Indexern handelt es sich um Funktionen, mit denen der Indexer persistente Objekte indizieren kann. Nach der Indizierung mit einem Indexer können Objekte mithilfe von Zeichenfolgen abgerufen werden, die ein Merkmal beschreiben, das dem Indexer wichtig ist.
Der Indexer wird häufig verwendet, um ein Objekt anhand einfacher Metadaten wie Namespace und Name abzurufen.
Der Informer füllt zunächst den Indexer, indem er alle von einem Client zurückgegebenen Ressourcen auflistet. Anschließend überwacht der Informant die Kubernetes-Ressource, der er zugewiesen ist. Wenn ein Ereignis eintrifft, verwendet es dieses Ereignis, um seinen Indexer zu aktualisieren und seine Ereignishandler auszuführen.
Normalerweise benötigt eine Anwendung mehrere Controller. Allerdings ist es möglicherweise nicht effizient, wenn jeder Controller seinen eigenen Informer und damit seinen eigenen Indexer hat. Mit dem SharedIndexerInformer von client-go können mehrere Controller hinzugefügt werden, die alle dieselben Indexer verwenden.
Im Kubernetes/Sample-Controller-Repo finden Sie eine großartige Visualisierung, wie ein Kubernetes-Controller funktionieren könnte.
Hinweis: Der Kürze halber wurden Informanten vereinfacht. Wenn Sie genau wissen möchten, wie sie funktionieren, empfehlen wir Ihnen, den Client-Go-Code durchzulesen.
Lasso standardisiert mit seinem Controller-Paket, was ein Controller ist. Lasso führt Fabriken zur Verwaltung von Caches, Controllern und Clients innerhalb eines Projekts ein. Dies ist für Rancher, die viele Instanzen unterschiedlicher Art verwalten, unerlässlich.
Der Lasso-Controller verwendet die Client-Go-Arbeitswarteschlange. Lasso registriert einen Event-Handler, der die Arbeitswarteschlange verarbeitet. Der an der Arbeitswarteschlange orientierte Handler sorgt dafür, dass für jeden Kubernetes-Typ nur ein Ereignishandler hinzugefügt werden muss. Wenn Sie nun einen Handler registrieren, wird er einfach zur Liste der Handler des Controllers des Typs hinzugefügt. Durch das Einreihen in die Warteschlange wird ein Objekt zur Arbeitswarteschlange hinzugefügt. Jedes Objekt in der Arbeitswarteschlange wird dann von Arbeitern verarbeitet, die in Goroutinen ausgeführt werden. Der Ereignishandler des Controllers stellt jedes Objekt erneut in die Warteschlange, das dazu führt, dass einer oder mehrere Handler des Controllers einen Fehler zurückgeben, der nicht vom Typ ErrIgnore
ist. In diese Arbeitswarteschlange können auch Objekte aus anderen Quellen eingereiht werden. Diese Funktionalität wird über die Enqueue-Funktion des Controllers verfügbar gemacht. Dies führt dazu, dass Controller nicht mehr nur auf Kubernetes-Ressourcen und Cache-Neusynchronisierungen reagieren, sondern auch durch Code aufgerufen werden können.
Der Typ sharedController bettet die Controller-Schnittstelle ein, um die Funktionalität seines Controllers verfügbar zu machen. Der sharedController stellt neben der Client-Funktion auch die RegisterHandler-Funktion bereit. RegisterHandler fügt den übergebenen Handler zur Handlerliste des Controllers hinzu und Client gibt einen Client für den entsprechenden Ressourcentyp des sharedControllers zurück. sharedController verfügt über ein GVK-Feld (Group Version Kind), das angibt, für welchen Typ es bestimmt ist.
Der „Shared“-Aspekt beginnt beim primitiveren Lasso-Controller. Die Verwendung einer Arbeitswarteschlange ermöglicht beispielsweise die gemeinsame Nutzung eines Satzes von Event-Handlern. Dann ergänzt der Lasso Shared Controller dies, indem er einen wiederverwendbaren Client für den GVK bereithält und mit RegisterHandler eine Möglichkeit hinzufügt, Handler einfach beim darunter liegenden Controller zu registrieren.
Der sharedController kann seinen zugrunde liegenden Controller erstellen. Dies geschieht erst, wenn ein Handler beim sharedController registriert ist.
Umschließt den Kubernetes-Client. Enthält GVK-Felder zum Verwalten des Clients in einer übergeordneten Struktur wie der sharedClientFactory. Stellt einige zusätzliche Funktionen bereit, z. B. die Konfiguration des User-Agent-Headers für den zugrunde liegenden REST-Client.
Der Lasso-Cache ist ein leichter Wrapper um einen SharedIndexInformer von client-go.
Der Hauptvorteil des Lasso-Cache besteht darin, dass ihm eine Cache-Factory zugewiesen werden kann, die SharedIndexInformer im Speicher durch GVK verwaltet, sodass sie wiederverwendet werden können. Bei Verwendung der Lasso-Cache-Funktionen verwaltet es sich selbst innerhalb der CacheFactory, die zum Erstellen übergeben wurde.
Die Shared Cache Factory speichert die Caches und ermöglicht deren Verwaltung über GVK-Strukturen. Sobald die Caches einmal erstellt wurden, können sie wiederverwendet werden.
Die Shared Client Factory existiert, damit ein Client für einen GVK nach seiner Erstellung wiederverwendet werden kann.
Die SharedControllerFactory verbindet alles oben Genannte miteinander. Es ermöglicht einen einzigen Einstiegspunkt für den Zugriff auf Clients, Caches und Handler, die alles für Sie verwaltet werden. Es ist möglich, hauptsächlich mit der Shared Controller Factory zu interagieren. Es werden alle zugrunde liegenden Controller, Clients und Caches erstellt, die Sie benötigen. Dadurch wird sichergestellt, dass es keine Duplikate dieser Objekte gibt. Dadurch werden Rennbedingungen verhindert.
Sobald Sie ForObject, ForKind, ForResource oder ForResourceKind verwenden, führt SharedControllerFactory Folgendes aus:
Der deferredController ist eine Funktion, die nach ihrer Ausführung einen Controller erstellt und zurückgibt. Der Controller wird mithilfe eines Caches aus der SharedCacheFactory erstellt. Der Zweck der deferredController-Funktion besteht darin, das Auffüllen des Caches so lange zu verzögern, bis es unbedingt erforderlich ist. Dadurch wird sichergestellt, dass nur Kubernetes-Ressourcen im Speicher gespeichert werden, für die Handler registriert sind, die in die Warteschlange gestellt wurden oder deren Controller-Cache angefordert wurde.
Wenn Sie einen sharedController von der SharedControllerFactory erhalten, ist noch kein zugrunde liegender Controller instanziiert. Stattdessen wird die deferredController-Methode aufgerufen, um eine zu erstellen, sobald einer der genannten Vorgänge ausgeführt wird.
Im Folgenden finden Sie die Schritte für eine einfache Möglichkeit, Handler zu registrieren und im Lasso auszuführen:
package main
import (
"context"
"github.com/rancher/lasso/pkg/controller"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
)
func main () {
config , err := clientcmd . BuildConfigFromFlags ( "" , os . Getenv ( "KUBECONFIG" ))
if err != nil {
panic ( err )
}
// Setup types you want to work with
scheme := runtime . NewScheme ()
appsv1 . AddToScheme ( scheme )
controllerFactory , err := controller . NewSharedControllerFactoryFromConfig ( config , scheme )
if err != nil {
panic ( err )
}
// ForObject, ForKind, ForResource, and ForResourceKind can all be used to retrieve the controller.
// They all accept different parameters but the first three all eventually call ForResourceKind.
// Refer to [How to use Lasso](#how-to-use-lasso) for more information on how ForResourceKind works.
sharedController , err := controllerFactory . ForObject ( & appsv1. Deployment {})
if err != nil {
panic ( err )
}
// Register a handler on a shared controller. If you need a dedicated queue then use controller.New()
sharedController . RegisterHandler ( context . TODO (), "my-handler" , controller . SharedControllerHandlerFunc ( func ( key string , obj runtime. Object ) (runtime. Object , error ) {
// obj is the latest version of this obj in the cache and MAY BE NIL when an object is finally deleted
dep , ok := obj .( * appsv1. Deployment )
if ! ok {
return obj , nil
}
// Do some stuff ...
// Get stuff from the cache
sharedController . Informer (). GetStore (). Get ( key )
result := & appsv1. Deployment {}
err := sharedController . Client (). Update ( ctx , dep . Namespace , dep , result , metav1. UpdateOptions {})
// return the latest version of the object
return result , err
}))
// the second, int parameter is the number of workers to be used for EACH controller.
err = controllerFactory . Start ( context . TODO (), 5 )
if err != nil {
panic ( err )
}
}
Einige der Lasso-Tests nutzen zur Ausführung envtest. Envtest ermöglicht die Ausführung von Tests auf einem „gefälschten“ Kubernetes-Server mit geringem oder keinem Overhead.
Um die erforderliche setup-envtest
Binärdatei zu installieren, verwenden Sie den folgenden Befehl:
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
Bevor Sie die Tests ausführen, müssen Sie den folgenden Befehl ausführen, um den gefälschten Server einzurichten:
# note that this will use a new/latest version of k8s. Our CI will run against the version of k8s that corresponds to lasso's
# current client-go version, as seen in scripts/test.sh
export KUBEBUILDER_ASSETS= $( setup-envtest use -p path )
Die folgenden Ressourcen waren beim Schreiben dieser Dokumente hilfreich. Sie werden wärmstens empfohlen, wenn Sie mehr lernen möchten als das, was hier vorgestellt wird: