KubeBuilder erleichtert die Erstellung von Kubernetes Operatoren, indem es Werkzeuge und Bibliotheken bereitstellt, um Custom Resource Definitions (CRDs) und Controller zu erstellen und zu verwalten. Mit KubeBuilder können Sie den gesamten Lebenszyklus einer benutzerdefinierten Ressource verwalten.
Bevor wir anfangen, müssen wir KubeBuilder installieren. Sie können die neueste Version von der offiziellen KubeBuilder GitHub-Seite herunterladen und installieren. Für Unix-Systeme können Sie das folgende Kommando verwenden:
curl -L https://github.com/kubernetes-sigs/kubebuilder/releases/download/v3.2.0/kubebuilder_3.2.0_linux_amd64.tar.gz | tar -xz -C /usr/local/bin/Erstellen wir ein neues KubeBuilder-Projekt. Wir starten damit, ein neues Verzeichnis für unser Projekt zu erstellen und KubeBuilder zu initialisieren:
mkdir my-operator
cd my-operator
kubebuilder init --domain example.com --repo example.com/my-operatorIn diesem Beispiel initialisieren wir ein neues KubeBuilder-Projekt
mit der Domäne example.com und dem Repository
example.com/my-operator.
Nachdem wir das Projekt initialisiert haben, erstellen wir eine neue API und den zugehörigen Controller:
kubebuilder create api --group webapp --version v1 --kind GuestbookDieses Kommando generiert die notwendigen Dateien für eine neue API
namens Guestbook in der Gruppe webapp und
Version v1. Es erstellt auch die grundlegenden Strukturen
für die CRD und den Controller.
Öffnen Sie die Datei api/v1/guestbook_types.go, die die
Struktur unserer benutzerdefinierten Ressource definiert:
package v1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// GuestbookSpec defines the desired state of Guestbook
type GuestbookSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Foo is an example field of Guestbook. Edit guestbook_types.go to remove/update
Foo string `json:"foo,omitempty"`
}
// GuestbookStatus defines the observed state of Guestbook
type GuestbookStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// Guestbook is the Schema for the guestbooks API
type Guestbook struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec GuestbookSpec `json:"spec,omitempty"`
Status GuestbookStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// GuestbookList contains a list of Guestbook
type GuestbookList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Guestbook `json:"items"`
}
func init() {
SchemeBuilder.Register(&Guestbook{}, &GuestbookList{})
}Passen Sie die GuestbookSpec an, um die gewünschten
Felder zu definieren. Beispiel:
// GuestbookSpec defines the desired state of Guestbook
type GuestbookSpec struct {
Size int32 `json:"size"`
}Öffnen Sie die Datei
controllers/guestbook_controller.go, die die Logik des
Controllers enthält. Fügen Sie die Reconcile-Logik hinzu, um die
gewünschte Zustandsänderung zu implementieren:
package controllers
import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/api/errors"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
examplev1 "example.com/my-operator/api/v1"
)
// GuestbookReconciler reconciles a Guestbook object
type GuestbookReconciler struct {
client.Client
Scheme *runtime.Scheme
}
//+kubebuilder:rbac:groups=webapp.example.com,resources=guestbooks,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=webapp.example.com,resources=guestbooks/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=webapp.example.com,resources=guestbooks/finalizers,verbs=update
func (r *GuestbookReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
_ = log.FromContext(ctx)
// Fetch the Guestbook instance
guestbook := &examplev1.Guestbook{}
err := r.Get(ctx, req.NamespacedName, guestbook)
if err != nil {
if errors.IsNotFound(err) {
// Object not found, return. Created objects are automatically garbage collected.
// For additional cleanup logic use finalizers.
return ctrl.Result{}, nil
}
// Error reading the object - requeue the request.
return ctrl.Result{}, err
}
// Implement your business logic here
fmt.Printf("Reconciling Guestbook %s/%s\n", guestbook.Namespace, guestbook.Name)
return ctrl.Result{}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *GuestbookReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&examplev1.Guestbook{}).
Complete(r)
}In diesem Beispiel wird ein Controller definiert, der die
Guestbook-Ressource überwacht und entsprechende Aktionen
durchführt.
Nachdem wir die CRD und den Controller implementiert haben, können wir den Operator erstellen und im Kubernetes-Cluster bereitstellen. Führen Sie die folgenden Kommandos aus:
make install
make runErstellen Sie ein Docker-Image und deployen Sie es in Ihrem Kubernetes-Cluster:
make docker-build docker-push IMG=<your-image-name>
make deploy IMG=<your-image-name>Stellen Sie sicher, dass Sie <your-image-name>
durch den tatsächlichen Namen des Docker-Images ersetzen.