사용자 정의 리소스란
Custom Resource
쿠버네티스 API를 원하는 대로 확장한 리소스
예로 쿠버네티스 코어 API에 Pod 라는 리소스가 있지만 사용자가 원하는 특별한 기능을 더한 MyPod라는 리소스를 새롭게 정의할 수 있습니다.
이는 사용자가 쉽게 API를 확장할 수 있도록 CustomResourceDefinition을 제공합니다.
# mypod-crd.yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: mypods.crd.example.com
spec:
group: crd.example.com
version: v1
scope: Namespaced
names:
plural: mypods# 복수 이름
singular: mypod# 단수 이름
kind: MyPod# Kind 이름
shortNames: # 축약 이름
- mp
- kind: CustomResourceDefinition 리소스를 이용하여 사용자 정의 리소스를 생성합니다.
- name: <NAMES>.<GROUP>으로 정의합니다(mypods.crd.example.com)
- group: apiVersion의 그룹 이름 (<GROUP>)을 지정합니다.
- version: 사용자 리소스의 버전을 정의합니다.
- scope: Cluster 레벨 리소스인지 네임스페이스 레벨 리소스인지 지정합니다.
- names: CRD 리소스의 이름을 정의합니다.
# crd 생성
kubectl apply -f mypod-crd.yaml
# customresourcedefinition.apiextensions.k8s.io/mypods.crd.example.com created
# crd 리소스 확인
kubectl get crd | grep mypods
# NAME CREATED AT
# mypods.crd.example.com 2020-06-14T09:33:32Z
이러면 kubectl을 통해 MyPod라는 사용자 리소스를 컨트롤 할 수 있습니다.
# MyPod 리소스 생성
cat << EOF | kubectl apply -f -
apiVersion: "crd.example.com/v1"
kind: MyPod
metadata:
name: mypod-test
spec:
uri: "any uri"
customCommand: "custom command"
image: nginx
EOF
# mypod.crd.example.com/mypod-test created
kubectl get mypod
# NAME AGE
# mypod-test 3s
# 축약형인, mp로도 조회가 가능합니다.
kubectl get mp
# NAME AGE
# mypod-test 3s
# MyPod의 상세 정보를 조회합니다.
kubectl get mypod mypod-test -oyaml
# apiVersion: crd.example.com/v1
# kind: MyPod
# metadata:
# ...
# name: mypod-test
# namespace: default
# resourceVersion: "723476"
# selfLink: /apis/crd.example.com/v1/namespaces/default/mypods/mypod-test
# uid: 50dd0cc8-0c1a-4f43-854b-a9c212e2046d
# spec:
# customCommand: custom command
# image: nginx
# uri: any uri
# MyPod를 삭제합니다.
kubectl delete mp mypod-test
# mypod.crd.example.com "mypod-test" deleted
아직 MyPod라는 리소스만 정의한 상태이고 동작 수행이 없습니다.
이는 다음 Custom Controller로 진행합니다.
Custom Controller
Controller는 쿠버네티스 클러스터 내에 Pod 형태로 존재하며 주기적으로 특정 리소스의 이벤트를 모니터링하다 해당 리소스의 상태 변화에 따라 사전에 정의된 동작을 수행하는 주체입니다.
쿠버네티스 내부적으로 존재하지 않는 사용자 정의 리소스는 Custom Contorller를 사용합니다.
앞서 만든 MyPod리소스 상태를 체크하며 변화에 맞춰 특정 동작을 수행하는 컨트롤러를 제작해봅시다.
(Custom Contoller를 만드는 방법은 언어/동작 방식에 따라 다양하다)
# MyPod 정의
struct MyPod {
Uri string
CustomCommand string
...
}
def main {
# 무한루프
for {
# 신규 이벤트
desired := apiServer.getDesiredState(MyPod)
# 기존 이벤트
current := apiServer.getCurrentState(MyPod)
# 변경점 발생시(수정,생성,삭제), 특정 동작 수행
if desired != current {
makeChanges(desired, current)
}
}
}
사용자 정의 리소스 생성 과정
- CRD을 이용하여 사용자 정의 리소스 생성
- 사용자 정의 리소스의 실제 객체를 생성
- MyPod Contoller가 새로운 이벤트가 발생한 것을 인지
- 특정 동작을 수행
Operator 패턴

