Data Engineering/s3 minio

EP05 [ MinIO S3 + Cilium 기초 과정 ] MinIO 기본 설치 및 관리 #2 | StatefulSet 작동 원리 - 쿠버네티스 상태 유지 워크로드 관리

ygtoken 2025. 3. 28. 13:49
728x90

이 글에서는 쿠버네티스 StatefulSet의 작동 원리와 MinIO와 같은 상태 유지가 필요한 워크로드의 관리 방법에 대해 살펴봅니다. Deployment와 StatefulSet의 차이점, StatefulSet의 특성과 구성 방법, 그리고 MinIO 분산 모드 배포를 위한 StatefulSet 활용법을 자세히 알아보겠습니다.


📌 상태 유지(Stateful) 워크로드의 의미와 과제

✅ 상태 비유지(Stateless) vs 상태 유지(Stateful) 워크로드

쿠버네티스 환경에서 워크로드는 크게 두 가지 유형으로 분류됩니다.

▶️ 상태 비유지(Stateless) 워크로드:

  • 모든 요청이 독립적으로 처리됨
  • 이전 요청이나 세션 정보를 저장할 필요 없음
  • 인스턴스를 언제든지 재시작, 교체, 스케일링해도 영향 없음
  • 예: 웹 서버, API 서버, 프론트엔드 애플리케이션

▶️ 상태 유지(Stateful) 워크로드:

  • 이전 요청이나, 세션, 트랜잭션 정보를 기억해야 함
  • 고유한 네트워크 식별자 필요
  • 영구 스토리지에 데이터 저장 필요
  • 인스턴스 순서와 신원이 중요함
  • 예: 데이터베이스, 메시지 큐, MinIO와 같은 스토리지 서비스

✅ 상태 유지 워크로드의 과제

쿠버네티스 환경에서 상태 유지 워크로드를 관리할 때 직면하는 주요 과제는 다음과 같습니다:

 

▶️ 네트워크 신원(Identity):

  • Pod IP는 재시작 시 변경됨
  • 클러스터 내에서 일관된 호스트 이름 필요
  • 다른 Pod와 안정적으로 통신할 수 있는 방법 필요

▶️ 데이터 지속성(Persistence):

  • Pod가 재시작되어도 데이터 유지 필요
  • Pod와 볼륨의 안정적인 연결 필요
  • 스토리지 상태 관리 필요

▶️ 배포 및 스케일링 순서:

  • 특정 순서로 Pod 시작 및 종료 필요
  • 버전 업그레이드 시 순차적 처리 필요
  • 스케일링 시 새 인스턴스 구성 관리 필요

상태 유지 워크로드와 상태 비유지 워크로드의 창이점 비교 다이어그램


📌 StatefulSet 소개 및 주요 특성

✅ StatefulSet이란?

StatefulSet은 쿠버네티스에서 상태 유지가 필요한 애플리케이션을 관리하기 위한 워크로드 리소스입니다.

# 기본적인 StatefulSet 예시
apiVersion: apps/v1            # apps API 그룹의 v1 버전 사용
kind: StatefulSet              # 리소스 종류는 StatefulSet
metadata:
  name: web                    # StatefulSet의 이름
spec:
  selector:                    # 관리할 Pod을 선택하는 라벨 셀렉터
    matchLabels:
      app: nginx               # 'app: nginx' 라벨이 있는 Pod 관리
  serviceName: "nginx"         # 연결된 헤드리스 서비스 이름
  replicas: 3                  # 복제본 수 (3개의 Pod 생성)
  template:                    # Pod 템플릿 정의
    metadata:
      labels:
        app: nginx             # 생성될 Pod에 적용할 라벨
    spec:
      containers:              # Pod 내 컨테이너 정의
      - name: nginx            # 컨테이너 이름
        image: nginx:1.14.2    # 사용할 이미지
        ports:
        - containerPort: 80    # 컨테이너 내부 포트
          name: web            # 포트 이름
        volumeMounts:          # 볼륨 마운트 설정
        - name: www            # 마운트할 볼륨 이름
          mountPath: /usr/share/nginx/html  # 마운트 경로
  volumeClaimTemplates:        # 각 Pod용 PVC 자동 생성 템플릿
  - metadata:
      name: www                # 생성될 PVC 이름
    spec:
      accessModes: [ "ReadWriteOnce" ]  # 볼륨 접근 모드
      resources:
        requests:
          storage: 1Gi         # 스토리지 요청 크기

