Chuyển đến nội dung chính

LESSON 34: OPERATORS AND CUSTOM RESOURCES

Operator pattern: CRDs, Custom Controllers, Operator SDK, Kubebuilder. Common operators: Prometheus Operator, CloudNativePG (PostgreSQL), Strimzi (Kafka). Write simple Operators with Kubebuilder.

🔒 DevSecOps — Lesson 34 LESSON 34: OPERATORS AND CUSTOM RESOURCES

KUBERNETES: FROM BASIC TO ADVANCED

Module 8: Helm, Operators & GitOps

xdev.asia

🎯 Lesson Objective

Understand the Operator pattern, how to use CRDs to extend the Kubernetes API, and how popular operators (Prometheus, CloudNativePG, Strimzi) help manage stateful applications.

1. Operator Pattern

Operators encode operational knowledge of an application into the Kubernetes controller. Instead of admins performing manual steps (backup, failover, scaling), Operators automate them.

Example: No need to know how to manually failover PostgreSQL primary — CloudNativePG Operator automatically detects primary down and promotes replica within seconds.

Operator = CRD (custom resource type) + Custom Controller (watches and acts)

2. Custom Resource Definitions (CRDs)

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: databases.mycompany.io
spec:
  group: mycompany.io
  names:
    kind: Database
    plural: databases
    singular: database
    shortNames: ["db"]
  scope: Namespaced
  versions:
  - name: v1
    served: true    # API server phục vụ version này
    storage: true   # etcd lưu ở version này
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            required: ["engine", "size"]
            properties:
              engine:
                type: string
                enum: ["postgres", "mysql"]
              size:
                type: string
              replicas:
                type: integer
                minimum: 1
                maximum: 5
          status:
            type: object
            properties:
              phase:
                type: string
              connectionString:
                type: string
    subresources:
      status: {}   # enable status subresource
    additionalPrinterColumns:
    - name: Engine
      type: string
      jsonPath: .spec.engine
    - name: Size
      type: string
      jsonPath: .spec.size
    - name: Phase
      type: string
      jsonPath: .status.phase
# Sau khi apply CRD, có thể tạo custom resources
cat <<EOF | kubectl apply -f -
apiVersion: mycompany.io/v1
kind: Database
metadata:
  name: my-postgres
  namespace: production
spec:
  engine: postgres
  size: medium
  replicas: 3
EOF

kubectl get databases -n production kubectl get db -n production # dùng shortName

3. Controller Loop

Custom Controller continuously watches resources and reconciles them to the desired state:

for {
  // Lấy desired state từ K8s API
  desired = getDatabase("my-postgres")

// Lấy actual state từ cluster actual = getActualDatabaseState()

// Tính sự khác biệt diff = compare(desired, actual)

// Act để reconcile if diff { applyChanges(diff) }

// Cập nhật status updateStatus(desired, actual.phase)

sleep(reconcileInterval) }

4. Kubebuilder — Build Operators

# Cài Kubebuilder
curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)
chmod +x kubebuilder && mv kubebuilder /usr/local/bin/

Tạo project mới

mkdir database-operator && cd database-operator kubebuilder init --domain mycompany.io --repo github.com/mycompany/database-operator

Tạo API (CRD + Controller)

kubebuilder create api --group mycompany --version v1 --kind Database

Project structure:

api/v1/database_types.go ← CRD schema

controllers/database_controller.go ← Reconcile loop

config/ ← K8s manifests

// controllers/database_controller.go
func (r *DatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    log := log.FromContext(ctx)

    // Lấy Database resource
    var database mycompanyv1.Database
    if err := r.Get(ctx, req.NamespacedName, &database); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // Tạo StatefulSet nếu chưa tồn tại
    statefulSet := &appsv1.StatefulSet{}
    err := r.Get(ctx, types.NamespacedName{
        Name:      database.Name,
        Namespace: database.Namespace,
    }, statefulSet)

    if errors.IsNotFound(err) {
        // Tạo StatefulSet
        newSS := r.constructStatefulSet(&database)
        r.Create(ctx, newSS)
        log.Info("Created StatefulSet", "name", newSS.Name)
    }

    // Cập nhật status
    database.Status.Phase = "Running"
    r.Status().Update(ctx, &database)

    return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
}

5. Common Operators — 2026

5.1 Prometheus Operator

# Quản lý Prometheus cluster bằng CRDs
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: main
  namespace: monitoring
spec:
  replicas: 2
  retention: 7d
  serviceMonitorSelector: {}   # watch tất cả ServiceMonitors
  resources:
    requests:
      memory: 512Mi

5.2 CloudNativePG — PostgreSQL (CNCF Graduated)

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: my-postgres
  namespace: production
spec:
  instances: 3    # 1 primary + 2 replicas
  primaryUpdateStrategy: unsupervised  # auto failover
  storage:
    size: 10Gi
    storageClass: fast-ssd
  postgresql:
    parameters:
      max_connections: "200"
      shared_buffers: "256MB"
  backup:
    retentionPolicy: "30d"
    barmanObjectStore:
      destinationPath: s3://my-bucket/postgres/
      s3Credentials:
        accessKeyId:
          name: aws-creds
          key: ACCESS_KEY_ID
# CloudNativePG: automatic primary/replica management
kubectl get clusters -n production
kubectl get pods -n production -l cnpg.io/cluster=my-postgres
# my-postgres-1 → primary
# my-postgres-2 → replica
# my-postgres-3 → replica

Failover: xóa primary → operator tự promote replica

kubectl delete pod my-postgres-1 -n production

→ my-postgres-2 được promote thành primary trong ~5s

5.3 Strimzi — Apache Kafka

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-kafka
  namespace: messaging
spec:
  kafka:
    replicas: 3
    version: 3.9.0
    config:
      auto.create.topics.enable: "false"
    storage:
      type: persistent-claim
      size: 50Gi
  zookeeper:
    replicas: 3
    storage:
      type: persistent-claim
      size: 10Gi
  entityOperator:
    topicOperator: {}    # quản lý KafkaTopic CRDs
    userOperator: {}     # quản lý KafkaUser CRDs

5.4 cert-manager

# Tự động cấp và renew TLS certificates
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: api-tls
  namespace: production
spec:
  secretName: api-tls-secret
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
  - api.example.com
  - *.api.example.com

6. Operator Hub and OLM

# Operator Lifecycle Manager (OLM) quản lý lifecycle của operators
# Tìm operators tại: https://operatorhub.io/

Cài OLM

curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/latest/download/install.sh | bash -s latest

Cài operator từ OperatorHub

kubectl create -f https://operatorhub.io/install/postgresql.yaml

Summary

  • Operator = CRD + Custom Controller to automate Day-2 operations__HTMLTAG_105___
  • CRD extends the Kubernetes API with custom resource types
  • Kubebuilder: scaffold and build operators with Go
  • CloudNativePG: best PostgreSQL operator (CNCF graduated, auto failover)
  • Strimzi: Kafka lifecycle management on Kubernetes__HTMLTAG_113___
  • cert-manager: TLS certificate automation