쿠버네티스 마스터 노트 시리즈 3편. ReplicaSet이 Pod 수를 유지하는 메커니즘, Deployment의 롤링 업데이트와 롤백, StatefulSet이 Stateful 앱(DB·Kafka)에 필요한 이유와 결정적 차이점, DaemonSet으로 모든 노드에 1개씩(로깅·모니터링), Job·CronJob의 일회성 작업 패턴, 5 Workload 선택 기준까지.
이 글은 쿠버네티스 마스터 노트 시리즈의 세 번째 편입니다. 2편(Pod)에서 Pod 단위를 봤다면, 이번엔 그 Pod을 자동 관리하는 추상화 — Workloads 5종.
Pod 직접 만들면 다운 시 안 살아남. Deployment로 감싸면 자동 복구·확장·롤링 업데이트. 5 종류 추상화의 선택이 시스템 동작 결정.
처음 Workloads가 어렵게 느껴지는 이유
처음 이 단원이 어렵게 느껴지는 이유는 두 가지예요. 첫째, 종류가 5개라 헷갈립니다. ReplicaSet·Deployment·StatefulSet·DaemonSet·Job — 어느 게 어디에? 둘째, 계층 관계가 모호합니다. Deployment가 ReplicaSet 만든다는데, 둘 다 직접 만들면?
해결법은 한 가지예요. "각 Workload = 한 줄 사용처". Deployment=일반 stateless, StatefulSet=DB·Kafka, DaemonSet=노드별 1개, Job=일회성, CronJob=스케줄. 이 한 줄만 잡으면 끝.
5 Workload 한 줄 정리
| Workload | 한 줄 사용처 |
|---|---|
| ReplicaSet | Pod 수 유지 (직접 사용 X, Deployment가 만듦) |
| Deployment | 일반 stateless 앱 (웹·API) |
| StatefulSet | stateful 앱 (DB·Kafka·ZooKeeper) |
| DaemonSet | 모든 노드에 1개 (로깅·모니터링) |
| Job / CronJob | 일회성 / 스케줄 작업 |
ReplicaSet — Pod 수 유지
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-rs
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
역할 — 항상 N개 Pod 유지:
- Pod 다운 → 새 Pod 생성
- Pod 추가 (수동) → 초과분 제거
여기서 정말 중요한 시험 함정 — ReplicaSet 직접 사용 거의 X. Deployment가 자동으로 ReplicaSet 만들고 관리. 사용자는 Deployment만 다루면 됨.
Deployment — 가장 일반적
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 3
selector:
matchLabels:
app: nginx
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
kubectl apply -f deployment.yaml
kubectl get deployments
kubectl get rs # ReplicaSet 자동 생성됨
kubectl get pods
Rolling Update
# 이미지 업데이트
kubectl set image deployment/nginx-deploy nginx=nginx:1.26
# 또는 YAML 수정 후 apply
kubectl apply -f deployment.yaml
# 진행 상황
kubectl rollout status deployment/nginx-deploy
흐름:
1. 새 ReplicaSet (이미지 1.26) 생성
2. 새 Pod 1개 띄움 (maxSurge=1)
3. 기존 Pod 1개 제거
4. 반복 (모든 Pod 교체될 때까지)
5. 옛 ReplicaSet은 보관 (롤백용)
maxSurge = 한 번에 몇 개 추가, maxUnavailable = 한 번에 몇 개 삭제.
여기서 정말 중요한 시험 함정 — maxSurge=0, maxUnavailable=0 동시 X. 한쪽이 0이면 다른쪽 1+이어야. 안 그러면 업데이트 진행 X.
롤백
# 이력
kubectl rollout history deployment/nginx-deploy
# 이전 버전으로
kubectl rollout undo deployment/nginx-deploy
# 특정 revision
kubectl rollout undo deployment/nginx-deploy --to-revision=2
옛 ReplicaSet 그대로 둠 → 즉시 롤백.
Update 전략
| 전략 | 설명 |
|---|---|
| RollingUpdate (기본) | 점진적 교체 (무중단) |
| Recreate | 모두 죽이고 새로 시작 (다운타임) |
여기서 시험 함정이 하나 있어요. RollingUpdate 시 두 버전 동시 존재 시간 있음. API 호환성 신중. Blue-Green이나 Canary는 더 정교한 도구 (Argo Rollouts 등).
StatefulSet — Stateful 앱
DB·Kafka·ZooKeeper처럼 상태가 있는 앱.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres-headless
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 10Gi
Deployment vs StatefulSet 결정적 차이
| 측면 | Deployment | StatefulSet |
|---|---|---|
| Pod 이름 | 무작위 (nginx-7d8...) |
순차 (pg-0, pg-1, pg-2) |
| Pod 시작 | 동시 | 순차 (0 → 1 → 2) |
| Pod 종료 | 무작위 | 역순 (2 → 1 → 0) |
| Storage | 공유 또는 X | 각 Pod 별도 PVC |
| 네트워크 | Pod IP 변경 시 새로 | 고정 DNS (pg-0.headless.ns) |
| 사용처 | Stateless | Stateful (DB·Queue) |
여기서 정말 중요한 시험 함정 — StatefulSet의 핵심 = 안정적 ID + 안정적 Storage. Pod 다운돼도 같은 이름·같은 DNS·같은 PVC. DB Master-Slave 같은 구조에 필수.
Headless Service
StatefulSet엔 Headless Service 함께:
apiVersion: v1
kind: Service
metadata:
name: postgres-headless
spec:
clusterIP: None # Headless
selector:
app: postgres
ports:
- port: 5432
각 Pod이 직접 DNS:
pg-0.postgres-headless.namespace.svc.cluster.localpg-1.postgres-headless.namespace.svc.cluster.local
DaemonSet — 모든 노드에 1개
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
containers:
- name: node-exporter
image: prom/node-exporter
ports:
- containerPort: 9100
각 노드에 자동으로 1개씩 Pod. 노드 추가 시 자동 배포.
용도:
- 로그 수집 (Fluentd·Filebeat per node)
- 모니터링 (Node Exporter·DataDog)
- 네트워크 플러그인 (Calico·Flannel)
- 스토리지 데몬 (Glusterfs·Ceph)
여기서 시험 함정이 하나 있어요. DaemonSet은 Pod 수 = 노드 수 자동. replicas 지정 X. 특정 노드만 = nodeSelector·affinity 사용.
Job — 일회성 작업
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
spec:
template:
spec:
containers:
- name: migrate
image: my-app:migrate
command: ['./migrate.sh']
restartPolicy: OnFailure
backoffLimit: 3
특성:
- 끝까지 실행 (exit 0)
- 실패 시 재시도 (
backoffLimit) - 완료 후 Pod 보관 (로그 확인용)
병렬:
spec:
parallelism: 5 # 동시 실행 수
completions: 100 # 총 완료 횟수
용도:
- DB 마이그레이션
- 배치 처리
- 데이터 임포트
- 테스트 실행
CronJob — 스케줄 작업
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-backup
spec:
schedule: "0 2 * * *" # 매일 새벽 2시
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: backup-tool
command: ['./backup.sh']
restartPolicy: OnFailure
cron 형식:
분 시 일 월 요일
0 2 * * * # 매일 02:00
*/15 * * * * # 15분마다
0 0 * * 0 # 매주 일요일 00:00
여기서 정말 중요한 시험 함정 — CronJob은 작업 누락 가능. K8s 다운 시점이면 그 시점 작업 X. 정확한 스케줄링 필요 = 외부 도구 (Argo Workflows 등).
Workload 선택 결정표
| 상황 | 선택 |
|---|---|
| 일반 웹·API (stateless) | Deployment |
| DB·Kafka·ZooKeeper | StatefulSet |
| 로그·모니터링 (노드별) | DaemonSet |
| 마이그레이션·일회성 | Job |
| 매시 백업·정기 작업 | CronJob |
| Pod 수 유지만 (단순) | (Deployment 사용, ReplicaSet 직접 X) |
디버깅
# Deployment 상태
kubectl get deployment <name>
kubectl describe deployment <name>
# Rollout 상태·이력
kubectl rollout status deployment/<name>
kubectl rollout history deployment/<name>
# 일시 정지·재개 (단계별 카나리)
kubectl rollout pause deployment/<name>
kubectl rollout resume deployment/<name>
# scaling
kubectl scale deployment/<name> --replicas=5
시험 직전 한 번 더 — 자주 헷갈리는 함정 모음
여기까지가 3편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.
- 5 Workload — Deployment / StatefulSet / DaemonSet / Job / CronJob
- ReplicaSet은 Deployment가 자동 (직접 X)
- Deployment = 일반 stateless 앱 (웹·API)
- Rolling Update —
maxSurge(추가) +maxUnavailable(삭제) - 둘 다 0 X
- 옛 ReplicaSet 보관 → 즉시 롤백 (
kubectl rollout undo) - Update 전략 — RollingUpdate (기본·무중단) / Recreate (다운타임)
- StatefulSet = stateful (DB·Kafka)
- 안정적 ID —
pg-0,pg-1(순차) - 안정적 Storage — 각 Pod 별도 PVC
- 안정적 DNS —
pg-0.headless.ns - 시작 순차·종료 역순
- Headless Service 함께 (clusterIP: None)
- DaemonSet = 노드별 1개
- 노드 추가 시 자동 배포
- 로깅·모니터링·CNI·스토리지 데몬
- Job = 일회성·끝까지 실행
backoffLimit·parallelism·completions- 마이그레이션·배치·임포트
- CronJob = 스케줄 작업
- cron 형식 —
분 시 일 월 요일 - K8s 다운 시 작업 누락 가능
- 정확한 스케줄 = Argo Workflows 등
- 디버깅 — describe·rollout (status·history·undo·pause·resume)·scale
시리즈 다른 편
- 1편 — 아키텍처·Control Plane
- 2편 — Pod
- 3편 — Workloads (현재 글)
- 4편 — Services·Networking
- 5편 — ConfigMap·Secret
- 6편 — Storage
- 7편 — Scaling·Scheduling
- 8편 — Security
- 9편 — Helm
- 10편 — 실전 (매니지드·GitOps·Observability)
공식 문서: Kubernetes Workloads 에서 더 깊이.
다음 글(4편)에서는 Services & Networking — ClusterIP·NodePort·LoadBalancer·Ingress 4종, DNS·서비스 디스커버리까지 풀어 갑니다.