✅ StatefulSet의 핵심 특성

StatefulSet은 다음과 같은 핵심 특성을 제공합니다:

 

▶️ 안정적인 네트워크 식별자:

  • 각 Pod에 <statefulset-name>-<ordinal-index> 형식의 고정 이름 부여
  • 위 예시에서는 web-0, web-1, web-2와 같은 이름 할당
  • 헤드리스 서비스와 결합하여 안정적인 DNS 이름 제공
    • <pod-name>.<service-name>.<namespace>.svc.cluster.local
    • 예: web-0.nginx.default.svc.cluster.local

▶️ 안정적인 스토리지:

  • volumeClaimTemplates를 통해 각 Pod에 대한 PVC 자동 생성
  • Pod가 재스케줄링되어도 동일한 스토리지 유지
  • Pod 이름과 연결된 PVC 이름 부여 (예: www-web-0, www-web-1)

▶️ 순차적인 배포와 스케일링:

  • Pod가 순서대로 생성됨 (0, 1, 2, ...)
  • 이전 Pod가 Ready 상태가 되어야 다음 Pod 생성
  • 삭제 시 역순으로 처리 (2, 1, 0, ...)
  • 업데이트도 순차적으로 진행됨

▶️ 네트워크 신원과 헤드리스 서비스:

  • 헤드리스 서비스 필요 (clusterIP: None 설정)
  • 각 Pod에 대한 DNS 레코드 생성
  • Pod 간 직접 통신 가능

StatefulSet 생성 후 Pod, PVC, DNS 레코드 관계를 보여주는 다이어그램

✅ Deployment vs StatefulSet

두 리소스의 주요 차이점을 이해하는 것이 중요합니다:

특성 Deployment StatefulSet
Pod 이름 랜덤 생성 (예: nginx-75f86df8b4-xvdg6) 예측 가능한 이름 (예: web-0, web-1)
Pod 생성/삭제 순서 병렬 처리 순차적 처리
스토리지 공유 볼륨 또는 임시 볼륨 Pod별 고유 볼륨
네트워크 ID 불안정, 재시작 시 변경 안정적, 재시작해도 유지
업데이트 전략 롤링 업데이트, 블루/그린, 카나리 순차적 업데이트
사용 사례 웹 서버, API 서버, 프론트엔드 데이터베이스, 스토리지 서비스, 메시지 큐
# Deployment와 StatefulSet 생성 비교

# Deployment 생성 및 확인
$ kubectl create deployment nginx --image=nginx
deployment.apps/nginx created

$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-75f86df8b4-xvdg6   1/1     Running   0          5s

# StatefulSet 생성 및 확인
$ kubectl apply -f statefulset.yaml
statefulset.apps/web created

$ kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          10s
web-1   1/1     Running   0          20s
web-2   1/1     Running   0          30s

📌 StatefulSet 작동 원리 심층 분석

✅ Pod 신원과 순서

StatefulSet의 Pod는 0부터 시작하는 순차적인 인덱스를 기반으로 신원이 할당됩니다.

 

▶️ Pod 신원의 특성:

  • 생성 및 삭제 순서가 결정적임
  • 공유 서비스 도메인으로부터 파생된 네트워크 신원 보유
  • Pod가 삭제되고 재생성되어도 동일한 이름과 신원 유지
  • 노드 간 이동해도 신원 유지

▶️ 관리 순서:

  • 생성: 0, 1, 2, ... (오름차순)
  • 삭제: ..., 2, 1, 0 (내림차순)
  • 스케일 다운: 가장 높은 인덱스부터 삭제
  • 업데이트: podManagementPolicy 설정에 따라 달라짐
