
StatefulSet(스테이트풀셋)은 데이터베이스처럼 안정적인 네트워크 식별자와 영구적인 스토리지가 필요한 상태 저장 애플리케이션을 관리하기 위한 워크로드 리소스이다.
Deployment / ReplicaSet 과의 가장 큰 차이점
[스테이트풀셋 이름]-[숫자 인덱스] (예: web-0 , web-1) 형태의 예측 가능한 고유한 이름을 가진다. 이 이름은 파드가 재시작되거나 다른 노드로 이동해도 절대 변경되지 않아, 다른 파드들이 특정 파드를 항상 동일한 이름으로 찾을 수 있게 해준다. StatefulSet을 생성할 때는 각 파드에 고유한 스토리지를 할당해주기 위한 volumeClaimTemplates 와 고유한 네트워크 주소를 부여하기 위한 serviceName 이 핵심적인 역할을 한다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sample-statefulset
spec:
serviceName: "sample-statefulset" # 파드에 고유 DNS 주소를 부여할 Headless Service 이름
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: nginx-container
image: nginx
volumeMounts:
- name: www # 아래 volumeClaimTemplates의 이름과 일치해야 함
mountPath: /usr/share/nginx/html
volumeClaimTemplates: # 각 파드에 대한 PVC(영구 볼륨 요청)를 생성하기 위한 템플릿
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
StatefulSet을 배포하면, 정의된 내용에 따라 파드(Pod), 영구 볼륨 요청(PVC), 그리고 실제 저장 공간인 영구 볼륨(PV)이 순차적으로 생성된다.
# StatefulSet 생성
kubectl apply -f sample-statefulset.yaml
# 생성된 StatefulSet 확인
kubectl get statefulset
# 생성된 파드 확인 (이름이 -0, -1, -2 로 끝나는 것을 확인)
kubectl get pods -o wide
# 생성된 PVC(저장소) 확인 (파드별로 PVC가 생성된 것을 확인)
kubectl get persistentvolumeclaims
# 생성된 PV 확인 (PVC에 의해 PV가 동적으로 생성되고 Bound된 것을 확인)
kubectl get persistentvolumes
각 파드는 www-[파드이름] 형식의 고유한 PVC를 가지며, 이 PVC는 실제 스토리지인 PV와 연결된다.
StatefulSet의 가장 독특한 특징 중 하나는 순서가 보장되는 스케일링(Ordered Scaling)이다.
# 스케일링 수행
kubectl scale statefulset sample-statefulset --replicas=5
sample-statefulset-3 이 생성되고 Running 상태가 된 이후에야 sample-statefulset-4 가 생성되기 시작한다.
sample-statefulset-4 가 먼저 삭제되고, 그 다음 sample-statefulset-3 이 삭제된다.
이러한 순차적 동작은 데이터베이스 클러스터의 멤버를 추가하거나 제거할 때 데이터 정합성을 유지하는 데 매우 중요하다.
StatefulSet의 순차적인 동작은 spec.podManagementPolicy 필드를 통해 제어할 수 있다.
OrderedReady (기본값): 위에서 설명한 것처럼 파드를 순서대로 생성하고 삭제한다.
Parallel : ReplicaSet이나 Deployment처럼 모든 파드를 병렬로 동시에 기동시킨다. 파드 간의 기동 순서가 중요하지 않은 일부 상태 저장 워크로드에서 사용할 수 있다.
spec:
podManagementPolicy: Parallel
# ...
StatefulSet의 업데이트 전략은 spec.updateStrategy.type 필드를 통해 지정하며, 데이터의 안정성을 최우선으로 고려하여 설계되었다.
OnDelete 전략에서는 데몬셋의 매니페스트 파일(예: 컨테이너 이미지 버전)을 변경하여 적용해도, 실행 중인 기존 파드들은 자동으로 업데이트되지 않는다.
업데이트는 사용자가 직접 파드를 삭제(kubectl delete pod ...)했을 때만 이루어진다. 파드가 삭제되면 StatefulSet 컨트롤러가 새로운 버전의 파드를 해당 노드에 다시 생성한다.
데이터베이스나 클러스터형 시스템처럼 운영자가 직접 제어하며 신중하게 업데이트를 진행하고 싶을 때 사용한다.
spec:
updateStrategy:
type: OnDelete
RollingUpdate 전략은 파드를 순차적으로 업데이트하는 방식이지만, 스케일 인(Scale-In)과 마찬가지로 인덱스가 높은 순서부터 역순으로 진행된다.
이 전략의 핵심은 partition 필드이다.
partition은 업데이트를 적용할 파드와 적용하지 않을 파드를 나누는 경계선 역할을 한다.
인덱스가 partition 값보다 크거나 같은 파드만 새로운 버전으로 업데이트되고, partition 값보다 작은 인덱스를 가진 파드는 이전 버전을 그대로 유지한다.
예를 들어 replicas: 5, partition: 3일 때, sample-sts-4와 sample-sts-3 파드만 업데이트되고, sample-sts-2, sample-sts-1, sample-sts-0은 업데이트되지 않는다.
이를 통해 일부 파드만 새 버전으로 배포하여 안정성을 테스트하는 카나리(Canary) 배포나 단계적 배포가 가능하다.
spec:
replicas: 5
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 3 # 인덱스 3 이상인 파드만 업데이트
StatefulSet의 가장 중요한 특징은 파드가 사라져도 데이터는 보존된다는 점이다. 이는 각 파드가 고유한 PVC(PersistentVolumeClaim)를 통해 자신만의 PV(PersistentVolume)에 연결되어 있기 때문이다.
다음 과정을 통해 데이터 영속성을 직접 확인할 수 있다.
# sample-statefulset-0 파드의 마운트된 볼륨에 테스트 파일 생성
kubectl exec -it sample-statefulset-0 -- touch /usr/share/nginx/html/sample.html
kubectl exec -it sample-statefulset-0 -- ls /usr/share/nginx/html/
파드에 장애가 발생했거나, 사용자가 직접 파드를 삭제하는 상황을 시뮬레이션한다.
kubectl delete pod sample-statefulset-0
StatefulSet은 즉시 sample-statefulset-0 파드를 다시 생성한다. 새로 생성된 파드는 이전 파드와 이름은 같지만 IP는 다를 수 있다. 이 파드에 다시 접속하여 파일 존재 여부를 확인한다.
# 파드가 Running 상태가 된 후, 파일 확인
kubectl exec -it sample-statefulset-0 -- ls /usr/share/nginx/html/sample.html
결과적으로, 이전에 생성했던 sample.html 파일이 그대로 존재하는 것을 확인할 수 있다. 이는 파드가 자신의 고유한 PVC에 다시 연결되었기 때문이다.
StatefulSet을 삭제할 때 데이터의 유실을 막기 위한 안전장치가 마련되어 있다.
kubectl delete statefulset [이름] 명령어로 StatefulSet 리소스를 삭제해도, 이와 연결된 PVC(와 PV)는 자동으로 삭제되지 않고 그대로 남아있다.
이는 운영자의 실수로 StatefulSet을 삭제하더라도 중요한 데이터가 유실되는 것을 방지하기 위한 매우 중요한 정책이다.
만약 PVC가 남아있는 상태에서 동일한 이름의 StatefulSet을 다시 생성하면, 새로 생성된 파드들은 기존에 남아있던 PVC에 그대로 연결되어 데이터를 이어서 사용할 수 있다.
StatefulSet과 관련된 모든 리소스를 완전히 삭제하고 싶다면, 반드시 다음 순서로 진행해야 한다.
StatefulSet 리소스 삭제
StatefulSet이 사용하던 PVC 수동 삭제
# StatefulSet이 확보했던 PVC를 명시적으로 삭제
kubectl delete persistentvolumeclaims www-sample-statefulset-0 www-sample-statefulset-1
⚠️ 주의 : PVC를 삭제하면 연결된 PV의 Reclaim Policy에 따라 실제 스토리지의 데이터가 삭제될 수 있으며, 복구가 불가능하므로 신중해야 한다. 또한, 삭제하지 않은 PVC는 계속해서 스토리지 비용을 발생시킬 수 있다.