
StatefulSet은 말 그대로
“상태(State)를 가진 파드를 순서대로 생성·유지하는 컨트롤러”이다.
Deployment는 파드를 아무 순서나 생성·삭제하지만,
StatefulSet은 순서를 엄격히 지킨다.
예를 들어,
즉, DB나 캐시처럼 데이터 보존이 중요한 서비스에 쓰인다.
ex)MySQL, Redis, Kafka, ZooKeeper 등
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "web"
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx
ports:
- containerPort: 80
name: web
이건 간단히 Nginx 파드 3개를 순서대로 만드는 StatefulSet 예시다.
동작 설명 생성 순서 web-0 → web-1 → web-2삭제 순서 web-2 → web-1 → web-0각 파드 고유한 이름과 PVC를 가짐 사용 사례 MySQL, Redis, Kafka, ZooKeeper 등
StatefulSet은 Headless Service와 함께 동작해야 한다.
즉, 두 개의 YAML 파일이 필요하다.
StatefulSet 파드들이 DNS 이름으로 서로 통신할 수 있게 해주는 서비스다.
vim statefulset-svc.yaml
하고 밑에 있는 스크립트를 복사붙여넣기 한다.
apiVersion: v1
kind: Service
metadata:
name: web
labels:
app: web
spec:
ports:
- port: 80
name: web
clusterIP: None #Headless Service (ClusterIP 없음)
selector:
app: web
StatefulSet이 순서대로 파드를 생성하고, 각 파드마다 고유한 이름을 부여한다.
vim statefulset.yaml
하고 밑에 있는 스크립트를 복사붙여넣기 한다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "web"
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeClaimTemplates:
- metadata:
name: web-storage
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: hostpath
resources:
requests:
storage: 1Gi
clusterIP: None 으로 지정하면, 파드별로 web-0.web, web-1.web 같은 고유 DNS 이름이 생성된다.
vim pv.yaml
으로 파일을 밑에 있는 스크립트로 복붙해준다.
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: PersistentVolume
metadata:
name: web-pv-0
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
hostPath:
path: /data/web-storage-0
storageClassName: hostpath
- apiVersion: v1
kind: PersistentVolume
metadata:
name: web-pv-1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
hostPath:
path: /data/web-storage-1
storageClassName: hostpath
- apiVersion: v1
kind: PersistentVolume
metadata:
name: web-pv-2
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
hostPath:
path: /data/web-storage-2
storageClassName: hostpath
kubectl apply -f pv.yaml
kubectl get pv
kubectl get pvc
STATUS가 Bound로 바뀌면 PVC와 PV가 연결된 것이다.
kubectl apply -f statefulset-svc.yaml
kubectl apply -f statefulset.yaml

kubectl apply -f statefulset-svc.yaml

하여 Headless Service를 생성한다.
kubectl apply -f statefulset.yaml

하여 StatefulSet를 생성한다.
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 1m
web-1 1/1 Running 0 40s
web-2 1/1 Running 0 15s
→ 순서대로 web-0, web-1, web-2가 생성된 것을 확인할 수 있다.

이 명령어를 실행하여 파드가 순서대로 생성되었는지 확인할 수 있다.
이렇게 0부터 1 순서대로 생성되는 것을 확인할 수 있다.

아래 순서대로 삭제하면 모든 관련 리소스를 안전하게 제거할 수 있다.
# StatefulSet 삭제
kubectl delete -f statefulset.yaml
# Headless Service 삭제
kubectl delete -f statefulset-svc.yaml
# PVC(파드별 스토리지 요청) 삭제
kubectl delete pvc --all
# PV(실제 물리 볼륨) 삭제
kubectl delete pv --all
저작권 문제를 방지하기 위해 공식 문서 내용을 참고하였으며, 일부 설명은 ChatGPT를 활용해 재구성하였습니다.
본 포스트는 학습용 예시로 작성되었습니다.