# Pod 관리 정책 설정 예시
spec:
  podManagementPolicy: OrderedReady  # 기본값: 순차적 처리
  # 또는
  podManagementPolicy: Parallel       # 병렬 처리 (순서 무시)

✅ 헤드리스 서비스 연동

StatefulSet은 안정적인 네트워크 신원을 제공하기 위해 헤드리스 서비스와 연동됩니다.

# 헤드리스 서비스 예시
apiVersion: v1                  # 핵심 API 그룹의 v1 버전
kind: Service                   # 리소스 종류는 Service
metadata:
  name: nginx                   # 서비스 이름 (StatefulSet의 serviceName과 일치해야 함)
  labels:
    app: nginx                  # 서비스 식별 라벨
spec:
  ports:
  - port: 80                    # 서비스 포트
    name: web                   # 포트 이름
  clusterIP: None               # 헤드리스 서비스 설정 (중요!)
  selector:
    app: nginx                  # Pod 선택 라벨 (StatefulSet Pod 라벨과 일치해야 함)

 

▶️ 헤드리스 서비스의 역할:

  • clusterIP: None으로 설정
  • 클러스터 IP 주소가 아닌 개별 Pod의 DNS 레코드 생성
  • 각 Pod에 대해 다음 형식의 DNS 레코드 제공:
    • <pod-name>.<service-name>.<namespace>.svc.cluster.local
    • 예: web-0.nginx.default.svc.cluster.local

▶️ DNS 레코드 확인 방법:

# DNS 확인 예시
$ kubectl run -it --rm debug --image=busybox -- nslookup web-0.nginx
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      web-0.nginx
Address 1: 10.244.1.15 web-0.nginx.default.svc.cluster.local

✅ 볼륨 클레임 템플릿과 스토리지

StatefulSet의 가장 중요한 특성 중 하나는 Pod별 영구 스토리지를 관리하는 방식입니다.

# 볼륨 클레임 템플릿 예시
volumeClaimTemplates:           # 각 Pod별 PVC 자동 생성을 위한 템플릿
- metadata:
    name: www                   # 볼륨 클레임 기본 이름
  spec:
    accessModes: ["ReadWriteOnce"]  # 단일 노드에서만 읽기/쓰기 가능
    storageClassName: "standard"    # 사용할 스토리지 클래스
    resources:
      requests:
        storage: 1Gi            # 요청할 스토리지 크기

 

▶️ 볼륨 클레임 템플릿 특성:

  • 각 Pod마다 고유한 PVC 자동 생성
  • PVC 이름 형식: <volumeClaimTemplate-name>-<statefulset-name>-<ordinal-index>
  • 예: www-web-0, www-web-1, www-web-2
  • Pod가 삭제되어도 PVC는 유지됨 (데이터 보존)
  • Pod가 다른 노드로 이동해도 해당 PVC 재연결

▶️ PVC 및 Pod 삭제 시 동작:

  • Pod를 삭제해도 PVC는 자동으로 삭제되지 않음
  • StatefulSet을 삭제해도 PVC는 유지됨
  • PVC를 수동으로 삭제하면 데이터가 영구적으로 손실됨
  • persistentVolumeClaimRetentionPolicy 설정으로 삭제 정책 조정 가능 (1.23+)
# PVC 유지 정책 예시 (쿠버네티스 1.23+)
spec:
  persistentVolumeClaimRetentionPolicy:
    whenDeleted: Retain    # StatefulSet 삭제 시 PVC 유지 (기본값)
    # 또는 Delete          # StatefulSet 삭제 시 PVC 삭제
    
    whenScaled: Retain     # Pod 스케일 다운 시 PVC 유지 (기본값)
    # 또는 Delete          # Pod 스케일 다운 시 PVC 삭제

 

StatefulSet PVC 생성 및 관리 흐름을 보여주는 다이어그램

 


📌 StatefulSet의 업데이트 및 파티션

✅ 업데이트 전략

StatefulSet은 Pod 템플릿 업데이트 방식을 제어하는 다양한 전략을 제공합니다.

