DevOps/K8S

[K8S] StatefulSet

kyoulho 2024. 10. 10. 21:41

StatefulSet은 Kubernetes에서 상태가 있는 애플리케이션을 관리하기 위한 리소스이다. StatefulSet은 각 파드가 고유한 네트워크 ID와 영구적인 스토리지를 유지하도록 보장하며, 파드의 생성 및 삭제 순서를 관리한다. 이는 데이터베이스, 분산 파일 시스템, 캐시 시스템 등과 같은 애플리케이션에 매우 유용하다.

주요 특징

  • 고유한 네트워크 ID: 각 파드는 고유한 DNS 이름을 가지며, 이는 재시작 후에도 유지된다. 예를 들어, StatefulSet 이름이 mysql이고 replicas가 3인 경우, 파드 이름은 mysql-0, mysql-1, mysql-2로 고정된다.
  • 고유한 영구 스토리지: 각 파드에 대해 고유한 PersistentVolumeClaim을 생성하여, 파드가 삭제되거나 재시작되더라도 동일한 스토리지가 유지된다. 이를 통해 데이터의 영속성을 보장할 수 있다.
  • 순차적인 배포 및 업데이트: 파드의 생성, 삭제, 업데이트를 순차적으로 수행하여 클러스터의 안정성을 유지한다. 새로운 파드가 준비되면 다음 파드가 생성되며, 업데이트 시에도 순차적으로 적용된다.
  • 안정적인 네트워크 연결: StatefulSet은 Headless Service와 함께 사용되어 각 파드가 고정된 호스트 이름을 통해 접근 가능하게 한다. 이는 클러스터 내에서 안정적인 네트워크 통신을 보장한다.

단점

  • 복잡성 증가: StatefulSet은 Deployment에 비해 설정이 더 복잡하며, Headless Service 및 PersistentVolume 설정이 필요하다.
  • 확장성 제한: 파드가 순차적으로 배포되므로, 대규모 확장이 필요한 경우 시간이 더 소요될 수 있다.
  • 리소스 소모: 각 파드에 고유한 PersistentVolume을 할당하므로, 스토리지 리소스가 더 많이 소모될 수 있다.
Headless Service란
Kubernetes에서 서비스의 클러스터 IP를 할당하지 않고, 대신 개별 파드에 직접 접근할 수 있도록 하는 특별한 유형의 서비스이다. 일반적인 Kubernetes 서비스는 클러스터 내부에서 고정된 IP 주소를 할당받아 파드의 집합에 대한 단일 진입점을 제공하지만, Headless Service는 이러한 단일 진입점을 제공하지 않고 각 파드에 고유한 DNS 이름을 부여하여 직접 통신할 수 있게 한다.


왜 파드의 순서가 필요한가?

동일한 기능을 수행하는 파드라도 특정 순서로 시작되고 종료되어야 하는 이유는 다음과 같다.

1. 리더 선출 및 클러스터 안정성

분산 데이터베이스나 클러스터 관리 시스템에서는 리더 노드가 있어야 한다. 예를 들어, etcd나 ZooKeeper 같은 시스템에서는 리더 노드가 클러스터의 상태를 관리하고 다른 노드들과의 동기화를 담당한다. 이러한 시스템에서는 리더 노드가 먼저 시작되고, 다른 팔로워 노드들이 그 뒤를 따라야 안정적인 클러스터 운영이 가능하다.

2. 데이터 복제 및 동기화

데이터베이스 클러스터에서는 데이터의 일관성을 유지하기 위해 복제와 동기화가 필수적이다. 파드가 순차적으로 시작되면 데이터 복제 과정이 순서대로 진행되어 데이터 무결성을 보장할 수 있다. 만약 모든 파드가 동시에 시작된다면 데이터 복제가 제대로 이루어지지 않을 수 있다.

3. 의존성 관리

일부 애플리케이션은 특정 파드가 먼저 준비되어야 다른 파드가 정상적으로 동작할 수 있다. 예를 들어, Redis Sentinel은 마스터 노드가 먼저 시작되고, 슬레이브 노드들이 그 마스터에 연결된다. 이 순서가 보장되지 않으면 슬레이브 노드가 마스터 노드를 찾지 못해 정상적으로 동작하지 않을 수 있다.

4. 롤링 업데이트의 안정성

StatefulSet은 파드의 롤링 업데이트 시 순차적으로 업데이트를 진행한다. 이는 모든 파드가 동시에 업데이트되지 않도록 하여 클러스터의 가용성을 유지하고, 업데이트 중에도 안정적인 서비스를 제공할 수 있게 한다.

 

StatefulSet과 Deployment의 차이점

기능 StatefulSet Deployment
Pod 식별 고유한 이름(my-app-0, my-app-1, …)  동적 이름(my-app-xyz123)
스토리지 각 파드에 고유한 PersistentVolume 할당 파드 삭제 시 스토리지도 함께 삭제됨
배포 순서 순차적으로 배포 및 업데이트 병렬적으로 배포 및 업데이트
사용 사례 상태가 있는 애플리케이션 (데이터베이스, 캐시 등) 상태가 없는 애플리케이션 (웹 서버, 워커 등)
네트워크 ID 고정된 DNS 이름을 사용 고유하지 않은 DNS 이름을 사용

 

StatefulSet 설정 예시

예시는 3개의 MySQL 인스턴스를 배포하고, 각 인스턴스에 고유한 PersistentVolume을 할당한다.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  serviceName: "mysql"
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: password
  volumeClaimTemplates:
  - metadata:
      name: mysql-persistent-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

 

  • serviceName: StatefulSet이 연결될 Headless Service의 이름. Headless Service는 클러스터 내에서 각 파드에 고유한 DNS 이름을 할당할 수 있도록 한다.
  • replicas: 생성할 파드의 수를 정의한다. 이 예시에서는 3개의 MySQL 인스턴스를 생성한다.
  • selector: StatefulSet이 관리할 파드를 선택하는 라벨 셀렉.
  • template: 각 파드의 템플릿을 정의한다. 여기에는 사용할 컨테이너 이미지, 포트, 환경 변수 등이 포함된다.
  • volumeClaimTemplates: 각 파드에 대해 생성할 PersistentVolumeClaim을 정의한다. 각 PVC는 파드가 삭제되더라도 동일하게 유지된다.

 

StatefulSet 사용 시 고려사항

Pod 관리 정책

StatefulSet은 기본적으로 OrderedReady 전략을 사용하여 파드를 순차적으로 관리한다. 이는 파드가 준비된 후에 다음 파드를 생성하거나 업데이트하도록 한다. 필요에 따라 다른 관리 정책으로 변경할 수 있다.

네트워크 정책과 보안

StatefulSet을 사용할 때는 각 파드가 고유한 네트워크 ID를 가지므로, 네트워크 정책을 통해 파드 간의 통신을 세밀하게 제어할 수 있다. 또한, PersistentVolume에 대한 접근 권한도 적절히 설정해야 한다.

 

 

 

728x90

'DevOps > K8S' 카테고리의 다른 글

[K8S] 클러스터 버전 업그레이드  (0) 2024.10.16
[K8S] 테인트와 톨러레이션  (0) 2024.10.14
[K8S] Metric Server  (0) 2024.10.10
[K8S] MetalLB  (1) 2024.10.10
[K8S] 인그레스와 관련 리소스  (1) 2024.10.08