쿠버네티스 마스터 — Workloads (Deployment·StatefulSet·DaemonSet·Job)

2026-05-03확률과 통계 마스터 노트

쿠버네티스 마스터 노트 시리즈 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.local
  • pg-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 UpdatemaxSurge (추가) + 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

시리즈 다른 편

공식 문서: Kubernetes Workloads 에서 더 깊이.

다음 글(4편)에서는 Services & Networking — ClusterIP·NodePort·LoadBalancer·Ingress 4종, DNS·서비스 디스커버리까지 풀어 갑니다.

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!