# 업데이트 전략 예시
spec:
  updateStrategy:
    type: RollingUpdate          # 기본값: 순차적 롤링 업데이트
    # 또는
    type: OnDelete               # Pod 삭제 시에만 업데이트
    
    # 롤링 업데이트를 위한 추가 설정
    rollingUpdate:
      partition: 2               # 인덱스가 2 이상인 Pod만 업데이트

 

▶️ RollingUpdate 전략:

  • 순차적으로 Pod 업데이트 (인덱스 높은 것부터)
  • 이전 Pod가 Ready 상태가 되어야 다음 Pod 업데이트
  • partition 파라미터로 부분 업데이트 구현 가능

▶️ OnDelete 전략:

  • Pod가 수동으로 삭제될 때만 새 템플릿 적용
  • 업데이트 타이밍을 세밀하게 제어할 수 있음
  • 민감한 상태 유지 애플리케이션에 유용

✅ 파티션을 활용한 카나리 업데이트

파티션 기능을 사용하면 StatefulSet의 일부 Pod만 업데이트하는 카나리 배포 패턴을 구현할 수 있습니다.

# 파티션 설정 예시
spec:
  replicas: 5                    # 총 5개의 Pod
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 3               # 인덱스 3, 4만 업데이트

 

▶️ 파티션 작동 방식:

  • partition 값 이상의 인덱스를 가진 Pod만 업데이트
  • 나머지 Pod는 이전 버전 유지
  • 테스트 후 파티션 값을 줄여가며 점진적 업데이트 가능
# 파티션 업데이트 예시
# 처음 파티션 설정
$ kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}'

# 이미지 업데이트 (web-3, web-4만 업데이트됨)
$ kubectl set image statefulset/web nginx=nginx:1.15

# 테스트 후 파티션 값 줄이기
$ kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":0}}}}'

✅ 스케일링 동작

StatefulSet의 스케일링 동작도 순서가 중요합니다.

 

▶️ 스케일 아웃 (확장):

  • 순차적으로 낮은 인덱스부터 생성
  • 예: 현재 web-0, web-1 실행 중 → 3개로 확장 → web-2 생성

▶️ 스케일 인 (축소):

  • 순차적으로 높은 인덱스부터 삭제
  • 예: 현재 web-0, web-1, web-2 실행 중 → 1개로 축소 → web-2, web-1 삭제
# StatefulSet 스케일링 예시
# 스케일 아웃
$ kubectl scale statefulset web --replicas=5

# 스케일 인
$ kubectl scale statefulset web --replicas=2

[StatefulSet 업데이트 및 파티션 동작을 보여주는 다이어그램]


📌 MinIO를 위한 StatefulSet 설계

✅ MinIO 분산 모드의 요구사항

MinIO는 분산 모드로 실행할 때 StatefulSet의 기능이 특히 중요합니다.

 

▶️ MinIO 분산 모드 특성:

  • 여러 서버에 데이터 분산 저장
  • 이라즈 코딩으로 데이터 내구성 확보
  • 서버 간 통신을 위한 안정적인 네트워크 신원 필요
  • 각 서버마다 고유한 스토리지 필요
  • 순차적인 시작 및 종료 절차 필요

▶️ MinIO 분산 모드 구성 요소:

  • MinIO 서버 Pod (최소 4개, 확장성을 위해 짝수 개 권장)
  • 헤드리스 서비스 (Pod 간 통신용)
  • 표준 서비스 (클라이언트 접근용)
  • PVC 템플릿 (각 서버의 데이터 저장용)
  • Secret (자격 증명 저장용)

✅ MinIO용 StatefulSet 예시

다음은 MinIO 분산 모드를 위한 StatefulSet 구성 예시입니다:

# MinIO 분산 모드 StatefulSet 예시
apiVersion: v1                  # 핵심 API 그룹의 v1 버전
kind: Service                   # 리소스 종류는 Service
metadata:
  name: minio-headless          # 헤드리스 서비스 이름
  labels:
    app: minio                  # 서비스 라벨
spec:
  clusterIP: None               # 헤드리스 서비스 설정
  ports:
  - port: 9000                  # MinIO API 포트
    name: api                   # 포트 이름
  selector:
    app: minio                  # 대상 Pod 선택 라벨
