[Kubernetes] StatefulSet + Headless Service

배창민·2025년 12월 4일
post-thumbnail

StatefulSet + Headless Service 정리

1. StatefulSet이 뭐하는 건지부터

StatefulSet은 상태를 가진 애플리케이션을 위한 Pod 운영 방식이다.
특징은 크게 네 가지로 정리할 수 있다.

  • Pod 이름이 고정된다
  • Pod마다 자기만의 PVC(영구 스토리지)를 가진다
  • 생성·삭제 순서가 보장된다 (0번부터 차례대로)
  • 각 Pod에 변하지 않는 DNS 이름이 붙는다

이게 필요한 이유는 이런 시스템들 때문이다.

  • MySQL / PostgreSQL: primary / replica 역할이 고정돼야 함
  • Kafka: broker-0, broker-1 같이 브로커 ID가 고정돼야 함
  • Redis Cluster: 노드마다 맡은 hash slot이 다름
  • MongoDB: 샤딩, 복제 구조가 노드 ID에 묶여 있음

이런 애들은 사실상

노드 ID = 데이터 영역

이 1:1로 묶여 있어야 정상 동작한다.
그래서 Pod 이름이 매번 바뀌는 Deployment로는 제대로 운영할 수 없고,
정체성이 보장되는 StatefulSet이 필요하다.


2. Deployment vs StatefulSet 비교

항목DeploymentStatefulSet
Pod 이름랜덤 suffix고정 (이름-0, 이름-1, …)
스토리지공유 또는 옵션Pod별 고유 PVC
스케일 순서신경 안 씀순서대로 생성/삭제
네트워크 ID변경될 수 있음각 Pod에 고정 DNS 부여

StatefulSet은 그냥 “데이터를 안 날리는 Pod” 수준이 아니라

  • ID 기반 클러스터 (Kafka, Redis Cluster, DB ReplicaSet 등)
  • 각 노드 역할이 정해져 있는 시스템

을 위한 구조라고 보는 게 더 정확하다.


3. StatefulSet 예제 구조 이해하기

3-1. StatefulSet 매니페스트 핵심

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: stateful-demo
spec:
  serviceName: "stateful-demo"   # Headless Service 이름
  replicas: 2
  selector:
    matchLabels:
      app: stateful-demo
  template:
    metadata:
      labels:
        app: stateful-demo
    spec:
      containers:
        - name: web
          image: nginx
          volumeMounts:
            - name: data
              mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 1Gi

여기서 중요한 포인트만 뽑으면

  • replicas: 2
    stateful-demo-0, stateful-demo-1 두 개의 Pod 생성

  • serviceName: "stateful-demo"
    → 이 이름을 가진 Headless Service를 기준으로 고정 DNS 부여

  • volumeClaimTemplates
    → Pod 수만큼 PVC를 자동 생성
    data-stateful-demo-0, data-stateful-demo-1 같은 이름으로 생김

각 Pod는 자기 전용 디스크를 가진다.


4. Headless Service 역할

StatefulSet에서 가장 중요한 친구가 Headless Service다.

apiVersion: v1
kind: Service
metadata:
  name: stateful-demo
spec:
  clusterIP: None      # 이게 Headless Service의 핵심
  selector:
    app: stateful-demo
  ports:
    - port: 80

clusterIP: None을 주면 하나의 VIP(가상 IP) 대신
각 Pod에 대해 개별 DNS 레코드가 생성된다.

예를 들면:

stateful-demo-0.stateful-demo.default.svc.cluster.local
stateful-demo-1.stateful-demo.default.svc.cluster.local

특징:

  • Pod가 재시작돼도 이 DNS는 그대로 유지된다
  • 분산 시스템이 “broker-0에 접속”, “node-1에 repl 연결” 같은 식으로
    노드 ID를 기준으로 서로 붙을 수 있게 해준다

그래서 StatefulSet 쓸 때는 거의 무조건 Headless Service와 세트라고 보면 된다.


5. 실습할 때 체크 포인트

5-1. 생성

kubectl apply -f statefulset-headless.yml
kubectl apply -f statefulset-demo.yml

확인:

kubectl get pods
kubectl get pvc

확인해야 할 것:

  1. Pod 이름이 정확히 stateful-demo-0, stateful-demo-1 형태로 뜨는지

  2. PVC가 Pod 수만큼 자동 생성되는지

    • data-stateful-demo-0
    • data-stateful-demo-1
  3. PVC는 그대로 두고 Pod만 다시 떠도, 같은 PVC를 계속 쓰는지

5-2. Pod 삭제 후 동작

kubectl delete pod stateful-demo-0
kubectl get pods -w

기대 동작:

  • stateful-demo-0가 다시 생성된다 (이름이 절대 바뀌지 않음)
  • 기존 PVC data-stateful-demo-0가 유지된 상태로 재사용된다

Deployment였다면 stateful-demo-xxx-abcde 이런 식으로 suffix가 매번 바뀌겠지만,
StatefulSet은 0번은 영원히 0번이다.


6. 정리

한 줄씩 정리하면:

  • StatefulSet

    • 상태ful 서비스, ID 기반 노드 구조를 위한 Pod 관리 방식
    • 고정 Pod 이름, Pod별 고유 PVC, 순서 기반 생성/삭제 지원
  • Headless Service

    • clusterIP: None
    • 각 Pod에 대해 고정 DNS를 발급
    • pod-name.service-name.namespace.svc.cluster.local 형태
  • 언제 쓰는지

    • MySQL / PostgreSQL ReplicaSet
    • Kafka, Redis Cluster, MongoDB 같은 분산 스토리지/메시징 시스템
    • “노드 ID = 역할 = 데이터”가 강하게 묶인 구조

결론적으로, StatefulSet + Headless Service 조합은
쿠버네티스에서 상태ful 분산 시스템을 돌리기 위한 사실상 표준 패턴이다.
단순 웹 서버, API 서버처럼 “어디에 붙어도 상관 없는” 서비스는 Deployment로,
노드 하나하나 정체성이 중요한 서비스는 StatefulSet으로 가져가는 게 기본 설계 방향이다.

profile
개발자 희망자

0개의 댓글