Kubernetes의 상태 저장 애플리케이션 배포: StatefulSet


1. StatefulSet이란?

Kubernetes에서 애플리케이션을 배포할 때, 대부분의 경우 Stateless(무상태) 애플리케이션을 다룬다. 하지만 데이터베이스, 분산 저장소, 캐시 시스템처럼 상태를 유지해야 하는(Stateful) 애플리케이션은 특별한 배포 방식이 필요하다. 이를 위해 Kubernetes에서는 StatefulSet을 제공한다.

StatefulSet은 Pod의 네트워크 ID와 볼륨을 유지하면서 순차적으로 생성 및 삭제하는 기능을 제공하여 상태 저장 애플리케이션의 안정적인 배포와 확장을 지원한다.


2. StatefulSet vs Deployment

특징StatefulSetDeployment
Pod 이름고유한 정해진 이름 부여 (<StatefulSet 이름>-<순번>)랜덤한 Pod 이름 부여
Pod 순서 보장생성, 업데이트, 삭제 시 순서 보장순서 보장 없음
네트워크 ID각 Pod에 고유한 호스트네임 유지Pod가 재시작될 때 네트워크 ID 변경 가능
볼륨 유지Pod가 재시작되거나 이동해도 동일한 볼륨 사용새로 생성된 Pod는 기존 볼륨과 연결되지 않음
주로 사용하는 애플리케이션데이터베이스(MySQL, PostgreSQL, MongoDB), 분산 시스템(ZooKeeper, Kafka)웹 서버, API 서버, 마이크로서비스

StatefulSet은 네트워크 ID와 볼륨이 중요한 워크로드에서 사용된다.


3. StatefulSet의 주요 기능

1) Pod 이름과 네트워크 ID 유지

StatefulSet은 각 Pod에 **고정된 네트워크 ID(도메인 이름)**를 부여한다.

  • statefulset-name-0, statefulset-name-1, statefulset-name-2 형태로 Pod가 생성됨
  • 도메인 이름이 유지되므로, 다른 Pod 또는 애플리케이션이 특정 Pod에 항상 접근 가능

💡 예제:

spec:
serviceName: "my-stateful-service"

이 설정을 하면 각 Pod는 my-stateful-service-0, my-stateful-service-1 같은 호스트네임을 갖는다.


2) Pod의 순차적 배포 및 종료

  • Pod 생성 시: 0 → 1 → 2 순서로 하나씩 생성됨
  • Pod 업데이트 시: 0 → 1 → 2 순서로 업데이트됨
  • Pod 삭제 시: 2 → 1 → 0 순서로 하나씩 삭제됨
  • 스케일링 시: 숫자를 늘리면 새로운 Pod가 마지막 숫자부터 추가됨

💡 예제:

replicas: 3

위 설정에서는 my-stateful-app-0, my-stateful-app-1, my-stateful-app-2 순으로 생성됨.


3) 안정적인 볼륨 유지

  • StatefulSet은 각 Pod에 독립적인 볼륨을 할당하고, Pod가 재시작되더라도 동일한 볼륨을 유지한다.
  • 볼륨을 유지하는 방식:
    • **PersistentVolumeClaim(PVC)**을 각 Pod에 개별적으로 바인딩
    • PVC가 생성될 때 **각 Pod에 연결된 Persistent Volume(PV)**이 유지됨

💡 예제:

volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi

이 설정을 하면 각 Pod마다 data라는 볼륨이 개별적으로 생성됨.


4. StatefulSet 예제

StatefulSet 및 Headless Service 예제

아래는 3개의 상태 저장 애플리케이션을 관리하는 StatefulSet 설정 예제이다.

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-stateful-app
spec:
serviceName: "my-stateful-service"
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-stateful-app-image
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi

📌 설명:

  1. replicas: 3 → 3개의 Pod가 생성됨 (my-stateful-app-0, my-stateful-app-1, my-stateful-app-2)
  2. serviceName: "my-stateful-service" → 각 Pod는 my-stateful-service-0, my-stateful-service-1 같은 DNS 이름 사용
  3. volumeClaimTemplates → 각 Pod에 개별적인 5Gi 볼륨을 생성

5. StatefulSet 사용 시 고려해야 할 점

삭제 시 자동으로 볼륨 제거되지 않음

  • StatefulSet을 삭제해도 **Persistent Volume(PV)**는 남아있음
  • 불필요한 스토리지가 남을 수 있으므로 수동 정리 필요
  • 삭제 시 데이터를 유지하려면 PersistentVolumeReclaimPolicyRetain으로 설정

빠른 확장이 어려움

  • Pod가 순차적으로 생성되고 준비될 때까지 기다려야 하므로, Deployment보다 확장 속도가 느림

Pod 간의 데이터 공유 어려움

  • 각 Pod는 개별적인 볼륨을 사용하기 때문에 데이터를 공유하려면 추가적인 설정 필요 (예: NFS, Ceph, GlusterFS 등)

6. StatefulSet을 사용해야 하는 경우

필수적으로 StatefulSet을 사용해야 하는 경우:

  • 데이터베이스(MySQL, PostgreSQL, MongoDB)
  • 메시지 브로커(Kafka, RabbitMQ, ActiveMQ)
  • 분산 저장소(Ceph, HDFS, MinIO)
  • 데이터 분석 및 캐싱 시스템(Elasticsearch, Redis, Memcached)

StatefulSet이 필요하지 않은 경우:

  • 단순한 웹 애플리케이션
  • Stateless API 서버
  • 일회성 작업 (Batch Processing, CI/CD)

7. 결론

StatefulSet은 Kubernetes에서 상태를 유지해야 하는 애플리케이션을 관리하는 중요한 리소스다.
특히, 데이터베이스, 메시지 브로커, 분산 시스템과 같이 특정한 네트워크 ID와 볼륨을 필요로 하는 애플리케이션에서 필수적으로 사용된다.

하지만 StatefulSet은 확장 속도가 느리고 볼륨이 자동으로 삭제되지 않는 등의 단점도 존재하므로, 필요에 따라 Deployment, DaemonSet과 비교하여 적절한 방식을 선택하는 것이 중요하다.

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다