---
apiVersion: apps/v1              # apps API 그룹의 v1 버전
kind: StatefulSet                # 리소스 종류는 StatefulSet
metadata:
  name: minio                    # StatefulSet 이름
spec:
  serviceName: minio-headless    # 연결할 헤드리스 서비스 이름
  replicas: 4                    # Pod 복제본 수 (최소 4개, 짝수 권장)
  selector:
    matchLabels:
      app: minio                 # 관리할 Pod 라벨
  template:
    metadata:
      labels:
        app: minio               # Pod에 적용할 라벨
    spec:
      containers:
      - name: minio              # 컨테이너 이름
        image: minio/minio:RELEASE.2023-10-16T04-13-43Z  # MinIO 이미지
        args:
        - server                 # MinIO 서버 모드
        - --address=:9000        # API 주소 바인딩
        - --console-address=:9001 # 콘솔 주소 바인딩
        # 분산 모드 설정 - StatefulSet Pod DNS 이름 활용
        - http://minio-{0...3}.minio-headless.default.svc.cluster.local/data  # Pod DNS 패턴으로 노드 지정
        ports:
        - containerPort: 9000     # MinIO API 포트
          name: api
        - containerPort: 9001     # MinIO 콘솔 포트 
          name: console
        env:
        - name: MINIO_ROOT_USER    # 관리자 사용자명
          valueFrom:
            secretKeyRef:          # Secret에서 값 참조
              name: minio-secret
              key: root-user
        - name: MINIO_ROOT_PASSWORD  # 관리자 비밀번호
          valueFrom:
            secretKeyRef:          # Secret에서 값 참조
              name: minio-secret
              key: root-password
        volumeMounts:
        - name: data               # 마운트할 볼륨 이름
          mountPath: /data         # 컨테이너 내 마운트 경로
  volumeClaimTemplates:           # 각 Pod용 PVC 템플릿
  - metadata:
      name: data                  # 볼륨 클레임 기본 이름
    spec:
      accessModes: [ "ReadWriteOnce" ]  # 접근 모드
      resources:
        requests:
          storage: 10Gi           # 각 서버의 스토리지 크기

✅ DNS 기반 서버 구성

MinIO 분산 모드의 핵심은 StatefulSet과 헤드리스 서비스를 통한 안정적인 DNS 기반 구성입니다.

 

▶️ 서버 인수 패턴 해석:

  • http://minio-{0...3}.minio-headless.default.svc.cluster.local/data
    • minio-{0...3}: Pod 이름 패턴 (minio-0, minio-1, minio-2, minio-3)
    • minio-headless.default.svc.cluster.local: 서비스 DNS 도메인
    • /data: 데이터 디렉토리 경로

▶️ 분산 모드 동작 방식:

  • 각 MinIO 서버 Pod는 시작 시 DNS를 통해 다른 Pod를 발견
  • 모든 Pod가 서로 통신하여 클러스터 형성
  • 데이터는 이라즈 코딩을 통해 분산 저장
  • 일부 Pod가 실패해도 이라즈 코딩으로 데이터 보호

MinIO 분산 모드의 DNS 기반 구성과 데이터 흐름


📌 StatefulSet 운영 모범 사례

✅ 리소스 관리

StatefulSet으로 관리되는 상태 유지 워크로드는 적절한 리소스 관리가 중요합니다.

# 리소스 설정 예시
spec:
  template:
    spec:
      containers:
      - name: minio
        resources:
          requests:             # 최소 요청 리소스
            memory: "1Gi"      # 메모리 요청
            cpu: "500m"        # CPU 요청 (0.5 코어)
          limits:              # 최대 제한 리소스
            memory: "2Gi"      # 메모리 제한
            cpu: "1"           # CPU 제한 (1 코어)

 

▶️ 리소스 관리 모범 사례:

  • 워크로드에 맞는 적절한 리소스 요청 설정
  • 메모리 한도 초과 시 OOM으로 인한 Pod 재시작 고려
  • 상태 유지 애플리케이션은 리소스 부족으로 인한 재시작이 데이터 일관성에 영향 줄 수 있음
  • 충분한 마진 확보