Operator패턴이란 Custom Resource와 그에 대응하는 Custom Controller의 조합을 이용하여 특정 애플리케이션이나 서비스의 생성/삭제를 관리하는 패턴을 말합니다.
이를 이용해 쿠버네티스 코어 API에 포함되지 않은 애플리케이션을 마치 쿠버네티스 native 리소스처럼 동작하게끔 만들 수 있습니다.
신규 프로젝트를 시작할 때마다 CI/CD를 위한 젠킨스 애플리케니션을 새로 생성하고 프로젝트 완료 이후에는 삭제한다 가정하면,
Operator패턴을 이용하여 젠킨스라는 리소스를 생성하여 새로운 젠킨스 애플리케이션이 필요할 때마다 젠킨스 리소스를 생성합니다.
Operator tools
이를 쿠버네티스 API를 이용하여 처음부터 개발하는 것도 가능하지만,
편리하게 만들 수 있게 제공하는 툴이 이미 존재합니다.
- kubebuilder: https://book.kubebuilder.io
- Operator Framework: https://coreos.com/operators
- Metacontroller: https://metacontroller.app
- KUDO: https://kudo.dev
유용한 Operators
Operator를 직접 개발하는 경우도 있지만 대부분 helm chart와 마찬가지로 이미 잘 만들어진 Operator들을 활용하는 경우가 더 많습니다.
MinIO Operator
이전에 스토리지에서 생성한 Object storage솔루셔닌 MinIO 또한 Operator를 이용하여 생성할 수 있습니다.
여러 환경에 Object storage 서버를 제공해야 하는 경우 유용하게 사용할 수 있습니다. (dev, prod 환경 구분 등)
MinIO CRD 및 Controller 설치
생략
Prometheus-Operator
로깅과 모니터링에서 Prometheus & Grafana 도 사실 prometheus-operator를 이용한 것입니다.
helm chart 설치 시, prometheus라는 리소스가 생성된 것을 확인할 수 있습니다.
helm install mon stable/prometheus-operator --version 8.16.1
# prometheus라는 사용자 정의 리소스 확인
kubectl get prometheuses
# NAME VERSION REPLICAS AGE
# mon-prometheus-operator-prometheus v2.18.1 1 17s
# Prometheus 사용자 정의 리소스
kubectl get prometheuses mon-prometheus-operator-prometheus -oyaml
# apiVersion: monitoring.coreos.com/v1
# kind: Prometheus
# metadata:
# annotations:
# meta.helm.sh/release-name: mon
# meta.helm.sh/release-namespace: default
# generation: 1
# labels:
# app: prometheus-operator-prometheus
# app.kubernetes.io/managed-by: Helm
# chart: prometheus-operator-8.14.0
# heritage: Helm
# ....
helm delete mon
Helm Operator
마지막으로 Helm operator를 살펴보겠습니다.
이게 제일 유용하게 사용할 수 있는데, 이는 helm chart를 사용자 쿠버네티스 리소스처럼 관리할 수 있게 해주는 Operator입니다.
helm 사용자 정의 리소스를 생성하면 helm chart가 설치되고 리소스가 삭제될 때 chart도 삭제 됩니다.
Helm Operator에서 사용하는 사용자 정의 리소스의 이름을 HelmRelease라고 부릅니다.
이 리소스만으로 원하는 chart를 마치 쿠버네티스 리소스처럼 사용할 수 있게 합니다.
HelmRelease의 세부 정의를 보면
# myHelmRelease.yaml
apiVersion: helm.fluxcd.io/v1
kind: HelmRelease
metadata:
name: rabbit
namespace: default
spec:
releaseName: rabbitmq
chart:
repository: <https://kubernetes-charts.storage.googleapis.com/>
name: rabbitmq
version: 3.3.6
values:
replicas: 1
- apiVersion, kind, metadata: 기본적인 리소스 정보
- spec: HelmRelease의 스펙을 정의
- releaseName: 배포된 helm chart의 이름을 지정
- chart: 설치할 chart의 위치
- Repositorty: 원격 레포의 위치 URL
- name: 원격 레포에서 사용하는 chart 이름 입력
- version: 설치하려는 chart 버전 입력
- value: helm chart의 values.yaml 파일 정보를 설정
Helm Operator 설치
이 리소스를 사용하기 위해 CRD와 Controller를 설치합니다.
(생략)
- Helm Operator가 왜 필요한지, 도대체 무엇을 하는 녀석인지 아주 쉽게 설명해 드릴게요.
1. 비유로 이해하기 (에어컨 vs 선풍기)- 일반 Helm (선풍기): 당신이 직접 버튼을 눌러야 켜집니다. "강풍"으로 바꾸고 싶으면 다시 가서 버튼을 눌러야 합니다. (명령형)
- Helm Operator (에어컨): 당신은 리모컨에 "24도"라고 설정(상태)만 해두면 됩니다. 그러면 에어컨(Operator)이 현재 온도를 감지해서 알아서 바람을 세게 틀었다가, 약하게 틀었다가 하며 24도를 유지합니다. (선언형)
- 당신은 쿠버네티스에게 "나는 이 차트의 1.0 버전을 원해"라고 적힌 **YAML 파일(주문서)**만 던져놓습니다.
- *Helm Operator(로봇)**는 그 주문서를 24시간 감시합니다.
- 주문서가 들어오면 Operator가 알아서 helm install을 수행합니다.
- 나중에 당신이 주문서의 버전을 1.1로 고치면? Operator가 그걸 감지하고 알아서 helm upgrade를 수행합니다.
- CRD (Custom Resource Definition): 쿠버네티스에 HelmRelease라는 새로운 자원 타입을 정의합니다.
- Controller (Operator): 이 자원을 감시하는 봇이 돕니다.
- Reconciliation (재조정):
- User: "이미지 태그를 v2로 바꾼 YAML을 적용할게."
- Operator: "어? 설정 파일(Desired State)은 v2인데, 지금 돌아가는 앱(Current State)은 v1이네? 내가 helm upgrade 돌려서 맞춰야겠다!"
- 이것이 바로 GitOps의 핵심 원리입니다.
- Helm Operator를 설치하면, 쿠버네티스 안에 HelmRelease 같은 **주문서(CRD)**를 만들 수 있습니다.
- 그런데 만약 버전을 1.1로 올리려면? 사람이 또 helm upgrade ...를 쳐야 합니다. 누가 실수로 설정을 바꾸면? 다시 명령어를 쳐서 복구해야 합니다. 즉, '사람'이 개입해야만 상태가 변합니다.
- Bash
- 일반적인 Helm의 문제점
- 한마디로 정의하면 "사람 대신 helm install, helm upgrade 명령어를 쳐주는 로봇"입니다.
'개발 > DevOps' 카테고리의 다른 글
| Jira DC 제품의 SSO 연동 및 DR 구축 방안 사례 (0) | 2026.01.24 |
|---|---|
| [Kubenetes] 접근제어 - Network Policy, Ingress & Egress, AND & OR (1) | 2025.12.24 |
| [Kubenetes] 접근제어 - HTTP Basic Authentication, X.509 인증서, RBAC (1) | 2025.12.23 |
| [Kubenetes] 스토리지 - PersistentVolume, PersistentVolumeClaim, StorageClass (1) | 2025.11.11 |