본문 바로가기

devops/k8s

Statefulset과 Deployment 차이점이란?

helm을 통해서 kafka를 배포했는데 배포된 리소스의 타입이 statefulset이었다. 왜 deployment을 안쓰고 statefulset을 사용을 하는지 궁금해져서 관련된 내용을 찾아보게 되었다.

StatefulSet이란?

공식문서에서는 애플리케이션의 스테이트풀을 관리하는데 사용하는 워크로드 API 오프젝트라고 소개한다. 즉, 상태를 안정적으로 관리할 수 있는 리소스라는 것이다.

스테이트 풀셋은 다음과 같은 요구 사항이 필요한 어플리케이션에 적합하다고 한다.

  • 안정적이고 고유한 네트워크 식별자가 필요한 경우
  • 안정적이고 지속적으로 유지가 필요한 스토리지가 필요한 경우
  • 순차적인, 정상 배포(graceful deployment)와 스케일링이 필요한 경우
  • 순차적인 자동 롤링 업데이트가 필요한 경우

구체적인 사례와 연관지어서 생각을 해보면 스테이트풀셋이 적합한 어플리케이션으로는 데이터베이스가 있다. 데이터 베이스는 영구적으로 데이터의 상태를 저장하는 스토리지 공간이 필요하고 이 공간은 안정적이고 지속적으로 운영이 되어야한다는 특징이 있다. 또한 테이터 베이스를 복제셋이나 클러스터로 운영하기 위해서는 각자를 식별할 수 있어야한다. 스테이트풀셋을 이런 요구사항에 적합한 쿠버네티스의 리소스이다.

StatefulSet과 Deployment의 차이는?

그렇다면 두가지 리소스의 차이는 무엇일까?

1. 영구적인 스토리지 사용

우선 스테이트 풀셋은 영구적인 스토리지(pvc)를 각 pod 마다 할당하여 사용해야한다. 이에 반해 디플로이먼트는 영구적인 스토리지를 선택적으로 사용할 수 있고 사용을 하더라도 모든 pod와 공유하는 공유 스토리지로 사용한다.

StatefulSet 구성
deployment 구성

2. pod를 지속적으로 식별할 수 있는지 여부

스테이트풀셋은 pod를 생성할 때, 그 식별자(name)을 일관성있는 규칙을 가지고 생성한다. 예를 들어서 web이라는 스테이트 풀셋있다면 그 스테이트풀셋의 pod의 식별자(name)은 web-0, web-1, ... , web-n 까지 순차적으로 생성된다. 때문에 지속적으로 각 pod를 식별할 수 있는 예측가능한 식별자를 가질 수 있다. 이에 반해 디플로이먼트는 랜덤한 식별자를 생성한다.

3. 순차적인 삭제 및 갱신

스테이트풀셋을 갱신하거나 삭제할 때, 그 순서가 정해져있다. 이에 반해 디플로이먼트는 삭제 및 갱신 작업을 수행할 때, 설정된 전략에 따라서 무작위의 pod를 대상으로 삭제 및 갱신 작업을 수행하게 된다.

Headless service

스테이트풀셋의 제한사항 중에는 스테이트풀셋은 현재 파드의 네트워크 신원을 책임지고 있는 헤드리스 서비스 가 필요하다. 사용자가 이 서비스를 생성할 책임이 있다. 라고 한다. 헤드리스 서비스가 왜 무엇인지를 알아보았다.

헤드리스 서비스는 무엇일까? 우선 헤드가 무엇일까? 헤드는 무언가를 대표하는 사람이나 상징적인 무언가를 말한다. 쿠버네티스의 서비스는 배포된 어플리케이션에 접속하기 위한 헤드로서 작동하는 clusterIP, loadBalancer, NodPort, Ingress와 같은 타입있다. 이 모든 타입은 하나의 서비스가 배포된 어플리케이션의 집합을 대표한다.
하지만 헤드리스 서비스는 이를 대표하지 않는다. 때문에 접속을 위해서는 연결하고자하는 pod에 대한 추가적인 정보를 입력하여 연결한다. pod-name.headless-service-name.namespace.svc.cluster-domain.example 이런 도메인을 통해서 접속할 수 있다.

스테이트풀셋은 headless service와 많이 사용되는데 이는 안정되고 고유한 네트워크 식별자를 가지는 특징으로 인해서 동일한 요소의 pod가 상호작용할 때, 유용하기 때문이다. 앞선 사례에서 데이터베이스의 복제 셋 구성을 배포하는 상황을 생각해보자. 모든 pod는 복제셋에 연결되어야하고 복제셋에서 각 pod를 식별할 안정적인 식별자 역시 필요하다. 이 상황에서 스테이트 풀셋과 헤드리스 서비스의 조합을 사용하면 안정적으로 고유한 식별자를 사용하는 데이터베이스 pod를 통해서 복제셋을 구성할 수 있다.

참고 자료

k8s 공식문서 : StatefulSet
k8s 공식문서 : headless service
healess가 필요한 이유에 대한 블로그 포스팅
k8s 공식문서 : 서비스 및 파드용 DNS