✅ 인터럽트 처리 및 가용성

StatefulSet 워크로드의 가용성을 확보하기 위한 인터럽트 처리 설정:

# Pod Disruption Budget 예시
apiVersion: policy/v1           # policy API 그룹의 v1 버전
kind: PodDisruptionBudget       # 리소스 종류는 PDB
metadata:
  name: minio-pdb               # PDB 이름
spec:
  minAvailable: 3               # 최소 3개 Pod는 항상 가용해야 함
  # 또는
  # maxUnavailable: 1           # 최대 1개 Pod만 불가용 허용
  selector:
    matchLabels:
      app: minio                # 대상 Pod 선택 라벨

 

▶️ 가용성 확보 모범 사례:

  • PodDisruptionBudget을 설정하여 동시에 중단되는 Pod 수 제한
  • 애플리케이션의 쿼럼(quorum) 요구사항 고려
  • 노드 유지보수 및 업그레이드 중에도 가용성 확보
  • 종료 시 적절한 정리 작업을 위한 라이프사이클 훅 설정
# 라이프사이클 훅 설정 예시
spec:
  template:
    spec:
      containers:
      - name: minio
        lifecycle:
          preStop:              # Pod 종료 전 실행할 훅
            exec:
              command:          # 정상 종료를 위한 명령
              - /bin/sh
              - -c
              - "mc admin service stop local/"

✅ 백업 및 복구 전략

StatefulSet의 상태 유지 애플리케이션에 대한 백업 및 복구 전략은 필수적입니다.

 

▶️ PVC 백업 방법:

  • 볼륨 스냅샷 사용 (스토리지 클래스가 지원하는 경우)
  • MinIO 자체 백업 도구 사용
  • 외부 백업 솔루션 통합
# 볼륨 스냅샷 예시
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: minio-data-snapshot
spec:
  volumeSnapshotClassName: csi-hostpath-snapclass
  source:
    persistentVolumeClaimName: data-minio-0  # 백업할 PVC 이름

 

▶️ 복구 전략:

  • 스냅샷에서 새 PVC 생성
  • 기존 PVC에 데이터 복원
  • 재해 복구 계획 수립

✅ 모니터링 및 로깅

StatefulSet 및 MinIO 모니터링을 위한 핵심 지표:

 

▶️ StatefulSet 모니터링 지표:

  • Pod 가용성 및 상태
  • 볼륨 사용량 및 성능
  • 노드 분산 상태
  • 업데이트 진행 상황

▶️ MinIO 핵심 모니터링 지표:

  • S3 API 호출 응답 시간
  • 디스크 사용량 및 IOPS
  • 이라즈 코딩 복구 이벤트
  • 데이터 액세스 패턴
# Prometheus ServiceMonitor 예시
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: minio-metrics
spec:
  selector:
    matchLabels:
      app: minio
  endpoints:
  - port: api
    path: /minio/v2/metrics/cluster
    interval: 30s

 


📌 Summary

StatefulSet과 상태 유지 워크로드 관리에 대해 다음과 같은 주요 내용을 살펴보았습니다:

  • StatefulSet은 안정적인 네트워크 신원과 스토리지를 필요로 하는 상태 유지 워크로드를 위한 쿠버네티스 리소스입니다
  • 주요 특징으로는 순차적인 Pod 관리, 안정적인 네트워크 신원, Pod별 영구 스토리지 등이 있습니다
  • 헤드리스 서비스와 함께 사용하여 Pod간 직접 통신을 가능하게 합니다
  • 볼륨 클레임 템플릿을 통해 각 Pod에 대한 영구 스토리지를 자동 관리합니다
  • 업데이트 전략과 파티션 기능을 활용하여 안전한 롤링 업데이트와 카나리 배포를 구현할 수 있습니다
  • MinIO 분산 모드는 안정적인 DNS 이름과 영구 스토리지가 필요하기 때문에 StatefulSet이 이상적입니다
  • 리소스 관리, 인터럽트 처리, 백업 및 복구 전략, 모니터링은 효과적인 StatefulSet 운영의 핵심 요소입니다

 

728x90