Files
project-infra/docs/standards/infra/workload-selection.md
T

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축으로 먼저 분류:

  1. 수명: 장기 실행 / 일회성 / 주기성
  2. 상태: stable identity + persistent storage 필요 / 불필요
  3. 배치: 노드별 한 Pod 필요 / cluster-wide 자유 배치

매핑:

  • 장기 + 무상태 + 자유 배치 → Deployment
  • 장기 + stateful + 자유 배치 → StatefulSet (또는 operator)
  • 장기 + 무상태 + 노드별 한 Pod → DaemonSet
  • 일회성 → Job
  • 주기성 → CronJob

2. Deployment는 stateless 장기 실행 기본값

조건:

  • Pod identity가 교체 가능
  • durable state가 외부 DB / 외부 storage / 외부 cache에 있음
  • 수평 확장이 자연스러움
  • Pod 이름 / 순서가 의미 없음

적용 후보:

  • auth-server
  • test-server (장기 실행 모드)
  • 외부 DB 사용하는 keycloak
  • 대부분의 stateless API / worker

필수 동반 리소스 (replicas≥2인 prod 워크로드):

  • PodDisruptionBudget (minAvailable ≥ 50% 또는 SLO tier에 맞춘 값)
  • HorizontalPodAutoscaler v2 (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 참조)
  • volumeClaimTemplates
  • podManagementPolicy: OrderedReady 기본. Parallel은 peer discovery가 순서를 요구하지 않을 때만.
  • updateStrategy: RollingUpdate + partition으로 canary rollout
  • persistentVolumeClaimRetentionPolicy 명시 (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.timeZone v1.25+)

금지:

  • 항상 떠 있어야 하는 서버를 CronJob으로 배포
  • 본 서비스 온라인 처리를 CronJob에 의존

8. Stateful workload는 retention / scale-down 정책을 먼저 박는다

StatefulSet의 persistentVolumeClaimRetentionPolicy:

  • whenDeleted (StatefulSet이 삭제될 때 PVC 처리): Retain (기본) / Delete
  • whenScaled (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 기본 → Cluster CRD. 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_INDEX env로 자기 작업 식별
  • 더 복잡한 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 조건에만