[Kubernetes] 13. 워크로드 (6편) - StatefulSet

JIWON·2025년 7월 3일

Kubernetes

목록 보기
13/32
post-thumbnail

1. StatefulSet 개요

StatefulSet(스테이트풀셋)은 데이터베이스처럼 안정적인 네트워크 식별자와 영구적인 스토리지가 필요한 상태 저장 애플리케이션을 관리하기 위한 워크로드 리소스이다.

Deployment / ReplicaSet 과의 가장 큰 차이점

  • 고유하고 안정적인 네트워크 식별자: StatefulSet이 생성하는 파드는 [스테이트풀셋 이름]-[숫자 인덱스] (예: web-0 , web-1) 형태의 예측 가능한 고유한 이름을 가진다. 이 이름은 파드가 재시작되거나 다른 노드로 이동해도 절대 변경되지 않아, 다른 파드들이 특정 파드를 항상 동일한 이름으로 찾을 수 있게 해준다.
  • 안정적인 영구 스토리지: 각 파드는 자신만의 고유한 영구 볼륨(Persistent Volume)을 할당받는다. 파드가 재시작되어도 항상 동일한 볼륨에 다시 연결되므로 데이터가 그대로 보존된다.

2. StatefulSet 생성

StatefulSet을 생성할 때는 각 파드에 고유한 스토리지를 할당해주기 위한 volumeClaimTemplates 와 고유한 네트워크 주소를 부여하기 위한 serviceName 이 핵심적인 역할을 한다.

sample-statefulset.yaml 파일 작성:

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와 연결된다.


3. StatefulSet 스케일링

StatefulSet의 가장 독특한 특징 중 하나는 순서가 보장되는 스케일링(Ordered Scaling)이다.

# 스케일링 수행
kubectl scale statefulset sample-statefulset --replicas=5
  • 스케일 아웃 (Scale-Out): 파드의 수를 늘리면, 인덱스가 낮은 순서부터 하나씩 순차적으로 생성된다.
    예를 들어 3개에서 5개로 늘리면, sample-statefulset-3 이 생성되고 Running 상태가 된 이후에야 sample-statefulset-4 가 생성되기 시작한다.
  • 스케일 인 (Scale-In): 파드의 수를 줄이면, 인덱스가 높은 순서부터 하나씩 순차적으로 삭제된다.
    예를 들어 5개에서 3개로 줄이면, sample-statefulset-4 가 먼저 삭제되고, 그 다음 sample-statefulset-3 이 삭제된다.

이러한 순차적 동작은 데이터베이스 클러스터의 멤버를 추가하거나 제거할 때 데이터 정합성을 유지하는 데 매우 중요하다.

1) Pod 관리 정책 (Pod Management Policy)

StatefulSet의 순차적인 동작은 spec.podManagementPolicy 필드를 통해 제어할 수 있다.

  • OrderedReady (기본값): 위에서 설명한 것처럼 파드를 순서대로 생성하고 삭제한다.

  • Parallel : ReplicaSet이나 Deployment처럼 모든 파드를 병렬로 동시에 기동시킨다. 파드 간의 기동 순서가 중요하지 않은 일부 상태 저장 워크로드에서 사용할 수 있다.

spec:
  podManagementPolicy: Parallel
  # ...

4. StatefulSet 업데이트 전략

StatefulSet의 업데이트 전략은 spec.updateStrategy.type 필드를 통해 지정하며, 데이터의 안정성을 최우선으로 고려하여 설계되었다.

1) OnDelete 전략

  • OnDelete 전략에서는 데몬셋의 매니페스트 파일(예: 컨테이너 이미지 버전)을 변경하여 적용해도, 실행 중인 기존 파드들은 자동으로 업데이트되지 않는다.

  • 업데이트는 사용자가 직접 파드를 삭제(kubectl delete pod ...)했을 때만 이루어진다. 파드가 삭제되면 StatefulSet 컨트롤러가 새로운 버전의 파드를 해당 노드에 다시 생성한다.

  • 데이터베이스나 클러스터형 시스템처럼 운영자가 직접 제어하며 신중하게 업데이트를 진행하고 싶을 때 사용한다.

YAML 설정:

