본문 바로가기
일반IT

Deployment vs. StatefulSet: 내 애플리케이션에 맞는 컨트롤러는?

by gasbugs 2025. 7. 31.

https://medium.com/@muppedaanvesh/a-hands-on-guide-to-kubernetes-deployments-statefulsets-and-daemonsets-%EF%B8%8F-20167634775d

 

쿠버네티스에서 애플리케이션을 배포할 때, 우리는 Deployment와 StatefulSet이라는 두 가지 강력한 컨트롤러를 주로 사용합니다. 둘 다 파드(Pod)의 실행을 관리하고 원하는 수의 복제본을 유지한다는 공통점이 있지만, 그 작동 방식과 목적은 근본적으로 다릅니다. 잘못된 컨트롤러를 선택하면 애플리케이션의 확장성과 안정성에 심각한 문제가 생길 수 있습니다.

이번 글에서는 Deployment와 StatefulSet의 핵심적인 차이점을 명확히 알아보고, 어떤 상황에서 무엇을 선택해야 하는지에 대한 명확한 기준을 제시하겠습니다.

핵심 질문은 이것입니다: "내 애플리케이션의 파드는 서로 완벽히 교체 가능하며 신원(Identity)이 중요하지 않은가, 아니면 각자 고유한 신원과 상태를 가져야 하는가?"


Deployment: 상태 없는(Stateless) 애플리케이션의 표준 🚀

Deployment는 쿠버네티스에서 가장 보편적으로 사용되는 컨트롤러입니다. 그 목적은 상태가 없는(Stateless) 애플리케이션을 관리하는 것입니다. 여기서 '상태가 없다'는 것은 각 파드가 독립적이고 서로 교체 가능하여, 어느 파드가 요청을 처리하든 상관없는 경우를 의미합니다. 마치 똑같은 일을 하는 수많은 일꾼과 같습니다. 한 명이 사라져도 다른 한 명이 즉시 그 자리를 대체할 수 있죠.

주요 특징

  • 임의의 파드 이름: Deployment가 생성하는 파드는 [Deployment 이름]-[임의의 해시] 와 같은 무작위 이름을 갖습니다. (예: my-nginx-66bcf7c4c9-x1234)
  • 교체 가능한 존재: 파드가 죽거나 업데이트되면, 완전히 새로운 이름과 IP를 가진 새 파드가 그 자리를 대체합니다. 기존 파드의 정체성은 전혀 유지되지 않습니다.
  • 단일 서비스 엔드포인트: 여러 개의 파드는 하나의 Service를 통해 외부 또는 내부에 노출됩니다. Service는 어떤 파드가 요청을 받을지 신경 쓰지 않고, 그저 살아있는 파드 중 하나에게 트래픽을 전달할 뿐입니다.
  • 빠르고 유연한 확장: replicas 수를 늘리거나 줄이면, 순서에 상관없이 파드가 생성되거나 삭제됩니다. 빠른 수평 확장이 가능합니다.

이럴 때 사용하세요!

Deployment는 파드 내부에 고유한 데이터를 저장하지 않는 거의 모든 종류의 애플리케이션에 적합합니다.

  • 웹 서버: Nginx, Apache
  • API 서버: Spring Boot, Node.js, Django/Flask 등 MSA 백엔드
  • 프론트엔드 애플리케이션: React, Vue, Angular
  • 그 외 상태를 외부 데이터베이스나 스토리지에 저장하는 모든 애플리케이션

StatefulSet: 안정적인 '이름'이 필요한 애플리케이션을 위해 🐾

StatefulSet은 이름에서 알 수 있듯이 상태가 있는(Stateful) 애플리케이션을 위해 설계되었습니다. 여기서 '상태가 있다'는 것은 각 파드가 고유한 신원(Identity)을 가지며, 이 신원이 파드의 재시작이나 업데이트에도 반드시 유지되어야 하는 경우를 의미합니다. 각 파드는 단순한 일꾼이 아니라, 이름과 역할이 정해진 특별한 존재와 같습니다.

