Kubernetes Operatörleri: CRD, Denetleyici Kalıbı ve Operatör SDK'sı
Üretimde PostgreSQL kümesini nasıl yönetirsiniz? Birincil olanı izlemeli, tespit etmelisin hatalar, bir kopyanın tanıtılması, yapılandırmaların güncellenmesi, yedeklemelerin gerçekleştirilmesi Sertifikaların rotasyonunu planlayın ve yönetin. Bunlar uzman bir DBA'nın yapacağı işlemlerdir. Nasıl yapılacağını ezbere bilir, ancak her zaman bir şeyler ters gittiğinde saatlerce el emeği gerektirir sabah saat 3'te çarpık.
Desen Kubernetes Operatörü bu bilgiyi kodlamanıza olanak tanır Kubernetes yerel yazılımında çalışır durumdadır: kümenin durumunu gözlemleyen bir denetleyici, İstenilen durumla karşılaştırır ve bunları uzlaştırmak için gerekli önlemleri alır. Otomatik olarak. Sürekli. İnsan müdahalesi olmadan. Bu yazıda inşa edeceğiz Operatör SDK'sını ve Kubebuilder'ı kullanan, denetleyiciyi iyice anlayan eksiksiz bir Operatör desen ve uzlaştırma döngüsü.
Ne Öğreneceksiniz
- Kubernetes Operatörü nedir ve bir tane oluşturmak ne zaman mantıklıdır?
- Özel Kaynak Tanımı (CRD): şema, sürüm oluşturma, doğrulama
- Denetleyici Deseni ve Uzlaştırma Döngüsü
- Operatör SDK'sı ve Kubebuilder: farklar ve hangisinin ne zaman kullanılacağı
- Kubebuilder ile eksiksiz bir Operatör uygulayın
- Operatör Merkezi ve Operatör Yaşam Döngüsü Yöneticisi (OLM)
- envtest ile operatör testi
- Yapım Operatörü: Zalando Postgres Operatörü, Kafka için Strimzi
Kubernetes Operatörü Nedir?
"Operatör" terimi, CoreOS tarafından 2016 yılında bir modeli tanımlamak için tanıtıldı: gibi belirli bir uygulamanın operasyonel teknik bilgisini kapsayan yazılım Kubernetes denetleyicileri kümesi. Google'ın resmi tanımı:
Bir Operatör ve bir Kubernetes uygulamasını paketleme, dağıtma ve yönetme yöntemi. Bir Operatör, yönetim sırasında bir insan operatörün ortak görevlerini uygular ve otomatikleştirir bu tür bir uygulama: dağıtım, güncellemeler, yedekleme, yük devretme, ölçeklendirme.
Operatör, Kubernetes bildirim modelini belirli alanlara genişletir. Bunun yerine “bana bir Pod ver” diyebilirsiniz, “bana 3 kopyalı, günlük yedeklemeli bir PostgreSQL kümesi verin S3'te otomatik yük devretme ve TLS sertifikaları". Operatör bunu nasıl dönüştüreceğini biliyor Somut Kubernetes kaynaklarında üst düzey spesifikasyon.
Operatör Olgunluk Modeli
Operatör Yetenek Modeli artan olgunluğun 5 seviyesini tanımlar:
| Seviye | İsim | Kapasite |
|---|---|---|
| 1 | Temel Kurulum | Otomatik uygulama sağlama |
| 2 | Kusursuz Yükseltmeler | Yamalar ve küçük sürüm yükseltmeleri |
| 3 | Tam Yaşam Döngüsü | Yedekleme, arıza kurtarma, yeniden yapılandırma |
| 4 | Derin Bilgiler | Metrikler, uyarılar, günlük işleme, iş yükü analizi |
| 5 | Otomatik Pilot | Otomatik ölçeklendirme, otomatik yapılandırma, anormallik tespiti |
Özel Kaynak Tanımı (CRD)
CRD, Kubernetes API'sini özel kaynak türleriyle genişletir. Sadece kullanmak yerine
yerel kaynaklar (Pod, Dağıtım, Hizmet), belirli etki alanı kaynaklarını tanımlayabilirsiniz
nasıl PostgresCluster, KafkaTopic, MLModel.
Bir CRD tanımlayın
# postgres-cluster-crd.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: postgresclusters.database.example.com
spec:
group: database.example.com
scope: Namespaced
names:
plural: postgresclusters
singular: postgrescluster
kind: PostgresCluster
shortNames:
- pgc
versions:
- name: v1alpha1
served: true
storage: true
# Schema di validazione OpenAPI v3
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
required:
- replicas
- version
properties:
replicas:
type: integer
minimum: 1
maximum: 5
description: "Numero di repliche PostgreSQL"
version:
type: string
enum: ["14", "15", "16"]
description: "Versione PostgreSQL"
storage:
type: object
properties:
size:
type: string
pattern: "^[0-9]+Gi$"
default: "10Gi"
storageClass:
type: string
default: "fast-ssd"
backup:
type: object
properties:
enabled:
type: boolean
default: false
schedule:
type: string
description: "Cron expression per backup schedulato"
s3Bucket:
type: string
resources:
type: object
properties:
requests:
type: object
properties:
memory:
type: string
cpu:
type: string
limits:
type: object
properties:
memory:
type: string
cpu:
type: string
status:
type: object
properties:
phase:
type: string
enum: ["Pending", "Creating", "Running", "Degraded", "Failed"]
readyReplicas:
type: integer
primaryEndpoint:
type: string
conditions:
type: array
items:
type: object
properties:
type:
type: string
status:
type: string
reason:
type: string
message:
type: string
lastTransitionTime:
type: string
format: date-time
# Stampa colonne aggiuntive in kubectl get
additionalPrinterColumns:
- name: Replicas
type: integer
jsonPath: .spec.replicas
- name: Version
type: string
jsonPath: .spec.version
- name: Status
type: string
jsonPath: .status.phase
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
# Subresource status (necessario per UpdateStatus)
subresources:
status: {}
İş Başında Özel Bir Kaynak
# my-postgres-cluster.yaml
apiVersion: database.example.com/v1alpha1
kind: PostgresCluster
metadata:
name: myapp-db
namespace: production
spec:
replicas: 3
version: "16"
storage:
size: "100Gi"
storageClass: fast-ssd
backup:
enabled: true
schedule: "0 2 * * *" # ogni notte alle 2:00
s3Bucket: "my-postgres-backups"
resources:
requests:
memory: "2Gi"
cpu: "1000m"
limits:
memory: "4Gi"
cpu: "2000m"
Denetleyici Deseni ve Uzlaştırma Döngüsü
Bir Operatörün kalbi denetleyici: sürekli devam eden bir süreç kümedeki kaynakların mevcut durumunu gözlemler ve bunu istenen durumla karşılaştırır Özel Kaynakta bildirildi. Bir fark (sürüklenme) olduğunda, kontrolör çalıştırır iki devleti uzlaştırmak için gerekli eylemler. Bu döngüye denir uzlaştırma döngüsü.
// Pseudocodice del reconcile loop
for {
desiredState = getDesiredState(customResource)
currentState = getCurrentState(cluster)
if currentState != desiredState {
actions = computeActions(desiredState, currentState)
execute(actions)
}
// Attendi il prossimo trigger (evento API server o requeueing)
waitForTrigger()
}
Denetleyici "tamamen olay odaklı" bir yaklaşım kullanmaz (her olayın bir eylemi tetiklediği) spesifikasyon) ama bir yaklaşım seviyeye dayalı: toplam durumu gözlemleyin ve uzlaşmak. Bu, denetleyicileri daha sağlam hale getirir: olaylar (çökme, yeniden başlatma) eksikse, denetleyici yine de yeniden başlatılacak ve doğru duruma geçecektir.
Kubebuilder: Bir Operatör Oluşturmak
Kubebuilder, Go'da Operatör oluşturmaya yönelik resmi CNCF çerçevesidir. Oluştur proje iskelesi, API sunucusuyla iletişimi yönetir ve yardımcılar sağlar uzlaştırma döngüsü için. Operatör SDK'sı Kubebuilder'ı temel alır ve aşağıdakiler için destek ekler: Helm ve Ansible operatörleri.
Proje Kurulumu
# Installa Kubebuilder
curl -L -o kubebuilder "https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)"
chmod +x kubebuilder
sudo mv kubebuilder /usr/local/bin/
# Crea un nuovo progetto Operator
mkdir postgres-operator && cd postgres-operator
kubebuilder init \
--domain database.example.com \
--repo github.com/myorg/postgres-operator
# Genera l'API e il controller per PostgresCluster
kubebuilder create api \
--group database \
--version v1alpha1 \
--kind PostgresCluster \
--resource \
--controller
# Struttura generata:
# api/v1alpha1/
# postgrescluster_types.go <- Definizione della struct CRD
# groupversion_info.go
# internal/controller/
# postgrescluster_controller.go <- Logica del reconcile loop
# config/crd/ <- Manifest YAML della CRD
API Türünü Tanımlayın
// api/v1alpha1/postgrescluster_types.go
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
corev1 "k8s.io/api/core/v1"
)
// PostgresClusterSpec definisce lo stato desiderato
type PostgresClusterSpec struct {
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=5
Replicas int32 `json:"replicas"`
// +kubebuilder:validation:Enum={"14","15","16"}
Version string `json:"version"`
Storage PostgresStorageSpec `json:"storage,omitempty"`
Backup PostgresBackupSpec `json:"backup,omitempty"`
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
}
type PostgresStorageSpec struct {
// +kubebuilder:default="10Gi"
Size string `json:"size,omitempty"`
StorageClass string `json:"storageClass,omitempty"`
}
type PostgresBackupSpec struct {
Enabled bool `json:"enabled,omitempty"`
Schedule string `json:"schedule,omitempty"`
S3Bucket string `json:"s3Bucket,omitempty"`
}
// PostgresClusterStatus descrive lo stato osservato
type PostgresClusterStatus struct {
Phase string `json:"phase,omitempty"`
ReadyReplicas int32 `json:"readyReplicas,omitempty"`
PrimaryEndpoint string `json:"primaryEndpoint,omitempty"`
Conditions []metav1.Condition `json:"conditions,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Replicas",type=integer,JSONPath=".spec.replicas"
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=".status.phase"
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=".metadata.creationTimestamp"
type PostgresCluster struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec PostgresClusterSpec `json:"spec,omitempty"`
Status PostgresClusterStatus `json:"status,omitempty"`
}
Uzlaştırma Döngüsü: Uygulama
// internal/controller/postgrescluster_controller.go
package controller
import (
"context"
"fmt"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
databasev1alpha1 "github.com/myorg/postgres-operator/api/v1alpha1"
)
type PostgresClusterReconciler struct {
client.Client
Scheme *runtime.Scheme
}
// +kubebuilder:rbac:groups=database.example.com,resources=postgresclusters,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=database.example.com,resources=postgresclusters/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete
func (r *PostgresClusterReconciler) Reconcile(
ctx context.Context,
req ctrl.Request,
) (ctrl.Result, error) {
logger := log.FromContext(ctx)
// 1. Ottieni la Custom Resource
pgCluster := &databasev1alpha1.PostgresCluster{}
if err := r.Get(ctx, req.NamespacedName, pgCluster); err != nil {
if errors.IsNotFound(err) {
// CR eliminata, pulizia gia gestita dai finalizer
return ctrl.Result{}, nil
}
return ctrl.Result{}, err
}
logger.Info("Reconciling PostgresCluster",
"name", pgCluster.Name,
"namespace", pgCluster.Namespace,
"replicas", pgCluster.Spec.Replicas)
// 2. Reconcilia il Service headless
if err := r.reconcileHeadlessService(ctx, pgCluster); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to reconcile headless service: %w", err)
}
// 3. Reconcilia lo StatefulSet
sts, err := r.reconcileStatefulSet(ctx, pgCluster)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to reconcile statefulset: %w", err)
}
// 4. Aggiorna lo status della CR
pgCluster.Status.ReadyReplicas = sts.Status.ReadyReplicas
pgCluster.Status.PrimaryEndpoint = fmt.Sprintf(
"%s-0.%s.%s.svc.cluster.local:5432",
pgCluster.Name,
pgCluster.Name,
pgCluster.Namespace,
)
if sts.Status.ReadyReplicas == pgCluster.Spec.Replicas {
pgCluster.Status.Phase = "Running"
} else if sts.Status.ReadyReplicas > 0 {
pgCluster.Status.Phase = "Degraded"
} else {
pgCluster.Status.Phase = "Creating"
}
if err := r.Status().Update(ctx, pgCluster); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to update status: %w", err)
}
logger.Info("Reconciliation complete",
"phase", pgCluster.Status.Phase,
"readyReplicas", pgCluster.Status.ReadyReplicas)
return ctrl.Result{}, nil
}
func (r *PostgresClusterReconciler) reconcileStatefulSet(
ctx context.Context,
pgCluster *databasev1alpha1.PostgresCluster,
) (*appsv1.StatefulSet, error) {
desired := r.buildStatefulSet(pgCluster)
// Imposta il owner reference per la garbage collection automatica
if err := ctrl.SetControllerReference(pgCluster, desired, r.Scheme); err != nil {
return nil, err
}
existing := &appsv1.StatefulSet{}
err := r.Get(ctx, client.ObjectKeyFromObject(desired), existing)
if errors.IsNotFound(err) {
// StatefulSet non esiste: crealo
if err := r.Create(ctx, desired); err != nil {
return nil, fmt.Errorf("failed to create StatefulSet: %w", err)
}
return desired, nil
}
if err != nil {
return nil, err
}
// StatefulSet esiste: aggiornalo se necessario
existing.Spec.Replicas = desired.Spec.Replicas
existing.Spec.Template = desired.Spec.Template
if err := r.Update(ctx, existing); err != nil {
return nil, fmt.Errorf("failed to update StatefulSet: %w", err)
}
return existing, nil
}
func (r *PostgresClusterReconciler) buildStatefulSet(
pgCluster *databasev1alpha1.PostgresCluster,
) *appsv1.StatefulSet {
image := fmt.Sprintf("postgres:%s", pgCluster.Spec.Version)
return &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: pgCluster.Name,
Namespace: pgCluster.Namespace,
},
Spec: appsv1.StatefulSetSpec{
Replicas: &pgCluster.Spec.Replicas,
ServiceName: pgCluster.Name,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": pgCluster.Name},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": pgCluster.Name},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "postgres",
Image: image,
Resources: pgCluster.Spec.Resources,
},
},
},
},
VolumeClaimTemplates: []corev1.PersistentVolumeClaim{
{
ObjectMeta: metav1.ObjectMeta{
Name: "data",
},
Spec: corev1.PersistentVolumeClaimSpec{
AccessModes: []corev1.PersistentVolumeAccessMode{
corev1.ReadWriteOnce,
},
StorageClassName: &pgCluster.Spec.Storage.StorageClass,
Resources: corev1.VolumeResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceStorage: pgCluster.Spec.Storage.ParsedSize(),
},
},
},
},
},
},
}
}
// SetupWithManager registra il controller con il manager
func (r *PostgresClusterReconciler) SetupWithManager(
mgr ctrl.Manager,
) error {
return ctrl.NewControllerManagedBy(mgr).
For(&databasev1alpha1.PostgresCluster{}).
Owns(&appsv1.StatefulSet{}). // Reconcilia quando cambia lo StatefulSet owned
Owns(&corev1.Service{}).
Complete(r)
}
Sonlandırıcı: Kaynak Temizleme
Sonlandırıcılar, bir kaynak yayınlanmadan önce temizleme işlemlerini gerçekleştirmenize olanak tanır ortadan kaldırıldı. Sonlandırıcı olmadan PostgresCluster CR'nin silinmesi CR'yi siler ancak mutlaka S3'teki veriler veya yedeklemeler değil. Sonlandırıcılarla bu temizliği yönetebilirsiniz:
// Aggiungi finalizer handling al Reconcile
const pgClusterFinalizer = "database.example.com/finalizer"
func (r *PostgresClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
pgCluster := &databasev1alpha1.PostgresCluster{}
if err := r.Get(ctx, req.NamespacedName, pgCluster); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// Gestione eliminazione
if !pgCluster.DeletionTimestamp.IsZero() {
if controllerutil.ContainsFinalizer(pgCluster, pgClusterFinalizer) {
// Esegui cleanup
if err := r.cleanupExternalResources(ctx, pgCluster); err != nil {
return ctrl.Result{}, err
}
// Rimuovi il finalizer
controllerutil.RemoveFinalizer(pgCluster, pgClusterFinalizer)
if err := r.Update(ctx, pgCluster); err != nil {
return ctrl.Result{}, err
}
}
return ctrl.Result{}, nil
}
// Aggiungi finalizer se non presente
if !controllerutil.ContainsFinalizer(pgCluster, pgClusterFinalizer) {
controllerutil.AddFinalizer(pgCluster, pgClusterFinalizer)
if err := r.Update(ctx, pgCluster); err != nil {
return ctrl.Result{}, err
}
}
// ... resto della logica di reconcile
return ctrl.Result{}, nil
}
envtest ile operatör testi
Kubebuilder şunları sağlar envtest, bir API sunucusunu başlatan bir test çerçevesi Denetleyicileri entegre bir şekilde test etmek için gerçek Kubernetes (kubelet'ler ve düğümler olmadan):
// internal/controller/postgrescluster_controller_test.go
package controller
import (
"context"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
databasev1alpha1 "github.com/myorg/postgres-operator/api/v1alpha1"
)
var _ = Describe("PostgresCluster Controller", func() {
const (
timeout = time.Second * 10
interval = time.Millisecond * 250
)
Context("Quando crea un PostgresCluster", func() {
It("Deve creare lo StatefulSet corrispondente", func() {
ctx := context.Background()
pgCluster := &databasev1alpha1.PostgresCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test-postgres",
Namespace: "default",
},
Spec: databasev1alpha1.PostgresClusterSpec{
Replicas: 1,
Version: "16",
Storage: databasev1alpha1.PostgresStorageSpec{
Size: "10Gi",
StorageClass: "standard",
},
},
}
Expect(k8sClient.Create(ctx, pgCluster)).Should(Succeed())
// Verifica che lo StatefulSet venga creato
stsLookupKey := types.NamespacedName{
Name: "test-postgres",
Namespace: "default",
}
createdSts := &appsv1.StatefulSet{}
Eventually(func() bool {
err := k8sClient.Get(ctx, stsLookupKey, createdSts)
return err == nil
}, timeout, interval).Should(BeTrue())
// Verifica le specifiche dello StatefulSet
Expect(*createdSts.Spec.Replicas).Should(Equal(int32(1)))
Expect(createdSts.Spec.Template.Spec.Containers[0].Image).
Should(Equal("postgres:16"))
// Cleanup
Expect(k8sClient.Delete(ctx, pgCluster)).Should(Succeed())
})
})
})
Operatör Oluşturma ve Dağıtımı
# Build dell'immagine
make docker-build docker-push IMG="myregistry/postgres-operator:v0.1.0"
# Deploy dell'Operator nel cluster
make deploy IMG="myregistry/postgres-operator:v0.1.0"
# Verifica il deployment
kubectl get pods -n postgres-operator-system
kubectl logs -n postgres-operator-system deployment/postgres-operator-controller-manager
# Applica una CR
kubectl apply -f my-postgres-cluster.yaml
kubectl get postgresclusters -n production
kubectl describe postgrescluster myapp-db -n production
Üretim Operatörü: Gerçek Örnekler
Her yaygın uygulama için bir Operatör oluşturmaya gerek yoktur. Ekosistem Kubernetes, önemli durum bilgisi olan uygulamalar için olgun Operatörler sunar:
Zalando Postgres Operatörü
# Installa il Postgres Operator di Zalando (level 5 maturity)
helm repo add postgres-operator-charts \
https://opensource.zalando.com/postgres-operator/charts/postgres-operator
helm install postgres-operator \
postgres-operator-charts/postgres-operator \
-n postgres-operator --create-namespace
# Crea un cluster PostgreSQL con HA e backup su S3
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: myapp-postgres
namespace: production
spec:
teamId: "myteam"
volume:
size: 100Gi
storageClass: fast-ssd
numberOfInstances: 3
users:
myapp:
- superuser
- createdb
databases:
myapp: myapp
postgresql:
version: "16"
parameters:
shared_buffers: "1GB"
max_connections: "200"
resources:
requests:
cpu: 1000m
memory: 2Gi
limits:
cpu: 2000m
memory: 4Gi
patroni:
failsafe_mode: false
# Backup automatico su S3 con WAL-G
enableLogicalBackup: true
logicalBackupSchedule: "00 02 * * *"
Strimzi: Kubernetes'te Kafka
# Kafka cluster con Strimzi (level 5 maturity)
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
name: production-cluster
namespace: kafka
spec:
kafka:
version: 3.7.0
replicas: 3
listeners:
- name: plain
port: 9092
type: internal
tls: false
- name: tls
port: 9093
type: internal
tls: true
config:
offsets.topic.replication.factor: 3
transaction.state.log.replication.factor: 3
transaction.state.log.min.isr: 2
default.replication.factor: 3
min.insync.replicas: 2
inter.broker.protocol.version: "3.7"
storage:
type: jbod
volumes:
- id: 0
type: persistent-claim
size: 200Gi
class: fast-ssd
deleteClaim: false
resources:
requests:
memory: 4Gi
cpu: 2000m
limits:
memory: 8Gi
cpu: 4000m
zookeeper:
replicas: 3
storage:
type: persistent-claim
size: 10Gi
class: fast-ssd
deleteClaim: false
entityOperator:
topicOperator: {}
userOperator: {}
Operatör Yaşam Döngüsü Yöneticisi (OLM)
OLM, kurulumu, yükseltmeyi ve yaşam döngüsü yönetimini yönetir. Kümedeki operatör. Ve OperatorHub.io tarafından Operatörleri dağıtmak için kullanılan mekanizma.
# Installa OLM nel cluster
curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.28.0/install.sh | bash -s v0.28.0
# Installa un Operator da OperatorHub tramite OLM
kubectl create -f https://operatorhub.io/install/postgres-operator.yaml
# Verifica gli Operator installati
kubectl get csv -n operators # ClusterServiceVersion
kubectl get subscription -n operators
Operatörler için En İyi Uygulamalar
Üretim Operatörleri için Kontrol Listesi
- Sonlandırıcıyı kullanın: Her zaman harici yan etkileri olan kaynaklar için (S3 klasörü, DNS kayıtları vb.)
- Durum koşullarını uygulayın: Kubernetes koşul modelini takip edin (tür, durum, neden, mesaj)
- İdempotans: Mutabakat döngüsünün aynı sonuçla birden çok kez yürütülmesi güvenli olmalıdır
- Yeniden denemeyle hataları ele alın: Amerika
ctrl.Result{RequeueAfter: time.Minute}geçici hatalar için - Engelleme işlemlerini yapmayın: Uzlaşma engellememeli; uzun işlemler için goroutinleri kullanın
- Asgari RBAC: Ek açıklamalarda yalnızca kesinlikle gerekli izinleri kullanın
+kubebuilder:rbac - envtest ile test etme: Her uzlaşma senaryosu için entegrasyon testleri yazın
- Sürüm oluşturma API'si: Geçişler için sürüm oluşturma (v1alpha1 -> v1beta1 -> v1) ve dönüşüm web kancalarını kullanın
Bir Operatör Oluşturulmaması Gerektiğinde
Operatörlerin önemli bir geliştirme ve bakım maliyeti vardır. Bir tane inşa et yalnızca şu durumlarda anlamlıdır: (1) OperatorHub'da uygulama için olgun bir Operatör varsa yönetiyorsun, kullan; (2) uygulama karmaşıktır, durum bilgisi gerektirir ve bilgi gerektirir otomatikleştirilecek özel işlemler; (3) bakımını yapabilecekleri özel ekipleriniz var Zamanla koda geçin. Basit dağıtım için buna gerek yoktur.
Sonuçlar ve Sonraki Adımlar
Kubernetes Operatör modeli, bildirimsel felsefenin doğal uzantısıdır. Kubernetes'ten karmaşık uygulama alanlarına. Veritabanlarını manuel olarak yönetmek yerine, mesajlaşma sistemleri ve durum bilgisi olan hizmetler ile operasyonel bilgiyi bir Sistemi istenilen durumda tutmak için 7/24 çalışan kontrolör.
Kubebuilder ve Operatör SDK'sı temelleri sağlar: proje iskelesi, yönetim sunucu API'sinin çerçevesini uzlaştırın. Ancak iş mantığı - nasıl yönetilir PostgreSQL yük devretme, Kafka kümesinin nasıl ölçekleneceği, TLS sertifikalarının nasıl döndürüleceği - spesifik uygulamaya ilişkin derin bilgi birikimiyle uygulanmalıdır.
Kubernetes at Scale Serisinde Yaklaşan Makaleler
İlgili Kaynaklar ve Seriler
- Kubernetes Ağı: eBPF ile CNI, Cilium
- Kubernetes'te Kalıcı Depolama
- MLOps: Kubernetes'te ML'yi ölçeklendirme — Eğitim hattının operatörü