spec:
  updateStrategy:
    type: OnDelete

2) RollingUpdate 전략 (기본값)

  • RollingUpdate 전략은 파드를 순차적으로 업데이트하는 방식이지만, 스케일 인(Scale-In)과 마찬가지로 인덱스가 높은 순서부터 역순으로 진행된다.

  • 이 전략의 핵심은 partition 필드이다.

    • partition은 업데이트를 적용할 파드와 적용하지 않을 파드를 나누는 경계선 역할을 한다.

    • 인덱스가 partition 값보다 크거나 같은 파드만 새로운 버전으로 업데이트되고, partition 값보다 작은 인덱스를 가진 파드는 이전 버전을 그대로 유지한다.

    • 예를 들어 replicas: 5, partition: 3일 때, sample-sts-4sample-sts-3 파드만 업데이트되고, sample-sts-2, sample-sts-1, sample-sts-0은 업데이트되지 않는다.

    • 이를 통해 일부 파드만 새 버전으로 배포하여 안정성을 테스트하는 카나리(Canary) 배포단계적 배포가 가능하다.

YAML 설정:

spec:
  replicas: 5
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 3 # 인덱스 3 이상인 파드만 업데이트

5. 영구 볼륨 데이터 저장 확인

StatefulSet의 가장 중요한 특징은 파드가 사라져도 데이터는 보존된다는 점이다. 이는 각 파드가 고유한 PVC(PersistentVolumeClaim)를 통해 자신만의 PV(PersistentVolume)에 연결되어 있기 때문이다.

다음 과정을 통해 데이터 영속성을 직접 확인할 수 있다.

1) 파드 내부에 파일 생성

# 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/

2) 파드 강제 삭제

파드에 장애가 발생했거나, 사용자가 직접 파드를 삭제하는 상황을 시뮬레이션한다.

kubectl delete pod sample-statefulset-0

3) 파드 자동 복구 및 파일 확인

StatefulSet은 즉시 sample-statefulset-0 파드를 다시 생성한다. 새로 생성된 파드는 이전 파드와 이름은 같지만 IP는 다를 수 있다. 이 파드에 다시 접속하여 파일 존재 여부를 확인한다.

# 파드가 Running 상태가 된 후, 파일 확인
kubectl exec -it sample-statefulset-0 -- ls /usr/share/nginx/html/sample.html

결과적으로, 이전에 생성했던 sample.html 파일이 그대로 존재하는 것을 확인할 수 있다. 이는 파드가 자신의 고유한 PVC에 다시 연결되었기 때문이다.


6. StatefulSet 삭제와 데이터 보존

StatefulSet을 삭제할 때 데이터의 유실을 막기 위한 안전장치가 마련되어 있다.

  • kubectl delete statefulset [이름] 명령어로 StatefulSet 리소스를 삭제해도, 이와 연결된 PVC(와 PV)는 자동으로 삭제되지 않고 그대로 남아있다.

  • 이는 운영자의 실수로 StatefulSet을 삭제하더라도 중요한 데이터가 유실되는 것을 방지하기 위한 매우 중요한 정책이다.

  • 만약 PVC가 남아있는 상태에서 동일한 이름의 StatefulSet을 다시 생성하면, 새로 생성된 파드들은 기존에 남아있던 PVC에 그대로 연결되어 데이터를 이어서 사용할 수 있다.

1) 완전한 리소스 정리

StatefulSet과 관련된 모든 리소스를 완전히 삭제하고 싶다면, 반드시 다음 순서로 진행해야 한다.

  1. StatefulSet 리소스 삭제

  2. StatefulSet이 사용하던 PVC 수동 삭제

# StatefulSet이 확보했던 PVC를 명시적으로 삭제
kubectl delete persistentvolumeclaims www-sample-statefulset-0 www-sample-statefulset-1

⚠️ 주의 : PVC를 삭제하면 연결된 PV의 Reclaim Policy에 따라 실제 스토리지의 데이터가 삭제될 수 있으며, 복구가 불가능하므로 신중해야 한다. 또한, 삭제하지 않은 PVC는 계속해서 스토리지 비용을 발생시킬 수 있다.

0개의 댓글