목차
- 1. 왜 Kubernetes StatefulSet vs Deployment가 중요한가
- 2. 개념부터 쉽게 정리해보겠습니다
- 2-1. Deployment란?
- 2-2. StatefulSet이란?
- 3. 핵심 차이점 비교: Kubernetes StatefulSet vs Deployment
- 3-1. 언제 Deployment를 선택하나
- 3-2. 언제 StatefulSet을 선택하나
- 4. 실전 구현 1: Deployment로 Stateless 앱 배포
- 5. 실전 구현 2: StatefulSet으로 상태 저장 애플리케이션 배포
- 6. ⚠️ 실제로 많이 겪는 문제와 트러블슈팅
- 6-1. Deployment에 데이터베이스를 올리고 나중에 후회하는 경우
- 6-2. Headless Service를 빼먹는 경우
- 6-3. PVC가 남는 걸 보고 당황하는 경우
- 6-4. 순서 의존성을 무시하고 병렬처럼 다루는 경우
- 7. 검증 방법: 내가 만든 배포가 의도대로 동작하는지 확인
- 7-1. Deployment 검증
- 7-2. StatefulSet 검증
- 8. 자주 묻는 질문과 정리
- 8-1. Kubernetes StatefulSet vs Deployment: PVC를 붙이면 차이가 없나요?
- 8-2. 모든 데이터베이스는 무조건 StatefulSet인가요?
- 8-3. 캐시는 어떤 걸 써야 하나요?
- 8-4. 결국 어떤 기준으로 결정하면 되나요?
[Kubernetes] Kubernetes StatefulSet vs Deployment 비교 분석
Kubernetes StatefulSet vs Deployment를 처음 제대로 구분하게 된 건, 홈랩에서 데이터베이스를 올렸다가 볼륨이 꼬이면서 한참 삽질했을 때였습니다. 처음엔 둘 다 그냥 Pod(파드)를 여러 개 띄우는 Kubernetes 워크로드(workload, 애플리케이션 실행 단위)겠거니 싶었거든요. 근데 실제로 운영해보니까 차이가 꽤 크더라고요. 특히 상태 저장 애플리케이션(stateful application, 데이터와 식별성이 중요한 앱) 쪽은 정말 그랬습니다. 웹 API처럼 가볍게 교체되는 애플리케이션 배포는 Deployment(디플로이먼트)가 정말 편한데, MySQL이나 PostgreSQL 같은 건 접근을 잘못하면 나중에 복구할 때 진짜 식은땀이 나더라고요.
혹시 이런 경험 있으신가요? 애플리케이션은 잘 떴는데, 재시작 후 데이터 경로가 달라지거나 Pod 이름이 바뀌면서 클러스터 구성이 꼬이는 상황 말입니다. 여기서 중요한 포인트! Kubernetes StatefulSet vs Deployment는 단순히 생성 방식만 다른 게 아니라, 애플리케이션의 정체성(identity), 저장소(storage), 배포 순서(ordering)를 다루는 철학 자체가 다릅니다.
이번 글에서는 제가 직접 홈랩에서 써보며 정리한 기준으로, Kubernetes StatefulSet vs Deployment 차이를 실무 감각으로 풀어보겠습니다. 단순 정의만 보면 헷갈리기 쉬우니까, 실제 YAML 예제와 트러블슈팅까지 같이 보시죠. 이전 글에서 다룬 Persistent Volume(PV, 영구 볼륨)과 StorageClass(스토리지 클래스) 내용을 같이 보시면 이해가 더 빨라집니다. 다음 글에서는 Helm(헬름, 쿠버네티스 패키지 매니저)으로 상태 저장 애플리케이션 배포 자동화하는 방법도 다룰 예정입니다.
Deployment와 StatefulSet이 Pod, Service, Volume을 어떻게 다르게 다루는지 한눈에 보는 개요 이미지입니다.
1. 왜 Kubernetes StatefulSet vs Deployment가 중요한가
쉽게 말해 Deployment는 언제든 교체 가능한 복제본을 잘 다루고, StatefulSet은 각 인스턴스가 자기 이름과 저장소를 유지해야 하는 경우를 잘 다룹니다.
예를 들어 보겠습니다.
- 웹 프론트엔드나 API 서버는 Pod가 하나 죽어도 새 Pod가 뜨면 보통 괜찮습니다.
- 반면 데이터베이스나 메시지 큐(message queue, 비동기 메시지 처리 시스템)는 각 인스턴스가 가진 데이터와 순서가 중요거든요.
- 캐시 서버도 단일 노드냐 클러스터 구성이냐에 따라 선택이 달라집니다.
제가 처음엔 Redis를 무조건 Deployment로 올렸었는데요. 단일 캐시 테스트 용도에선 괜찮았는데, 나중에 persistent volume을 붙이고 노드 재스케줄링이 일어나니까 예상과 다르게 동작하는 부분이 있었어요. 그때 느낀 게, 상태 저장 애플리케이션은 살아 있는 데이터만 보는 게 아니라, 재시작 이후의 동일성까지 봐야 한다는 점이었습니다.
2. 개념부터 쉽게 정리해보겠습니다
2-1. Deployment란?
Deployment는 ReplicaSet(레플리카셋, 동일 Pod 복제 관리)을 통해 여러 Pod를 선언적으로 관리하는 방식입니다. 주 목적은 무중단에 가깝게 애플리케이션 배포를 반복 가능하게 만드는 것입니다.
- Pod 이름은 매번 바뀔 수 있습니다.
- 특정 Pod가 죽어도 새 Pod가 대체되면 됩니다.
- Rolling Update(롤링 업데이트, 순차 교체)가 편하죠.
- 웹 서버, API 서버, 워커(worker, 백그라운드 작업 프로세스)에 잘 맞습니다.
2-2. StatefulSet이란?
StatefulSet은 이름 그대로 상태(state)를 가진 워크로드를 위한 리소스입니다. 각 Pod가 고정된 네트워크 식별자와 안정적인 스토리지 연결을 유지하도록 설계되어 있거든요.
- Pod 이름이 ordinal(순번) 기반으로 고정됩니다. 예:
db-0,db-1 - 생성/삭제 순서가 제어됩니다.
- 각 Pod마다 독립적인 PersistentVolumeClaim(PVC, 영구 볼륨 요청)이 붙을 수 있습니다.
- 데이터베이스, ZooKeeper, Kafka 계열, 복제 구조가 있는 저장소에 자주 씁니다.
저도 처음엔 이게 뭔가 싶었는데, 실제로 써보니까 StatefulSet은 Pod를 복제한다기보다, 번호가 붙은 개별 인스턴스를 관리한다는 느낌으로 이해하는 게 가장 쉽더라고요.
3. 핵심 차이점 비교: Kubernetes StatefulSet vs Deployment
| 항목 | Deployment | StatefulSet |
|---|---|---|
| 주 용도 | Stateless 애플리케이션 배포 | Stateful 애플리케이션 배포 |
| Pod 이름 | 가변적 | 고정적 순번 부여 |
| 스토리지 | 공유 또는 외부 스토리지 중심 | Pod별 고정 스토리지 할당 가능 |
| 생성/종료 순서 | 순서 보장 약함 | 순차 생성, 순차 종료 |
| 네트워크 식별성 | Pod 교체 시 변경 가능 | 안정적인 DNS 이름 유지 |
| 대표 사용 사례 | 웹, API, 배치 워커 | DB, 분산 저장소, 클러스터형 메시지 시스템 |
여기서 독자분들이 가장 헷갈리는 부분이 스토리지입니다. Deployment에도 PVC를 붙일 수는 있습니다. 그래서 겉보기엔 둘 차이가 없어 보일 수 있어요. 근데 StatefulSet은 각 Pod가 자기 볼륨을 안정적으로 유지해야 하는 구조를 전제로 설계되어 있거든요. 이 차이가 운영 중엔 꽤 크게 작용합니다.
3-1. 언제 Deployment를 선택하나
- Pod가 교체돼도 서비스만 유지되면 되는 경우
- 세션 상태를 외부 Redis나 DB에 저장하는 경우
- 스케일 아웃/인 빈도가 잦은 경우
- CI/CD로 잦은 애플리케이션 배포가 필요한 경우
3-2. 언제 StatefulSet을 선택하나
- 각 인스턴스마다 고유 ID가 필요한 경우
- 볼륨을 Pod별로 안정적으로 유지해야 하는 경우
- 클러스터 합류 순서나 부팅 순서가 중요한 경우
- 상태 저장 애플리케이션 특성상 재시작 후에도 동일한 엔드포인트가 필요한 경우
실제로 써보니까, 애매하면 먼저 데이터의 소유권이 누구에게 붙는지를 보면 판단이 쉽습니다. 데이터가 서비스 전체에 느슨하게 연결되면 Deployment 쪽, 데이터가 특정 인스턴스에 강하게 묶이면 StatefulSet 쪽이더라고요.
4. 실전 구현 1: Deployment로 Stateless 앱 배포
먼저 Nginx(엔진엑스, 웹 서버)를 Deployment로 배포해보겠습니다. 이 예제는 구조를 이해하기 위한 가장 기본적인 형태입니다.
- Deployment 매니페스트를 작성합니다.
- Service(서비스, 네트워크 접근 추상화)로 노출합니다.
- 롤링 업데이트와 스케일링을 확인합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
type: ClusterIP
kubectl apply -f web-deployment.yaml
kubectl get deploy,pods,svc -o wide
이 상태에서 Pod 하나가 내려가도 새 Pod가 올라오면 됩니다. 이름이 바뀌어도 크게 문제되지 않죠. 바로 이 특성이 Deployment의 장점입니다.
업데이트도 간단합니다.
kubectl set image deployment/web-deployment nginx=nginx:latest
kubectl rollout status deployment/web-deployment
제가 직접 해보니 테스트 환경이나 프론트엔드 계층은 거의 이 패턴으로 끝나더라고요. 단순하고, 빠르고, 운영 피로도가 낮습니다. 드디어 됐다! 싶은 순간이 자주 오는 쪽이죠.
Deployment가 ReplicaSet과 함께 Pod를 순차 교체하는 흐름을 설명하는 이미지입니다.
5. 실전 구현 2: StatefulSet으로 상태 저장 애플리케이션 배포
이번엔 StatefulSet 예제를 보겠습니다. 여기서는 이해를 위해 간단한 Nginx 이미지를 쓰되, 핵심은 고정된 Pod 이름과 volumeClaimTemplates 구조를 보는 데 있습니다. 실제 운영에서는 MySQL, PostgreSQL, Redis 클러스터, RabbitMQ 같은 워크로드에서 더 의미가 커요.
StatefulSet은 보통 Headless Service(헤드리스 서비스, 개별 Pod 식별을 위한 서비스)와 함께 사용합니다.
apiVersion: v1
kind: Service
metadata:
name: web-headless
spec:
clusterIP: None
selector:
app: web-stateful
ports:
- port: 80
name: http
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web-stateful
spec:
serviceName: web-headless
replicas: 3
selector:
matchLabels:
app: web-stateful
template:
metadata:
labels:
app: web-stateful
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- containerPort: 80
name: http
volumeMounts:
- name: web-data
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: web-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
kubectl apply -f web-statefulset.yaml
kubectl get statefulset,pods,pvc,svc
적용 후 보면 Pod가 이런 식으로 생성됩니다.
web-stateful-0web-stateful-1web-stateful-2
그리고 PVC도 Pod별로 따로 붙습니다. 이게 진짜 중요합니다. 예를 들어 web-data-web-stateful-0 같은 식으로 각 인스턴스가 자기 스토리지를 계속 들고 가거든요.
여기서 중요한 포인트! StatefulSet은 삭제 후 다시 생성되어도 같은 이름 규칙과 볼륨 연결을 유지하는 데 초점이 있습니다. 이 특성 덕분에 상태 저장 애플리케이션 운영이 가능해집니다.
kubectl delete pod web-stateful-1
kubectl get pods -w
이렇게 해보면 동일한 ordinal을 가진 Pod가 다시 올라옵니다. 제가 홈랩에서 PostgreSQL 실험할 때도 이 패턴 덕분에 노드 교체 후 구조를 이해하기 쉬웠습니다. 물론 데이터 정합성은 애플리케이션 레벨에서 별도로 봐야 하지만요.
6. ⚠️ 실제로 많이 겪는 문제와 트러블슈팅
6-1. Deployment에 데이터베이스를 올리고 나중에 후회하는 경우
이거 진짜 자주 봅니다. 처음엔 빠르게 띄우려고 Deployment로 시작하거든요. 근데 운영 중에 Pod가 교체되고, 스토리지 붙는 방식이 예상과 다르면 문제를 마주하게 됩니다.
- Pod 이름이 바뀌어 클러스터 노드 인식이 꼬임
- 단일 PVC 공유 구조가 애플리케이션 특성과 맞지 않음
- 복제본 간 데이터 소유권이 불명확해짐
해결 방향: 데이터가 인스턴스별로 귀속되는 구조라면 StatefulSet으로 전환을 검토해야 합니다.
6-2. Headless Service를 빼먹는 경우
저도 처음엔 왜 서비스가 꼭 필요하지? 했었는데, StatefulSet에서 안정적인 네트워크 식별성을 얻으려면 Headless Service가 사실상 핵심이거든요.
kubectl get svc web-headless
kubectl describe statefulset web-stateful
Pod 간 통신이나 클러스터 초기화가 필요한 앱이라면 이 부분을 꼭 확인하세요.
6-3. PVC가 남는 걸 보고 당황하는 경우
StatefulSet을 줄였는데 볼륨이 바로 안 지워져서 당황하는 경우가 있습니다. 근데 이건 오히려 안전장치에 가깝습니다. 실수로 데이터가 날아가면 더 큰일이거든요.
주의: StatefulSet 삭제가 곧 데이터 삭제를 의미하지는 않습니다. 스토리지 정책과 reclaim policy를 같이 확인해야 합니다.
6-4. 순서 의존성을 무시하고 병렬처럼 다루는 경우
StatefulSet은 생성과 종료 순서가 의미가 있습니다. 특히 클러스터형 데이터베이스나 합의 기반 시스템은 더 그렇습니다. 그래서 readiness probe, startup probe 같은 헬스체크도 같이 설계해야 하죠. 저도 이걸 대충 봤다가 부팅 순서 꼬여서 한참 로그만 들여다봤습니다 ㅎㅎ
StatefulSet에서 각 Pod가 독립적인 영구 볼륨과 DNS 이름을 갖는 구조를 설명하는 이미지입니다.
7. 검증 방법: 내가 만든 배포가 의도대로 동작하는지 확인
설정이 끝났으면 꼭 검증해야 합니다. YAML만 맞다고 끝이 아니더라고요. 실제로 재시작, 스케일링, 이름 유지 여부를 봐야 합니다.
7-1. Deployment 검증
kubectl get deployment web-deployment
kubectl rollout history deployment/web-deployment
kubectl scale deployment web-deployment --replicas=5
kubectl get pods -l app=web
- Pod 수가 바로 조정되는지
- 업데이트 중 서비스 중단이 없는지
- 새 Pod 이름이 생성되어도 서비스 접근이 유지되는지
7-2. StatefulSet 검증
kubectl get statefulset web-stateful
kubectl get pods -l app=web-stateful
kubectl get pvc
kubectl scale statefulset web-stateful --replicas=2
kubectl get pods,pvc
- Pod가 역순으로 종료되는지
- 줄였다가 다시 늘렸을 때 ordinal이 유지되는지
- PVC가 각 Pod에 맞게 보존되는지
🎉 여기서 원하는 대로 동작하면 거의 감이 옵니다. Deployment는 교체 가능한 인스턴스 관리에 최적화되어 있고, StatefulSet은 상태와 순서를 존중하는 구조라는 점이 실제 결과에서 드러납니다.
배포 후 Pod, PVC, 롤아웃 상태를 검증하는 운영 화면 느낌의 이미지입니다.
8. 자주 묻는 질문과 정리
8-1. Kubernetes StatefulSet vs Deployment: PVC를 붙이면 차이가 없나요?
비슷해 보일 수는 있지만 다릅니다. 핵심은 Pod별 고정 정체성과 순서 보장입니다. PVC 하나 붙였다고 StatefulSet의 운영 특성이 생기지는 않습니다.
8-2. 모든 데이터베이스는 무조건 StatefulSet인가요?
대체로 그렇지만, 실제 운영 구조에 따라 외부 매니지드 데이터베이스를 쓰면 Kubernetes 안에 직접 올리지 않을 수도 있습니다. 즉, 워크로드 선택은 애플리케이션 구조 전체를 봐야 합니다.
8-3. 캐시는 어떤 걸 써야 하나요?
단순 캐시, 세션 캐시처럼 날아가도 되는 구조는 Deployment가 편합니다. 반면 복제, 영속성, 노드 식별이 중요해지면 StatefulSet 쪽을 봐야 합니다.
8-4. 결국 어떤 기준으로 결정하면 되나요?
- Pod가 바뀌어도 되는가?
- 각 인스턴스가 자기 데이터를 가져야 하는가?
- 이름과 네트워크 식별성이 유지되어야 하는가?
- 생성/종료 순서가 중요한가?
이 네 가지에 하나라도 강하게 해당되면 StatefulSet을 우선 검토해보세요.
정리해보겠습니다.
- Deployment: 빠르고 유연한 애플리케이션 배포, stateless 워크로드에 적합
- StatefulSet: 상태 저장 애플리케이션, 고정 이름, 고정 스토리지, 순서 제어에 적합
저도 처음엔 Kubernetes StatefulSet vs Deployment를 너무 단순하게 봤었는데, 실제로 운영해보니까 선택이 잘못되면 나중에 구조를 다시 뜯어고쳐야 하더라고요. 특히 홈랩처럼 이것저것 실험하는 환경에서는 처음부터 정답을 맞히기 어렵습니다. 그래서 더더욱 워크로드의 상태 특성을 먼저 보는 습관이 중요합니다.
💡 팁 하나 남기자면, 처음 설계할 때는 "이 Pod가 내일 사라져도 괜찮은가?"를 스스로에게 물어보세요. 괜찮으면 Deployment일 가능성이 높고, 안 괜찮으면 StatefulSet을 봐야 합니다.
마지막으로, 다음 글에서는 StatefulSet 기반 데이터베이스를 백업/복구 관점에서 어떻게 설계하면 좋은지 다뤄보겠습니다. 그 글까지 같이 보시면 Kubernetes 워크로드 선택 감이 훨씬 또렷해지실 겁니다.
어떤 워크로드에 Deployment를 쓰고, 어떤 경우 StatefulSet을 써야 하는지 요약한 비교 이미지입니다.
'IT > k8s' 카테고리의 다른 글
| [k8s] Prometheus Operator vs 직접 설정: Kubernetes 모니터링 실전 비교 분석 (1) | 2026.07.18 |
|---|---|
| [Kubernetes] Kubernetes PodSecurity 도입 전후 비교: 보안 강화 사례 연구 (0) | 2026.07.17 |
| [Kubernetes] Karpenter 오토스케일러 1년 사용 후기: 비용 절감과 성능 최적화 회고 (0) | 2026.07.17 |
| [k8s] Backstage 운영 후기: 개발자 포털 1년 회고와 정착 과정 (0) | 2026.07.14 |
| [k8s] Pod Security Standards 마이그레이션: Kubernetes PSP에서 안전하게 전환하기 (0) | 2026.07.14 |
| [k8s] Karpenter 오토스케일로 EKS 비용 절감 검증하는 방법 (1) | 2026.07.14 |