Kubernetes 커스텀 리소스, 커스텀 리소스 정의 (CRD) 및 컨트롤러

발행: (2026년 1월 18일 오후 01:34 GMT+9)
7 min read
원문: Dev.to

Source: Dev.to

SHARON SHAJI

Kubernetes는 Pods나 Services 때문에 강력한 것이 아니다.
Kubernetes 자체를 수정하지 않고 확장할 수 있기 때문에 강력합니다.

그 확장성은 Custom Resources + CRDs + Controllers에서 비롯됩니다.

이 세 가지를 제대로 이해하지 못한다면, 여러분은 실제로 Kubernetes를 사용하고 있는 것이 아니라 단순히 YAML을 배포하고 있는 것입니다.

Why CRDs Exist

Kubernetes solves generic infrastructure problems:

  • Scheduling
  • Networking
  • Storage
  • Scaling

But real companies have domain‑specific problems:

  • “Deploy a model”
  • “Provision a database”
  • “Create a service mesh rule”
  • “Manage certificates”

Instead of hard‑coding these into Kubernetes, it gives us a way to define our own APIs.

Framework

ComponentPurpose
CRD새 API 유형을 정의합니다
Custom Resource해당 API의 인스턴스
Controller실제 동작을 구현하는 로직

정신 모델 (중요)

Kubernetes 자체는 CRD에 대해 아무것도 하지 않으며, 단지 저장할 뿐입니다.
CRD를 컨트롤러 없이 생성하면, Kubernetes는 기꺼이 이를 받아들이지만 전혀 아무것도 하지 않습니다. 이것은 버그가 아니라 설계 의도입니다.

커스텀 리소스(CR)란 무엇인가요?

Custom Resource는 Kubernetes의 새로운 객체 유형이며, 다음과 같은 것과 같습니다:

  • Pod
  • Service
  • Deployment

직접 만들 수도 있습니다, 예를 들어:

  • Database
  • Application
  • MLModel
  • Certificate
  • Gateway

예시

kubectl get databases
kubectl apply -f myapp.yaml

Kubernetes는 Database가 무엇을 의미하는지 신경 쓰지 않습니다.

CRD (CustomResourceDefinition)란 무엇인가?

CRD는 Kubernetes 내부에 새로운 API 스키마를 정의합니다. 다음과 같이 생각하면 됩니다:

“Kubernetes야, 새로운 종류의 객체가 있어. 저장해 줘.”

CRD는 다음을 지정합니다:

  • API 그룹
  • 버전
  • Kind
  • 스키마 (검증)

간단한 CRD 예제

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: databases.mycompany.io
spec:
  group: mycompany.io
  scope: Namespaced
  names:
    plural: databases
    singular: database
    kind: Database
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                engine:
                  type: string
                version:
                  type: string
                storage:
                  type: string

이 CRD를 적용한 후:

kubectl get databases

Kubernetes는 이제 Database를 유효한 객체로 인식합니다 — 그 외는 없습니다.

Custom Resource (CR) 만들기

apiVersion: mycompany.io/v1
kind: Database
metadata:
  name: user-db
spec:
  engine: postgres
  version: "15"
  storage: 20Gi

적용하기:

kubectl apply -f database.yaml

결과:

  • etcd에 저장됨
  • Pod이 생성되지 않음
  • 데이터베이스가 시작되지 않음

대부분의 초보자들이 여기서 혼란스러워합니다.

왜 컨트롤러가 필수인가

A Controller는 뇌와 같습니다. 그것은:

  • 커스텀 리소스를 감시합니다
  • 원하는 상태실제 상태를 비교합니다
  • 차이를 조정합니다

컨트롤러가 없으면:

  • CRD = 죽은 스키마
  • CR = 쓸모없는 YAML

컨트롤러 조정 루프

모든 컨트롤러는 다음 루프를 따릅니다:

Observe → Compare → Act → Repeat

코드로 표현하면:

while True:
    desired_state = cr.spec
    actual_state = cluster_reality
    if desired_state != actual_state:
        fix_it()

이 루프는 절대 멈추지 않습니다.

CRD + 컨트롤러가 함께 작동하는 방식

User
  |
  | kubectl apply
  v
Kubernetes API Server
  |
  v
etcd (stores CR)
  |
  v
Controller watches CR
  |
  v
Controller creates / updates:
  - Pods
  - Services
  - PVCs
  - ConfigMaps

실제 예시: 데이터베이스 오퍼레이터

커스텀 리소스

apiVersion: mycompany.io/v1
kind: Database
metadata:
  name: user-db
spec:
  engine: postgres
  version: "15"
  storage: 20Gi

컨트롤러 로직

IF Database CR is created:
  - Create StatefulSet
  - Create PVC
  - Create Service

IF Database CR is deleted:
  - Cleanup resources

Kubernetes는 데이터베이스를 알지 못합니다. 당신의 컨트롤러는 알고 있습니다.

원하는 상태 vs 실제 상태

Desired State (CR):
  Database:
    engine: postgres
    replicas: 1

Actual State (Cluster):
  StatefulSet: missing

Controller Action:
  Create StatefulSet

누군가 StatefulSet을 수동으로 삭제하면, 컨트롤러가 이를 다시 생성합니다.

CRD와 Deployments

FeatureDeploymentCRD
Built‑inYesNo
Controller includedYesOnly if you write one
Logic locationKubernetesYou
DescriptionA Deployment is just a CRD + controller shipped by Kubernetes.

Istio는 CRDs를 사용합니다

Istio는 다음과 같은 CRDs를 사용하여 Kubernetes를 확장합니다:

  • VirtualService
  • DestinationRule
  • Gateway

예시

kind: VirtualService
spec:
  hosts:
    - myapp
  http:
    - ...

Istio CRDs Diagram

route:
  - destination:
      host: myapp-v2

Istio 컨트롤러가 이를 변환하는 대상

  • Envoy config
  • Traffic routing
  • Load balancing

Note: Istio는 Kubernetes를 수정하지 않습니다. 올바르게 확장합니다.

Why Companies Build Products Using CRDs

CRDs allow:

  • Kubernetes‑native APIs
  • Declarative behavior
  • kubectl‑first UX
  • Strong reconciliation guarantees

Used by:

  • ArgoCD
  • Crossplane
  • Cert‑Manager
  • Prometheus Operator
  • Istio

All follow the same pattern.

일반적인 실수

  • “CRD가 자동으로 리소스를 생성한다”
  • YAML 내부에 로직을 작성하기
  • .status 필드 무시하기
  • CRD를 설정 파일로 취급하기

CRD는 API이며, 설정 파일이 아닙니다.

언제 CRD를 사용해야 할까요?

CRD를 사용해야 할 경우:

  • 배포만이 아니라 라이프사이클을 관리할 때
  • 조정이 필요할 때
  • 플랫폼을 구축할 때

CRD를 사용하면 안 되는 경우:

  • 정적 구성
  • 일회성 작업
  • 간단한 값

최종 요약

  • CRDs는 WHAT을 정의합니다
  • Controllers는 HOW이 발생하는 방식을 정의합니다
  • Kubernetes는 루프를 강제합니다

이를 이해한다면, YAML을 넘어선 Kubernetes를 이해한 것입니다.

Back to Blog

관련 글

더 보기 »