dh_0e

[Cloud] StatefulSet 본문

Cloud/Kubernetes

[Cloud] StatefulSet

dh_0e 2026. 6. 3. 14:26

StatefulSet

  • 정의: "상태가 있는(Stateful) 애플리케이션"을 관리하기 위해  Pod의 순서와 고유성을 보장하며 배포하는 컨트롤러
  • Pod들은 동일한 컨테이너 스펙으로 생성되지만, 서로 교체할 수 없는 고유한 식별자상태를 가짐
    • 재스케줄링(Pod 재생성) 시에도 Pod의 이름과 네트워크 식별자, 스토리지 볼륨이 그대로 유지
  • 주요 사용처(Use Cases)
    • 데이터베이스 및 클러스터링 시스템: MySQL, MongoDB, Redis, Kafka 등 상태와 데이터 유지가 필수적인 워크로드의 90% 이상에 사용
      • 워크로드: 컴퓨팅 리소스가 작업 완료 또는 결과 도출을 위해 수행하는 처리 작업의 유형과 양
    • 안정적이고 고유한 네트워크 식별자가 필요한 경우
    • 안정적인 영구 스토리지(PV)가 필요한 경우
    • 순차적인 Pod의 배포, 스케일링, 삭제가 필요한 경우
    • PV와 궁합이 잘 맞음
  • 스토리지(Volume) 및 스케일링 특징
    • volumeClaimTemplates 사용: 각 Pod가 생성될 때 고유한 PVC를 자동으로 생성해 개별 PV와 1:1로 매핑함
    • Deployment는 하나의 PVC를 여러 Pod가 공유하는 방식이 흔하지만, StatefulSet은 이 템플릿을 통해 생성되는 각 Pod마다 자신만의 독립적인 PVC를 자동으로 생성하여 연결
  • 네트워크 (Headless Service)
    • StatefulSet은 로드밸런싱 목적인 일반 Service(ClusterIP) 대신 Headless Service(ClusterIP: None)와 짝을 이루어 사용함
    • 각 Pod는 <Pod이름>.<Service이름>.<Namespace>.svc.cluster.local 형태의 고정된 내부 DNS 주소를 가지게 되어, 특정 Pod(예: DB Master 노드)를 정확히 지정해 통신할 수 있음

Scale Up/Down of StatefulSet

  • Scale Down을 해도 PVC가 없어지지 않고 유지됨
  • Scale Up을 했을 때 기존 PVC로 쉽게 PV와 연결할 수 있음

 

Deployment vs StatefulSet 차이

  • Deployment로 만든 여러 개의 Pod들은 고유 ID나 Pod간의 순서가 없으며, 임의의 이름을 할당 받음
    • 모든 Pod들은 공유 볼륨을 사용할 수 있음
  • StatefulSet으로 만든 여러 개의 Pod들은 고유 ID를 가지며, 순차적으로 생성 및 종료
    • 각 Pod에 개별적인 PV가 필요

Using PV in Deployment
Using PV in StatefulSet

 

Deployment 여러 개로 StatefulSet 기능 구현

Stateful Application(Pod) without using StatefulSet

  • 각 Replica(Pod)들은 고유의 Service와 Deployment를 가짐
    • Service들은 각 Pod들에게 안정된 주소를 분리시켜 제공함 (Service x 3)
    • Deployment들은 각 Pod들에게 모두 다른 PVC를 제공함 (Deployment x 3)
    • 공유 주소로 모든 Pod를 함께 노출하고 싶을 경우, 또 다른 서비스(사진의 quiz Service)가 필요함 (+ 1 Service)
  • 만약 사진처럼 3개의 Pod에 각각 고유한 주소와 스토리지를 쥐어주려면, 사진에 나온 것처럼 3개의 Deployment, 3개의 개별 Service, 1개의 공통 Service 등 엄청나게 많은 리소스(YAML 파일)를 직접 관리해야 하는 복잡성이 있음
    • StatefulSet을 활용하면 이를 단 2개의 리소스로 압축해 줌
      1. StatefulSet: 사진 속의 파란색(Deployment)초록색(PVC) 상자들의 역할
      2. Headless Service: 사진 속의 노란색(개별 Service) 상자들 역할

 

Headless Service

