-
Notifications
You must be signed in to change notification settings - Fork 0
KR_CS_StatefulSet
somaz edited this page Mar 30, 2026
·
1 revision
질문: StatefulSet과 Stateless 애플리케이션의 차이를 설명하고, Kubernetes에서 각각의 배포 방법과 스케일링 전략을 설명하세요. Persistent Volume, Headless Service, Pod Identity의 역할을 중심으로 설명하세요.
| 용어 | 설명 |
|---|---|
| StatefulSet | 상태를 가진 애플리케이션을 관리하는 K8s 오브젝트 |
| Stateless Application | 내부 상태를 유지하지 않고 각 요청을 독립 처리하는 애플리케이션 |
| Headless Service | ClusterIP가 None인 서비스 — Pod IP를 직접 반환 |
| Ordinal Index | StatefulSet Pod의 순서 번호 (pod-0, pod-1, pod-2) |
| PVC (PersistentVolumeClaim) | Pod가 PV를 요청하는 오브젝트 |
| volumeClaimTemplates | StatefulSet에서 각 Pod마다 PVC를 자동 생성하는 템플릿 |
Stateless (Deployment): Stateful (StatefulSet):
┌──────┐ ┌──────┐ ┌──────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│Pod A │ │Pod B │ │Pod C │ │ mysql-0 │ │ mysql-1 │ │ mysql-2 │
│ │ │ │ │ │ │ (Master) │ │ (Slave) │ │ (Slave) │
└──────┘ └──────┘ └──────┘ │ PV-0 │ │ PV-1 │ │ PV-2 │
↓ └──────────┘ └──────────┘ └──────────┘
Shared Database └─────── Replication ──────┘
(External State)
| 항목 | Stateless (Deployment) | Stateful (StatefulSet) |
|---|---|---|
| Pod 이름 | 랜덤 (nginx-abc123) | 순서 번호 (mysql-0, mysql-1) |
| 생성 순서 | 동시 생성 가능 | 순차 생성 (0 → 1 → 2) |
| 삭제 순서 | 동시 삭제 가능 | 역순 삭제 (2 → 1 → 0) |
| Network Identity | 불안정 (Pod IP 변경) | 안정적 (DNS 유지) |
| Storage | 공유 또는 없음 | 각 Pod마다 PVC |
| Service Type | ClusterIP / LoadBalancer | Headless + ClusterIP |
| 사용 사례 | 웹 서버, API 서버 | DB, 메시징, 분산 스토리지 |
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"Rolling Update:
-
maxSurge: 1→ 최대 replica+1개까지 동시 실행 허용 -
maxUnavailable: 0→ 항상 replica 수 유지 (무중단)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql-headless # Headless Service 필수
replicas: 3
selector:
matchLabels:
app: mysql
template:
spec:
containers:
- name: mysql
image: mysql:8.0
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumeClaimTemplates: # Pod마다 PVC 자동 생성
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: gp3
resources:
requests:
storage: 10GiclusterIP: None 으로 설정하면 VIP 없이 Pod IP를 직접 반환.
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
spec:
clusterIP: None
selector:
app: mysql
ports:
- port: 3306DNS 조회 결과:
mysql-headless → 10.244.1.10 (mysql-0)
→ 10.244.2.20 (mysql-1)
→ 10.244.3.30 (mysql-2)
개별 Pod DNS:
mysql-0.mysql-headless.default.svc.cluster.local → 10.244.1.10
mysql-1.mysql-headless.default.svc.cluster.local → 10.244.2.20
Pod 재시작 후에도 DNS 이름 유지 → Master/Slave 직접 지정 가능.
- StatefulSet 삭제 시 PVC는 삭제되지 않음 (데이터 보존)
- Pod 재생성 시 기존 PVC 재사용
- PVC 수동 삭제 필요:
kubectl delete pvc mysql-data-mysql-0
볼륨 확장 (StorageClass에서 allowVolumeExpansion: true 필요):
kubectl patch pvc mysql-data-mysql-0 \
-p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'| 전략 | 동작 |
|---|---|
| RollingUpdate (기본) | 역순으로 순차 업데이트 (mysql-2 → mysql-1 → mysql-0) |
| OnDelete | 자동 업데이트 없음, Pod 수동 삭제 시 새 버전으로 재생성 |
| Parallel | 모든 Pod 동시 생성/삭제 (순서 보장 불필요한 경우) |