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 Operator | etcd 클러스터 관리 | 분산 저장소 |
| PostgreSQL Operator | PostgreSQL HA 관리 | 데이터베이스 |
| Kafka Operator | Kafka 클러스터 관리 | 메시지큐 |
| ** cert-manager** | TLS 인증서 자동화 | 보안 |
🔗 관련 노트
- 03-01-쿠버네티스-내부동작 — 컨트롤러 메커니즘
- 03-03-Helm-패키지-관리 — 패키지 관리
- 03-09-GitOps-ArgoCD — GitOps
마지막 업데이트: 2026-06-01