Headless Service for StatefulSet

  • 일반적인 Service에서는 자신만의 고유한 IP(Cluster IP)를 가짐
    • 로드밸런싱: 외부에서 이 IP로 요청을 보내면 Service가 알아서 뒤에 있는 여러 Pod 중 무작위로 트래픽을 넘겨줌
  • StatefulSet은 Pod들이 각각 고유 번호가 있기 때문에 Cluster IP를 주지 않는 Headless Service를 사용
    • Service 자체의 대표 ClusetrIP(Head)를 없애버린 것
    • 대표 IP가 없는 대신, 쿠버네티스 내부의 DNS 서버(주황색 원통)에 각 Pod들의 고유한 이름과 실제 IP 주소를 매핑하여 저장
    • 이 덕분에 랜덤한 Pod가 아니라, 내가 원하는 정확한 Pod를 콕 집어서 찾아갈 수 있게 됨
"StatefulSet의 Pod들은 각각 자기만의 고유한 역할과 데이터가 있기 때문에 아무 데나 랜덤하게 접속하면 안 된다. 그래서 대표 IP를 지워버린 Headless Service를 사용해, DNS를 통해 각 Pod의 고유한 도메인 주소(FQDN)로 직접 찾아가게 만든다."

 

StatefulSet YAML

Headless Service yaml, StatefulSet yaml

Headless Service (왼쪽 코드)

  • kind: Service
  • metadata.name: nginx
  • clusterIP: None (핵심)
    • 일반 Service를 Headless Service로 바꿔주는 옵션
    • 자신만의 대표 IP(머리)를 가지지 않고, 뒤에 연결될 Pod들의 IP를 DNS에 묶어주는 역할만 수행하겠다고 선언하는 것

StatefulSet (중간/오른쪽 코드)

  • kind: StatefulSet
  • serviceName: "nginx" (연결 고리)
    • 앞서 만든 Headless Service와 StatefulSet을 짝지어주는 역할
    • 내가 만드는 Pod(web-0, web-1, web-2)들의 고유 도메인 주소를 nginx라는 이름의 Headless Service DNS에 등록해 주라는 의미
  • replicas: 3
    • web-0, web-1, web-2 3개의 Pod를 순차적으로 찍어냄
  • volumeClaimTemplates (스토리지 자동화)
    • 이전에 봤던 "각 Pod마다 따로 PVC를 만들어주는 번거로운 작업"을 해결해 주는 템플릿
    • storage: 1Gi
      • Pod를 3개 만들면서, 이 템플릿을 바탕으로 3개의 독립적인 1Gi PVC를 알아서 생성하고 각각의 Pod에 1:1로 마운트 해줌 (mountPath: /usr/share/nginx/html)

 

한계점

  1. 스토리지(PV) 사전 준비 필수 (인프라 구성 난이도 상승)
    • 주어진 Pod의 스토리지는 요청된 스토리지 클래스를 기반으로 PV Provisioner(StorageClass)에 의해 제공되거나, 인프라 관리자에 의해 사전 제공되어야 함
  2. 자동 삭제되지 않는 볼륨 (데이터 유지됨)
    • StatefulSet을 삭제하거나 Scale-down(축소)해도 StatefulSet과 관련된 볼륨은 삭제되지 않음
    • 테스트가 끝난 후 리소스를 완전히 정리할 때 관리자가 수동으로 PVC를 지워주지 않으면 클라우드 환경에서 계속 스토리지 과금이 발생할 수 있음
  3. 현재 포드의 네트워크 동일성을 책임지기 위해 Headless Service가 항상 필요함
  4. StatefulSet이 삭제될 때 Pod의 종료에 대한 보장을 제공하지 않음
    • StatefulSet을 "kubectl delete"로 한 번에 날려버리면, Pod들이 순서를 지키지 않고 동시다발적으로 강제 종료될 위험이 있음
    • 분산 서버나 데이터베이스라면, 디스크에 안전하게 저장(Flush)할 시간이 필요하므로, 반드시 "replicas: 0"으로 먼저 Scale-down을 지시하여 제일 마지막 번호의 Pod부터 0번까지 차례대로(역순으로) 안전하게 마무리 작업을 하고 꺼지도록 유도해야 함