주요 특징

  • 안정적이고 예측 가능한 파드 이름: StatefulSet의 파드는 [StatefulSet 이름]-[순번] 형식의 고유하고 예측 가능한 이름을 갖습니다. (예: my-db-0, my-db-1, my-db-2)
  • 안정적인 퍼시스턴트 스토리지: 각 파드는 자신의 순번에 맞는 고유한 PersistentVolumeClaim(PVC)을 가집니다. my-db-0 파드가 재시작되어도, 이전에 사용하던 바로 그 PVC에 다시 연결됩니다. 이를 통해 파드는 자신의 고유한 데이터를 잃지 않습니다.
  • 안정적인 네트워크 신원: 각 파드는 고유한 DNS 이름을 가집니다. (예: my-db-0.my-service.my-namespace.svc.cluster.local) 클러스터 내 다른 애플리케이션들이 my-db-0이라는 특정 파드를 이름으로 직접 찾아 통신할 수 있습니다.
  • 순서가 보장된 운영:
    • 생성 및 확장: 파드는 순번대로(0부터) 하나씩 생성됩니다. my-db-0이 Running 및 Ready 상태가 되어야만 my-db-1이 생성됩니다.
    • 삭제 및 축소: 파드는 역순으로(가장 큰 순번부터) 하나씩 삭제됩니다.
    • 업데이트: 파드는 역순으로 하나씩 순차적으로 업데이트됩니다.

이럴 때 사용하세요!

StatefulSet은 복제본 간에 데이터를 동기화하거나, 리더-팔로워(Leader-Follower) 구조를 가지거나, 각 노드가 고유한 데이터를 저장해야 하는 분산 시스템에 필수적입니다.

  • 데이터베이스: MySQL, PostgreSQL (Primary-Secondary 복제 구성), MongoDB (Replica Set)
  • 메시지 큐: Kafka, RabbitMQ (클러스터 모드)
  • 분산 코디네이션 시스템: Zookeeper, etcd, Consul

한눈에 보는 비교: Deployment vs. StatefulSet

구분 Deployment (Stateless) StatefulSet (Stateful)
파드 신원 🎲 임의적, 교체 가능 🐾 고유함, 안정적, 예측 가능 (예: web-0, web-1)
네트워크 단일 Service IP로 접근 각 파드별 고유 DNS 이름 제공
스토리지 모든 파드가 공유 (ReadWriteMany) 또는 상태 없음 각 파드별 고유 스토리지 (PersistentVolume) 보장
확장/축소 💨 빠름, 순서 없음 🐢 순서가 보장됨 (생성: 0->N, 삭제: N->0)
업데이트 🔄 롤링 업데이트 🔄 순차적 업데이트 (역순 또는 파티션 지정)
주 사용처 웹 서버, API 서버 등 데이터베이스, 메시지 큐 등 분산 시스템
 

결론: 핵심은 '상태(State)'의 위치입니다

Deployment와 StatefulSet 사이의 선택은 결국 "애플리케이션의 상태가 어디에 저장되고, 파드의 고유성이 중요한가?" 라는 질문으로 귀결됩니다.

  • 상태를 파드 외부에 저장하고(DB, Redis 등), 파드들은 언제든지 교체되어도 상관없다면?Deployment를 사용하세요.
  • 파드 자체가 고유한 데이터를 저장해야 하고, 안정적인 이름으로 서로를 식별해야 한다면?StatefulSet이 정답입니다.

쿠버네티스에서는 "잘 모르겠다면 일단 Deployment로 시작하라"는 말이 있습니다. 대부분의 현대적인 애플리케이션은 상태를 외부로 분리하여 설계하기 때문입니다. 그러다 애플리케이션이 안정적인 네트워크 이름이나 고유한 스토리지를 요구하는 명백한 신호를 보낼 때, StatefulSet으로 전환하는 것을 고려하면 됩니다.

내 애플리케이션의 특성을 정확히 이해하고 올바른 컨트롤러를 선택하는 것이 안정적이고 확장 가능한 쿠버네티스 시스템을 구축하는 첫걸음입니다.