쿠버네티스 용어 사전
워크로드헤드리스 서비스 · volumeClaimTemplates

StatefulSet

안정된 이름·순서·전용 볼륨을 준다. 지워도 PVC는 남는다.

상태 있는 애플리케이션을 위한 워크로드.

  • 이름 — web-0 · web-1 · web-2 — 순서가 있고 재생성돼도 같은 이름
  • 순서 — 0 → 1 → 2 순으로 만들고, 역순으로 지운다
  • 볼륨 — volumeClaimTemplates 로 파드마다 전용 PVC 를 만든다
    • 파드가 재생성돼도 같은 볼륨에 다시 붙는다
  • 네트워크 — 헤드리스 서비스와 함께 쓰면 web-0.svc 로 개별 접근이 가능하다

Deployment 와 무엇이 다른가

  • Deployment — 파드가 서로 '대체 가능' 하다는 전제

    • 이름이 무작위고 순서가 없다
    • 모두 같은 PVC 를 쓰거나 볼륨이 없다
  • StatefulSet — 파드가 '개체' 다

    • 클러스터 멤버가 서로를 이름으로 식별해야 하는 것들에 쓴다
    • DB 복제 세트 · Kafka · ZooKeeper · Elasticsearch

헤드리스 서비스가 짝이다

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  clusterIP: None        # 헤드리스
  selector: { app: web }
  ports: [{ port: 80 }]

보통 서비스는 파드 여러 개를 묶어 대표 주소 하나를 주고, 요청이 오면 그중 아무거나 골라 보낸다. 그런데 DB 복제 세트 같은 것은 "아무나" 가 아니라 "0번한테" 보내야 한다. 리더가 0번이면 쓰기는 0번으로 가야 하기 때문이다.

clusterIP: None(헤드리스)으로 두면 대표 주소를 만들지 않고, DNS 가 파드 주소를 그대로 알려 준다. 그래서 파드마다 고유한 이름이 생긴다.

web-0.web.default.svc.cluster.local
│     │   │
│     │   └ 네임스페이스
│     └ 헤드리스 서비스 이름
└ 파드 이름 — 이 주소로 부르면 '그 파드' 에만 간다

이 덕분에 클러스터 멤버가 서로를 이름으로 지목해 부를 수 있다. 카프카 브로커가 다른 브로커를 찾거나 복제본이 리더에게 붙는 일이 전부 이 주소로 이뤄진다.

마지막으로 배선이 하나 필요하다. StatefulSet 의 serviceName 필드에 이 헤드리스 서비스 이름을 적어야 위 DNS 이름들이 실제로 만들어진다. 빠뜨리면 파드는 뜨는데 서로를 못 찾는다.

PVC 가 남는다

StatefulSet 을 지워도 PVC 는 남는다 (의도된 동작이다)

  • 데이터를 지키기 위해서다
  • 다시 만들면 같은 볼륨에 붙는다
  • 정리를 잊으면 볼륨이 계속 쌓인다

replicas 를 줄여도 그 파드의 PVC 는 남는다

  • 다시 늘리면 옛 데이터가 그대로 붙는다 (대개 원하는 동작이다)

운영에서 주의할 것

  • 순차 생성이라 파드 하나가 Ready 가 안 되면 다음이 안 뜬다
    • 기동이 느린 애플리케이션은 전체 배포가 매우 길어진다
    • podManagementPolicy: Parallel 로 동시 생성할 수도 있다
  • 롤링 업데이트도 역순으로 하나씩 (N-1 → 0)
    • partition 을 두면 일부만 먼저 올릴 수 있다 (카나리)
  • force delete 를 쓰면 같은 이름의 파드가 두 개 도는 상태가 생길 수 있다
    • 볼륨 손상으로 이어진다. 마지막 수단으로만

정말 StatefulSet 이 필요한가

  • 필요하다 — 멤버가 서로를 이름으로 식별해야 한다 (DB 복제 · Kafka)

    • 파드마다 다른 데이터를 가져야 한다
    • 시작·종료 순서가 의미를 갖는다
  • 필요 없다 — 데이터를 외부 스토리지(RDS · S3)에 둔다

    • Deployment 로 충분하다
    • 세션을 Redis 에 둔다 → 상태가 파드에 없다

가능하면 상태를 클러스터 밖으로 빼는 편이 운영이 훨씬 쉽다 쿠버네티스에서 DB 를 직접 돌리는 것은 그럴 이유가 분명할 때만

업데이트 전략

updateStrategy:
  type: RollingUpdate
  rollingUpdate:
    partition: 2      # 인덱스 2 이상만 업데이트

partition 을 두면 일부만 먼저 올릴 수 있다 (카나리)

  • replicas 5, partition 4 → web-4 만 새 버전
  • 확인 후 partition 을 낮춰 가며 전체로 확대

역순(N-1 → 0)으로 진행되므로 partition 이 '이상' 을 뜻한다

면접 함정

  • "상태가 있으면 무조건 StatefulSet" → 외부 스토리지를 쓰면 Deployment로도 된다.
  • "StatefulSet을 지우면 데이터도 지워진다" → PVC는 남는다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 워크로드 — 파드부터 Deployment까지