Kubernetes

[k8s] StatefulSet ㅡ 이해하기

최선을 다하자! 2026. 6. 9. 17:28

StatefulSet


왜 StatefulSet이 필요한가

Deployment는 Pod를 재생성할 때마다 이름이 바뀐다.

# Deployment로 만든 Pod — 이름에 랜덤 해시가 붙음
nginx-b8b844b6c-5kb69   (삭제)
nginx-b8b844b6c-x9kqw   (재생성 — 이름 바뀜)

nginx 같은 웹 서버는 이름이 바뀌어도 상관없다. 어느 Pod든 똑같은 역할을 하기 때문이다.

하지만 MySQL 같은 DB는 다르다. DB 복제(replication)를 구성하면 "0번이 마스터, 1번이 슬레이브"처럼 역할이 고정되어야 한다. Pod 이름이 바뀌면 이 설정이 깨진다.

StatefulSet은 이 문제를 해결한다. Pod에 순서 번호를 부여하고, 재생성해도 이름을 유지한다.

# StatefulSet으로 만든 Pod — 순서 번호 고정
mysql-0   (삭제)
mysql-0   (재생성 — 이름 그대로)

Deployment vs StatefulSet 전체 비교

  Deployment StatefulSet
Pod 이름 랜덤 해시 (매번 바뀜) 순서 번호 고정 (mysql-0, mysql-1)
재생성 후 이름 바뀜 그대로 유지
배포 순서 동시에 (순서 없음) 0번부터 순서대로
삭제 순서 동시에 (순서 없음) 큰 번호부터 역순으로
스토리지 Pod끼리 PVC 공유 가능 Pod마다 전용 PVC 자동 생성
네트워크 Service로 임의 Pod에 연결 Headless Service로 Pod 직접 지정 가능
주요 용도 nginx, API 서버 등 무상태 서비스 MySQL, Redis, Kafka 등 상태 있는 서비스
yaml 차이 kind: Deployment kind: StatefulSet + serviceName 필수

StatefulSet yaml 작성

Deployment와 구조는 거의 동일하다. 두 가지만 다르다.

1. kind: StatefulSet

2. serviceName 항목 추가 (필수 — Headless Service 이름을 지정)

apiVersion: apps/v1
kind: StatefulSet         # Deployment → StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql      # 필수 항목 (Deployment에는 없음)
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:8.0
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD   # mysql은 root 비밀번호 필수
          value: "1234"
        resources: {}
kubectl apply -f mysql-statefulset.yaml
kubectl get pods | grep mysql

 


Pod 삭제 후 이름 유지 확인

# Pod 삭제
kubectl delete pod mysql-0

# 재생성 확인
kubectl get pods | grep mysql

삭제 후 재생성되어도 이름이 mysql-0으로 유지된다. Deployment였다면 mysql-랜덤해시로 새 이름이 생성됐을 것이다.

 

 

15:19:33 [root@k8s-worker-jwc:/k8s]$ kubectl delete pod mysql-0
pod "mysql-0" deleted

17:30:12 [root@k8s-worker-jwc:/k8s]$ kubectl get pods | grep mysql
mysql-0                            1/1     Running   0             4s

언제 Deployment를, 언제 StatefulSet을 쓰는가

간단한 판단 기준은 이것이다.

질문 Yes → StatefulSet No → Deployment
Pod 이름이 고정되어야 하는가? DB 마스터/슬레이브 구분 nginx, API 서버
Pod마다 독립적인 스토리지가 필요한가? 각 DB 노드가 자기 데이터 보유 공유 스토리지면 충분
배포/삭제 순서가 중요한가? 마스터 먼저 기동 후 슬레이브 순서 무관