Operator 패턴

Kubernetes 리소스를 자동화하여 관리하는 고급 패턴


Kubernetes 리소스를 자동화하여 관리하는 고급 패턴

목표: 복잡한 애플리케이션을 자동화하여 운영할 수 있는 수준


🎯 Operator 개념

정의

애플리케이션의 도메인 지식을 코드로 구현한 Kubernetes 컨트롤러.

graph TB
    subgraph "Operator 패턴"
        CR["📋 Custom Resource"] -->|"정의"| CTRL["🎮 Controller"]
        CTRL -->|"관리"| APP["🗄️ Application"]
        
        CR -->|"원하는 상태"| CTRL
        CTRL -->|"현재 상태 확인"| APP
    end

핵심 원리:

  • Custom Resource로 선언적 API 제공
  • Controller로 상태 조정
  • 도메인 지식 자동화

📋 Custom Resource Definition (CRD)

CRD 생성

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: databases.myapp.example.com
spec:
  group: myapp.example.com
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              engine:
                type: string
                enum: ["mysql", "postgres"]
              version:
                type: string
              storage:
                type: string
              replicas:
                type: integer
                minimum: 1
                maximum: 5
  scope: Namespaced
  names:
    plural: databases
    singular: database
    kind: Database
    shortNames:
    - db

Custom Resource 사용

apiVersion: myapp.example.com/v1
kind: Database
metadata:
  name: production-db
spec:
  engine: mysql
  version: "8.0"
  storage: 10Gi
  replicas: 3

🎮 Controller 구현

Controller 루프

graph LR
    WATCH["Watch"] -->|"이벤트"| RECONCILE["Reconcile"]
    RECONCILE -->|"비교"| COMPARE["Desired vs Current"]
    COMPARE -->|"조정"| ACTION["Action"]
    ACTION --> WATCH

Go로 Controller 작성 (간단 예시)

package main

import (
    "context"
    "fmt"
    
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/rest"
)

func main() {
    config, _ := rest.InClusterConfig()
    clientset, _ := kubernetes.NewForConfig(config)
    
    // Database CRD Watch
    watch, _ := clientset.RESTClient().
        Get().
        AbsPath("apis/myapp.example.com/v1/databases").
        Watch(context.TODO())
    
    for event := range watch.ResultChan() {
        db := event.Object.(*Database)
        
        switch event.Type {
        case "ADDED", "MODIFIED":
            reconcile(db)
        case "DELETED":
            cleanup(db)
        }
    }
}

func reconcile(db *Database) {
    // 1. 현재 상태 확인
    // 2. 원하는 상태와 비교
    // 3. 차이 해소
    fmt.Printf("Reconciling database: %s\n", db.Name)
}

🛠️ Operator SDK

설치

# Operator SDK 설치
curl -LO https://github.com/operator-framework/operator-sdk/releases/latest/download/operator-sdk_linux_amd64
chmod +x operator-sdk_linux_amd64
sudo mv operator-sdk_linux_amd64 /usr/local/bin/operator-sdk

# 프로젝트 생성
operator-sdk init --domain=myapp.example.com --repo=github.com/myapp/database-operator

API 생성

# CRD 생성
operator-sdk create api --group=myapp --version=v1 --kind=Database --resource --controller

Controller 구현

// controllers/database_controller.go
func (r *DatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // Database CRD 가져오기
    db := &myappv1.Database{}
    if err := r.Get(ctx, req.NamespacedName, db); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }
    
    // 1. StatefulSet 생성/업데이트
    sts := r.desiredStatefulSet(db)
    if err := r.Create(ctx, sts); err != nil {
        if errors.IsAlreadyExists(err) {
            // 업데이트
            existing := &appsv1.StatefulSet{}
            r.Get(ctx, types.NamespacedName{Name: sts.Name, Namespace: sts.Namespace}, existing)
            existing.Spec = sts.Spec
            r.Update(ctx, existing)
        }
    }
    
    // 2. Service 생성
    svc := r.desiredService(db)
    r.Create(ctx, svc)
    
    // 3. Secret 생성
    secret := r.desiredSecret(db)
    r.Create(ctx, secret)
    
    // 상태 업데이트
    db.Status.Phase = "Running"
    db.Status.ReadyReplicas = 3
    r.Status().Update(ctx, db)
    
    return ctrl.Result{}, nil
}

빌드 및 배포

# 이미지 빌드
make docker-build IMG=myregistry/database-operator:v1.0.0

# 배포
make deploy IMG=myregistry/database-operator:v1.0.0

📋 주요 Operator 예시

Operator기능사용처
Prometheus Operator모니터링 스택 관리메트릭 수집
etcd Operatoretcd 클러스터 관리분산 저장소
PostgreSQL OperatorPostgreSQL HA 관리데이터베이스
Kafka OperatorKafka 클러스터 관리메시지큐
** cert-manager**TLS 인증서 자동화보안

🔗 관련 노트

  • 03-01-쿠버네티스-내부동작 — 컨트롤러 메커니즘
  • 03-03-Helm-패키지-관리 — 패키지 관리
  • 03-09-GitOps-ArgoCD — GitOps

마지막 업데이트: 2026-06-01