15 KiB
workload selection 기준
목적
이 문서는 각 컴포넌트를
- Deployment
- StatefulSet
- DaemonSet
- Job
- CronJob
중 무엇으로 배포할지 먼저 고정한다.
목표:
- 상태 저장 / 무상태 / 노드로컬 / 일회성 / 주기성 워크로드를 섞지 않는다
- PVC가 필요하다는 이유만으로 StatefulSet을 선택하는 실수를 막는다
- Ingress controller / CNI / CSI / 로그 shipper / node-exporter 같은 노드로컬 에이전트를 Deployment로 배포하는 실수를 막는다
- migration / bootstrap / 백업을 장기 실행 앱과 분리한다
- 1000+ 서비스 스케일에서 operator-managed 패턴이 기본인 영역(DB, Kafka, monitoring)은 operator를 기본 선택으로 문서화한다
공식 의미 (근거)
- Deployment: stateless 장기 실행.
spec.replicas기반 수평 확장. ReplicaSet으로 rolling update.https://kubernetes.io/docs/concepts/workloads/controllers/deployment/. - StatefulSet: stable network identity, stable persistent storage, ordered deployment/scaling. 각 Pod는
<name>-<ordinal>이름을 가지고 PVC가volumeClaimTemplates로 자동 생성.persistentVolumeClaimRetentionPolicy(GA since 1.27) 필드: 기본값{whenDeleted: Retain, whenScaled: Retain}.podManagementPolicy(OrderedReady / Parallel).updateStrategy(RollingUpdate / OnDelete). - DaemonSet: 선택된 모든 노드에 정확히 한 Pod를 실행. 노드 추가/제거에 따라 자동 생성/삭제.
https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/. - Job: 한 번 실행되어 완료.
restartPolicy: Never | OnFailure.backoffLimit/activeDeadlineSeconds/ttlSecondsAfterFinished/parallelism/completions. - CronJob: 시간 기반 스케줄 Job.
concurrencyPolicy: Allow | Forbid | Replace,startingDeadlineSeconds,successfulJobsHistoryLimit/failedJobsHistoryLimit. - Operator pattern: CRD + controller. 1000-서비스 스케일에서 DB/Kafka/Redis/monitoring은 사실상 Deployment/StatefulSet을 직접 쓰지 않고 operator가 소유.
기본 규칙
1. 기본 선택 기준은 "상태 + 수명 + 배치 위치"
3축으로 먼저 분류:
- 수명: 장기 실행 / 일회성 / 주기성
- 상태: stable identity + persistent storage 필요 / 불필요
- 배치: 노드별 한 Pod 필요 / cluster-wide 자유 배치
매핑:
- 장기 + 무상태 + 자유 배치 → Deployment
- 장기 + stateful + 자유 배치 → StatefulSet (또는 operator)
- 장기 + 무상태 + 노드별 한 Pod → DaemonSet
- 일회성 → Job
- 주기성 → CronJob
2. Deployment는 stateless 장기 실행 기본값
조건:
- Pod identity가 교체 가능
- durable state가 외부 DB / 외부 storage / 외부 cache에 있음
- 수평 확장이 자연스러움
- Pod 이름 / 순서가 의미 없음
적용 후보:
auth-servertest-server(장기 실행 모드)- 외부 DB 사용하는
keycloak - 대부분의 stateless API / worker
필수 동반 리소스 (replicas≥2인 prod 워크로드):
PodDisruptionBudget(minAvailable ≥ 50% 또는 SLO tier에 맞춘 값)HorizontalPodAutoscalerv2 (behavior 포함)topologySpreadConstraints(zone + hostname)ServiceMonitor또는 Prometheus scrape annotation
3. StatefulSet은 "stable identity + storage" 모두 맞을 때만
조건 중 하나라도 강하면:
- stable network identity (DNS name per replica) 필요
- stable persistent storage per Pod 필요
- ordered rollout / termination 필요
- replica 간 peer discovery가 ordinal에 의존
적용 후보:
postgres(operator 없을 때 — 있으면 CloudNativePG 같은 operator 우선)minio(MinIO Operator 가능)vault(Raft storage mode)etcd(외부)kafka,zookeeper(Strimzi operator 우선)elasticsearch(ECK operator 우선)
필수 선언:
serviceName(headless Service 참조)volumeClaimTemplatespodManagementPolicy: OrderedReady기본. Parallel은 peer discovery가 순서를 요구하지 않을 때만.updateStrategy: RollingUpdate+partition으로 canary rolloutpersistentVolumeClaimRetentionPolicy명시 (prod 기본{whenDeleted: Retain, whenScaled: Retain})
4. DaemonSet은 노드 전역 에이전트 전용
조건:
- 노드별 한 개만 떠야 함 (또는 특정 노드 group에 한 개)
- 노드 추가/제거에 자동 반응
- hostPath / hostNetwork / hostPID 필요한 경우 다수
적용 후보:
- 로그 shipper:
fluent-bit,fluentd,vector - metric exporter:
node-exporter,cadvisor - CNI agent:
calico-node,cilium-agent - CSI node plugin:
longhorn-manager,ceph-csi-node - security agent:
falco,tetragon - service mesh node proxy:
istio-cni-node - ingress-nginx DaemonSet 모드 (edge 노드가 고정되고 모든 edge 노드가 80/443 HostPort / hostNetwork로 외부 노출해야 할 때)
Ingress controller: DaemonSet vs Deployment 결정:
- Deployment +
Service type=LoadBalancer(MetalLB / 외부 LB): 기본 권장. 노드와 ingress replica 수가 분리됨. HPA 적용 가능. - DaemonSet +
hostNetwork: true/ HostPort 80,443: bare-metal + 외부 LB 없이 모든 노드가 ingress가 되어야 할 때. 80/443 노드 포트 점유, HPA 불가, 노드 수 = replica 수.
필수:
tolerations로 노드 taint (예:node-role.kubernetes.io/control-plane) 대응 결정nodeSelector또는affinity로 대상 노드 그룹 명시 (label 기반)updateStrategy: RollingUpdate+maxUnavailable지정priorityClassName: system-node-critical(필수 인프라 에이전트)
5. PVC가 있다고 무조건 StatefulSet 아니다
체크리스트:
- Pod마다 고유한 storage identity 필요? 아니면 단일 PVC 공유?
- Pod 이름 / 순서가 의미 있나?
- peer discovery가 stable DNS name에 의존?
아니면:
- 단일 replica Deployment + PVC (ReadWriteOnce) 도 유효
- Deployment + ReadWriteMany PVC (여러 replica가 동일 storage 공유) 도 유효 (shared cache 등)
6. Job은 migration / bootstrap / one-off 기본값
적용 후보:
flyway-migrate/liquibase-migrate- schema validation
- 초기 admin 사용자 bootstrap
- 데이터 리페어 / 정리
- 이미지 빌드 trigger
필수:
restartPolicy: Never(실패 원인 디버깅 가능) 또는OnFailure(transient 실패 재시도)backoffLimit명시 (기본값 6은 prod에서 너무 관대할 수 있음)activeDeadlineSeconds(무한 실행 방지)ttlSecondsAfterFinished(완료 Job 자동 정리, 1000-서비스 스케일 필수)- ServiceAccount 최소 권한
7. CronJob은 주기 실행 전용
적용 후보:
- etcd / DB 백업
- 정기 정리 (old PVC, old Snapshot, old Job)
- 정기 검증 / 리포트
- 비즈니스 배치 (야간 집계)
필수:
concurrencyPolicy: Forbid기본 (동시 실행 방지). 멱등하면Allow.startingDeadlineSeconds(노드 장애로 miss 된 job 무한 누적 방지)successfulJobsHistoryLimit: 3/failedJobsHistoryLimit: 5- schedule timezone 명시 (
spec.timeZonev1.25+)
금지:
- 항상 떠 있어야 하는 서버를 CronJob으로 배포
- 본 서비스 온라인 처리를 CronJob에 의존
8. Stateful workload는 retention / scale-down 정책을 먼저 박는다
StatefulSet의 persistentVolumeClaimRetentionPolicy:
whenDeleted(StatefulSet이 삭제될 때 PVC 처리):Retain(기본) /DeletewhenScaled(replica 축소될 때 PVC 처리):Retain(기본) /Delete
prod 기본: {whenDeleted: Retain, whenScaled: Retain} (기본값). DB/Vault/MinIO 모두 여기서 이탈하지 않는다.
dev/staging: {whenDeleted: Delete, whenScaled: Delete} 허용 (클러스터 재생성 시 자동 정리).
9. 외부 DB를 쓰는 앱 서버는 stateless 우선
Pod에 durable state가 없으면 Deployment. Pod identity가 고정되어야 한다는 이유만으로 StatefulSet 선택 금지.
기준:
auth-server→ Deployment- 외부 DB 사용
keycloak→ Deployment (caching은 external Redis / Infinispan cluster) - 외부 object store 사용 앱 → Deployment
10. Keycloak은 앱 레이어와 저장소를 분리
Keycloak 서버 자체는 stateless로 다룬다.
- 외부 DB (PostgreSQL) 사용이 prod 기본
- session / cache는 Infinispan embedded 또는 remote 모드 결정 (remote 선호, replica 간 peer discovery는 Kubernetes DNS)
- Deployment + externalTrafficPolicy 고려
- HA replica ≥ 2 + PDB
11. Vault는 모드별로 다르다
- dev mode: 학습 전용. prod 절대 금지.
- standalone (file storage): StatefulSet + PVC. replica=1. 단일 장애점.
- HA Raft: StatefulSet (integrated storage). replica 3 또는 5.
podManagementPolicy: Parallel허용. - HA Consul backend: StatefulSet (Vault) + StatefulSet (Consul). operator 권장.
- external Vault: 클러스터 내부 서버 없음, ExternalSecrets로 참조만.
prod 권장: HA Raft mode StatefulSet (replica 3) 또는 external Vault.
12. MinIO는 Operator 기본 (StatefulSet은 fallback)
1000-서비스 스케일에서 MinIO는 MinIO Operator + Tenant CRD가 기본. tenant가 StatefulSet을 내부적으로 생성.
raw StatefulSet은 단일 node/dev 환경에서만 예외 허용.
13. Flyway는 Job 기본값
- 앱 startup 내부 migration 금지 (앱 부팅 실패와 migration 실패가 섞임)
- Flyway Job이 선행되고 Success 후에 Deployment rollout
- ArgoCD PostSync hook 또는 Argo Workflows로 순서 제어
migrate,validate,info,repair각각 독립 Job
14. Ingress controller 배치 결정
prod 권장:
- ingress-nginx Deployment +
Service type=LoadBalancer(MetalLB L2 또는 BGP, 또는 외부 LB) - 또는 Envoy Gateway / Gateway API 기반 Deployment
- HPA 가능, PDB 필수 (tier-1 로 취급)
- 복수 IngressClass (
nginx-public,nginx-internal) 분리
DaemonSet 선택 조건:
- edge 노드가 고정되어 있고 hostNetwork 80/443이 필요
- 외부 LB가 없고 DNS round-robin으로 다수 노드 IP 노출
15. DB는 operator 기본, StatefulSet은 fallback
1000-서비스 스케일의 PostgreSQL:
- CloudNativePG Operator 기본 →
ClusterCRD. operator가 StatefulSet/Service/Secret/ConfigMap/Backup 전부 관리. - Zalando Postgres Operator도 대안
- raw StatefulSet은 dev / 특수 케이스에만
MySQL/MariaDB:
- MariaDB Operator / mysql-operator
Redis:
- Spotahome redis-operator / Redis Enterprise Operator
- cluster 모드면 StatefulSet, sentinel 모드면 Deployment(sentinel) + StatefulSet(redis)
16. Batch / 대량 병렬은 Job + parallelism + IndexedJob
단일 Job으로 수천 개 task 병렬 실행:
completionMode: Indexed+parallelism: N- 각 Pod가
JOB_COMPLETION_INDEXenv로 자기 작업 식별 - 더 복잡한 DAG는 Argo Workflows / Tekton
17. workload 종류만 맞는다고 품질이 보장되지 않는다
최종 결정 전 동반 표준 확인:
storage-pvc.md(StorageClass / volumeClaimTemplate / snapshot)network-ingress-tls.md(ingressClassName / TLS)resources-probes-availability.md(PDB / HPA / probe / resources)backup-restore.md(RPO / RTO / 절차)security-podsecurity.md(PSA / seccomp / capabilities)observability.md(ServiceMonitor / log shipping)
18. priority class / preemption 전략
- 플랫폼 에이전트 (CNI, CSI, log shipper, node-exporter):
system-node-critical - 클러스터 컨트롤러 (cert-manager, external-secrets, operator):
system-cluster-critical - 비즈니스 tier-1: 커스텀
tier-1-critical(value 1000000) - 비즈니스 tier-2:
tier-2(value 100000) - 비즈니스 tier-3 / batch:
tier-3(value 10000)
현재 스택 기본 권장안 (prod)
| 컴포넌트 | workload 종류 | operator | 비고 |
|---|---|---|---|
auth-server |
Deployment | — | tier-1 HPA+PDB |
test-server (장기) |
Deployment | — | |
test-server (검증) |
Job | — | ttlSecondsAfterFinished |
keycloak |
Deployment (외부 DB) | — | HA replicas≥2 |
postgres-identity |
StatefulSet (via CNPG) | CloudNativePG | replica 3 |
vault |
StatefulSet (Raft) | Vault Operator | replica 3 |
minio |
StatefulSet (via Tenant) | MinIO Operator | |
kafka |
StatefulSet (via Strimzi) | Strimzi | |
redis |
StatefulSet (via operator) | redis-operator | sentinel 또는 cluster 모드 |
flyway-migrate |
Job | — | ArgoCD PostSync hook |
postgres-backup |
CronJob | CNPG ScheduledBkp | operator가 소유 |
ingress-nginx |
Deployment + MetalLB | — | public / internal 분리 |
cert-manager |
Deployment | — | system-cluster-critical |
external-secrets |
Deployment | — | system-cluster-critical |
prometheus |
StatefulSet (via Prometheus) | Prometheus Op | |
fluent-bit |
DaemonSet | — | system-node-critical |
node-exporter |
DaemonSet | — | system-node-critical |
cilium-agent |
DaemonSet | Cilium Op (opt) | system-node-critical |
longhorn-manager |
DaemonSet | Longhorn |
프로젝트 기준 요약
- stateless 장기 → Deployment (+PDB+HPA+topologySpread 필수)
- stateful + stable identity/storage → StatefulSet (또는 operator)
- 노드 전역 에이전트 → DaemonSet
- 일회성 → Job (ttlSecondsAfterFinished 필수)
- 주기성 → CronJob (concurrencyPolicy + startingDeadlineSeconds)
- PVC ≠ StatefulSet 신호 전부 아님
- DB/Kafka/Redis/Prometheus는 operator 기본
persistentVolumeClaimRetentionPolicy명시, prod는 Retain/Retain- Flyway는 Job, 앱 startup 내부 migration 금지
- ingress controller는 Deployment+LB 기본, DaemonSet은 edge 조건에만