파드를 사용하는 다른 오브젝트들
- 13.1 잡(Job)
- 13.2 데몬셋(DaemonSet)
- 13.3 스테이트풀셋(StatefulSet)
모든 워크로드가 "항상 떠 있는 웹 서버" 형태는 아니잖아. 한 번 실행하고 끝나는 작업, 모든 노드에 하나씩 배포해야 하는 에이전트, 순서와 상태가 중요한 데이터베이스 — 각 상황에 맞는 오브젝트가 따로 있어.
**잡(Job)**은 한 번 실행하고 완료되면 끝나는 작업을 위한 오브젝트야. 디플로이먼트는 파드가 죽으면 다시 만들지만, 잡은 파드가 성공적으로 완료되면 더 이상 재시작하지 않아.
apiVersion: batch/v1
kind: Job
metadata:
name: data-migration
spec:
template:
spec:
containers:
- name: migrate
image: my-migration:1.0
command: ["python", "migrate.py"]
restartPolicy: Never
backoffLimit: 3
- restartPolicy:
Never또는OnFailure야.Always는 Job에서 사용할 수 없어. - backoffLimit: 실패 시 재시도 횟수인데, 기본값은 6이야.
- 파드가 성공적으로 완료되면(exit code 0) 잡은
Complete상태가 돼.
병렬 잡도 가능해:
spec:
completions: 5 # 총 5번 성공해야 완료
parallelism: 2 # 동시에 2개씩 실행
데이터 처리, 배치 작업, DB 마이그레이션 같은 일회성 작업에 쓰지.
**크론잡(CronJob)**은 잡을 스케줄에 따라 반복 실행하는 오브젝트야:
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-backup
spec:
schedule: "0 2 * * *" # 매일 새벽 2시
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: my-backup:1.0
command: ["sh", "-c", "backup.sh"]
restartPolicy: OnFailure
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
schedule은 리눅스 crontab과 같은 형식이야. successfulJobsHistoryLimit으로 완료된 잡 히스토리를 몇 개까지 보관할지 설정할 수 있지.
**데몬셋(DaemonSet)**은 모든 노드(또는 특정 노드)에 파드를 하나씩 배포하는 오브젝트야. 노드가 추가되면 자동으로 해당 노드에 파드가 생성되고, 노드가 제거되면 파드도 삭제돼.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: log-collector
spec:
selector:
matchLabels:
app: log-collector
template:
metadata:
labels:
app: log-collector
spec:
containers:
- name: fluentd
image: fluentd:latest
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
hostPath:
path: /var/log
데몬셋의 대표적인 사용 사례를 보면:
- 로그 수집: Fluentd, Filebeat 같은 로그 수집기. 모든 노드에서 로그를 수집해야 하니까.
- 모니터링 에이전트: node-exporter, Datadog Agent. 노드 메트릭을 수집하지.
- 네트워크 플러그인: kube-proxy, Calico, Flannel. CNI 플러그인은 모든 노드에 있어야 해.
- 스토리지 데몬: Ceph, GlusterFS. 분산 스토리지 시스템이야.
특정 노드에만 배포하려면 nodeSelector나 nodeAffinity를 사용하면 돼:
spec:
template:
spec:
nodeSelector:
role: worker
데몬셋은 스케줄러를 거치지 않고 직접 파드를 배치하기 때문에, 노드의 Taint도 기본적으로 무시해 (tolerations가 자동 추가돼). 하지만 명시적으로 특정 Taint를 tolerate하도록 설정할 수도 있지.
**스테이트풀셋(StatefulSet)**은 상태가 있는(stateful) 애플리케이션을 위한 오브젝트야. 디플로이먼트와 비슷하지만, 파드에 고유한 정체성(identity)을 부여해.
디플로이먼트 vs 스테이트풀셋을 비교하면:
| 특성 | 디플로이먼트 | 스테이트풀셋 |
|---|---|---|
| 파드 이름 | 랜덤 (app-7d8f9c6b-x2k4j) |
순번 (db-0, db-1, db-2) |
| 스토리지 | 공유 또는 없음 | 각 파드에 고유한 PVC |
| 시작/종료 순서 | 동시, 무순서 | 순차적 (0 → 1 → 2) |
| 네트워크 ID | 없음 (서비스로 접근) | 고유 DNS (db-0.db-svc) |
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db
spec:
serviceName: db-svc
replicas: 3
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
containers:
- name: postgres
image: postgres:15
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
핵심 특징을 보면, 안정적인 네트워크 ID가 있어. serviceName에 Headless Service를 지정하면 각 파드에 고유한 DNS가 부여돼. db-0.db-svc.default.svc.cluster.local 형태지. 클러스터 구성에서 마스터/슬레이브를 구분할 때 이 DNS를 사용해.
apiVersion: v1
kind: Service
metadata:
name: db-svc
spec:
clusterIP: None # Headless Service
selector:
app: db
ports:
- port: 5432
고유한 스토리지도 있어. volumeClaimTemplates로 각 파드에 별도의 PVC가 생성되거든. db-0은 data-db-0, db-1은 data-db-1 PVC를 가지지. 파드가 재시작되더라도 같은 PVC에 바인딩되니까 데이터가 보존돼.
순차적 관리도 중요해. 파드가 0, 1, 2 순서로 생성되고, 삭제는 2, 1, 0 역순이야. 스케일 업/다운도 순차적이지. 데이터베이스 클러스터에서 마스터가 먼저 뜨고 슬레이브가 그 다음에 뜨는 순서를 보장할 때 중요해.
스테이트풀셋이 필요한 대표적인 워크로드는 PostgreSQL/MySQL 클러스터, Elasticsearch, Kafka, ZooKeeper, Redis Cluster 같은 거야. 상태 없는 웹 서버나 API 서버라면 디플로이먼트를 쓰면 돼.
정리
13장 읽고 기억할 거 세 가지:
- 잡은 일회성 작업, 크론잡은 반복 작업이다. 완료되면 끝나는 배치 처리에 사용. restartPolicy가
Always가 아니어야 함. - 데몬셋은 모든 노드에 하나씩 배포한다. 로그 수집, 모니터링 에이전트, 네트워크 플러그인 같은 노드 레벨 서비스에 사용.
- 스테이트풀셋은 파드에 고유한 정체성을 부여한다. 안정적인 네트워크 ID, 고유한 스토리지, 순차적 관리가 핵심. 데이터베이스 같은 stateful 워크로드에 사용.