Data Engineering/s3 minio

EP09 [ MinIO S3 + Cilium 기초 과정 ] 스토리지 기초 개념 #1 | PV/PVC 완전 정복 - MinIO 데이터 영구 저장하기

ygtoken 2025. 3. 29. 16:17
728x90

이 글에서는 쿠버네티스 환경에서 데이터를 영구적으로 저장하기 위한 핵심 개념인 PV(PersistentVolume)와 PVC(PersistentVolumeClaim)에 대해 상세히 알아보겠습니다. 특히 MinIO와 같은 스토리지 시스템에서 데이터 영속성을 확보하는 방법에 중점을 두고 설명하겠습니다.


📌 PV와 PVC의 개념 이해하기

✅ 쿠버네티스의 스토리지 문제

쿠버네티스 환경에서는 컨테이너가 언제든지 재시작되거나 다른 노드로 이동할 수 있습니다. 이런 특성은 유연성과 확장성을 제공하지만, 데이터 저장에는 큰 도전이 됩니다. 기본적으로 컨테이너 내부에 저장된 데이터는 컨테이너가 삭제되면 함께 사라집니다.

▶️ 예시: 컨테이너 재시작 시나리오

  • MinIO 컨테이너가 오류로 재시작되면 내부 데이터가 모두 손실됨
  • 사용자가 업로드한 파일, 버킷 구성 등이 모두 초기화됨
  • 서비스 중단 및 데이터 손실 발생

✅ PV(PersistentVolume)란?

PersistentVolume은 관리자가 프로비저닝하거나 스토리지 클래스를 통해 동적으로 프로비저닝된 클러스터의 스토리지입니다. 컨테이너나 Pod의 생명주기와 별개로 존재하는 독립적인 리소스입니다.

 

▶️ PV의 주요 특징:

  • 클러스터 수준의 리소스 (네임스페이스에 속하지 않음)
  • 다양한 스토리지 백엔드 지원 (AWS EBS, Azure Disk, NFS, iSCSI 등)
  • 용량, 접근 모드, 재사용 정책 등을 정의할 수 있음
  • Pod의 생명주기와 독립적으로 유지됨

✅ PVC(PersistentVolumeClaim)란?

PersistentVolumeClaim은 사용자의 스토리지 요청입니다. Pod가 PV를 사용하기 위해서는 PVC를 통해 요청해야 합니다. PVC는 필요한 스토리지 용량과 접근 방식을 명시합니다.

 

▶️ PVC의 주요 특징:

  • 네임스페이스에 속하는 리소스
  • 필요한 스토리지 크기, 접근 모드 등을 지정
  • 적절한 PV와 바인딩됨
  • Pod에서 볼륨으로 마운트하여 사용

📌 PV/PVC 라이프사이클 이해하기

✅ 프로비저닝 (Provisioning)

PV를 생성하는 방법에는 정적 프로비저닝과 동적 프로비저닝 두 가지가 있습니다.

  1. 정적 프로비저닝 (Static Provisioning)
    • 관리자가 미리 PV를 생성해 놓는 방식
    • 클러스터에 사용 가능한 스토리지 풀을 준비
apiVersion: v1                   # 쿠버네티스 API 버전으로, PV는 핵심 리소스이므로 v1 사용
kind: PersistentVolume           # 리소스 종류를 PersistentVolume으로 지정
metadata:
  name: minio-pv                 # 이 PV를 식별하기 위한 고유 이름 지정
spec:
  capacity:
    storage: 10Gi                # 이 PV의 용량을 10GiB로 설정, MinIO의 데이터 저장에 충분한 공간 확보
  accessModes:
    - ReadWriteOnce              # 하나의 노드에서만 읽기/쓰기가 가능하도록 설정, 대부분의 스토리지에서 지원하는 기본 모드
  persistentVolumeReclaimPolicy: Retain  # PVC가 삭제되어도 PV와 데이터를 유지하도록 설정, 중요 데이터 보존을 위함
  hostPath:                      # Docker Desktop 환경에서 테스트용으로 사용하는 hostPath 타입 스토리지 지정
    path: /data/minio-pv         # 호스트 머신의 실제 경로, 데이터가 저장될 디렉토리 지정
  1. 동적 프로비저닝 (Dynamic Provisioning)
    • StorageClass를 이용해 PVC 요청 시 자동으로 PV 생성
    • 클라우드 환경에서 많이 사용됨
apiVersion: storage.k8s.io/v1    # 스토리지 관련 리소스는 storage.k8s.io API 그룹 사용
kind: StorageClass               # 동적 볼륨 프로비저닝을 위한 StorageClass 정의
metadata:
  name: minio-sc                 # 이 StorageClass를 식별하는 고유 이름
provisioner: k8s.io/minikube-hostpath  # Docker Desktop/Minikube 환경에서 사용하는 프로비저너, 실제 환경에서는 클라우드 프로비저너 사용
reclaimPolicy: Retain            # PVC 삭제 시 PV를 유지하도록 설정, 데이터 안전성 확보
volumeBindingMode: Immediate     # PVC 생성 즉시 PV를 바인딩하도록 설정, 빠른 볼륨 할당을 위함

✅ 바인딩 (Binding)

사용자가 PVC를 생성하면 쿠버네티스는 적절한 PV를 찾아 바인딩합니다. PVC의 요구사항(크기, 접근 모드 등)과 일치하는 PV를 선택합니다.

apiVersion: v1                   # PVC도 핵심 리소스이므로 v1 API 버전 사용
kind: PersistentVolumeClaim      # 리소스 종류를 PersistentVolumeClaim으로 지정
metadata:
  name: minio-data-claim         # 이 PVC를 식별하는 고유 이름, Pod에서 이 이름으로 참조
  namespace: minio-system        # PVC가 속할 네임스페이스 지정, 같은 네임스페이스의 Pod만 접근 가능
spec:
  accessModes:
    - ReadWriteOnce              # 단일 노드에서 읽기/쓰기 접근 모드 요청, MinIO 단일 인스턴스에 적합
  resources:
    requests:
      storage: 8Gi               # 필요한 스토리지 용량 8GiB 요청, MinIO 운영에 충분한 공간
  storageClassName: minio-sc     # 사용할 StorageClass 지정, 동적 프로비저닝에 사용됨

✅ 사용 (Using)

Pod에서는 볼륨 정의와 volumeMounts를 통해 PVC를 사용합니다.

apiVersion: v1                   # Pod 정의에는 핵심 리소스 v1 API 버전 사용
kind: Pod                        # 리소스 종류를 Pod로 지정
metadata:
  name: minio-server             # Pod의 고유 이름 지정
  namespace: minio-system        # Pod가 속할 네임스페이스 지정, PVC와 같은 네임스페이스여야 함
spec:
  containers:
  - name: minio                  # 컨테이너 이름 지정, 로그 확인 등에 사용
    image: minio/minio:RELEASE.2023-07-21T21-12-44Z  # 안정적인 특정 버전의 MinIO 이미지 사용
    args:
    - server                     # MinIO를 서버 모드로 실행하는 인자
    - /data                      # MinIO가 데이터를 저장할 경로 지정, 볼륨 마운트 지점과 일치해야 함
    ports:
    - containerPort: 9000        # MinIO의 API 서비스 포트 노출
    - containerPort: 9001        # MinIO 콘솔 UI 포트 노출
    volumeMounts:
    - name: minio-data           # 사용할 볼륨 이름, volumes 섹션에 정의된 이름과 일치해야 함
      mountPath: /data           # 컨테이너 내부에서 볼륨이 마운트될 경로, MinIO 데이터 저장 위치
  volumes:
  - name: minio-data             # 볼륨 이름 정의, volumeMounts에서 참조됨
    persistentVolumeClaim:
      claimName: minio-data-claim  # 사용할 PVC 이름 지정, 앞서 생성한 PVC와 일치해야 함

✅ 반환 (Reclaiming)

PVC가 삭제되면 PV는 재사용 정책(persistentVolumeReclaimPolicy)에 따라 처리됩니다.

  • Retain: PV를 유지하고 수동으로 관리자가 처리해야 함
  • Delete: PV와 관련 스토리지 자산을 자동으로 삭제
  • Recycle: PV의 데이터를 삭제하고 재사용 가능하게 함 (deprecated)

📌 MinIO에서 PV/PVC 활용하기

✅ MinIO의 데이터 지속성 요구사항

MinIO는 객체 스토리지로 대용량 데이터를 저장하고 관리합니다. 이러한 데이터는 컨테이너가 재시작되더라도 유지되어야 합니다.

▶️ MinIO 데이터 유형:

  • 사용자 업로드 파일 (객체)
  • 버킷 메타데이터
  • 사용자 인증 정보
  • 액세스 정책 및 설정

✅ MinIO 단일 인스턴스 PVC 구성

단일 MinIO 인스턴스에서 PVC를 구성하는 방법을 알아봅시다.

  1. 네임스페이스 생성
apiVersion: v1                   # 네임스페이스는 핵심 리소스이므로 v1 API 버전 사용
kind: Namespace                  # 리소스 종류를 Namespace로 지정
metadata:
  name: minio-system             # 네임스페이스 이름을 minio-system으로 지정, MinIO 관련 리소스를 그룹화
  1. PVC 생성
apiVersion: v1                   # PVC는 핵심 리소스이므로 v1 API 버전 사용
kind: PersistentVolumeClaim      # 리소스 종류를 PersistentVolumeClaim으로 지정
metadata:
  name: minio-data-claim         # PVC 이름 지정, Pod에서 이 이름으로 참조함
  namespace: minio-system        # PVC가 생성될 네임스페이스 지정
spec:
  accessModes:
    - ReadWriteOnce              # 단일 노드에서만 마운트 가능한 접근 모드 지정, MinIO 단일 인스턴스에 적합
  resources:
    requests:
      storage: 10Gi              # 필요한 스토리지 용량 요청, 실제 사용량에 따라 조정 필요
  storageClassName: standard     # 사용할 스토리지 클래스 지정, 환경에 따라 다름(Docker Desktop에서는 standard가 기본값)
  1. MinIO Deployment 생성
apiVersion: apps/v1              # Deployment는 apps API 그룹의 v1 버전 사용
kind: Deployment                 # 리소스 종류를 Deployment로 지정, Pod 관리 및 복제 기능 제공
metadata:
  name: minio                    # Deployment 이름 지정
  namespace: minio-system        # 배포될 네임스페이스 지정, PVC와 같은 네임스페이스여야 함
spec:
  replicas: 1                    # Pod 복제본 수를 1로 설정, PV가 ReadWriteOnce이므로 단일 복제본만 가능
  selector:
    matchLabels:
      app: minio                 # Pod 선택을 위한 라벨 지정, template 섹션의 라벨과 일치해야 함
  template:
    metadata:
      labels:
        app: minio               # Pod에 적용될 라벨 지정, selector의 matchLabels와 일치해야 함
    spec:
      containers:
      - name: minio              # 컨테이너 이름 지정
        image: minio/minio:RELEASE.2023-07-21T21-12-44Z  # 특정 버전의 MinIO 이미지 사용, 안정성 확보
        args:
        - server                 # MinIO 서버 모드 실행 인자
        - /data                  # 데이터 저장 경로 지정
        env:
        - name: MINIO_ROOT_USER           # MinIO 루트 사용자 환경 변수 설정
          value: "minio"                  # 루트 사용자 이름 지정, 프로덕션에서는 Secret으로 관리해야 함
        - name: MINIO_ROOT_PASSWORD       # MinIO 루트 비밀번호 환경 변수 설정
          value: "minio123"               # 루트 비밀번호 지정, 프로덕션에서는 Secret으로 관리해야 함
        ports:
        - containerPort: 9000    # API 서비스 포트 노출
          name: api              # 포트 이름 지정, Service에서 참조 가능
        - containerPort: 9001    # 콘솔 UI 포트 노출
          name: console          # 포트 이름 지정
        volumeMounts:
        - name: data             # 볼륨 이름 지정, volumes 섹션의 이름과 일치해야 함
          mountPath: /data       # 컨테이너 내부 마운트 경로, MinIO 데이터 저장 위치
      volumes:
      - name: data               # 볼륨 이름 정의
        persistentVolumeClaim:
          claimName: minio-data-claim  # 사용할 PVC 이름 지정, 앞서 생성한 PVC와 일치해야 함
  1. MinIO 서비스 생성
apiVersion: v1                   # Service는 핵심 리소스이므로 v1 API 버전 사용
kind: Service                    # 리소스 종류를 Service로 지정, 네트워크 접근 제공
metadata:
  name: minio                    # 서비스 이름 지정
  namespace: minio-system        # 서비스가 생성될 네임스페이스 지정
spec:
  ports:
  - port: 9000                   # 서비스에서 노출할 포트 번호
    targetPort: api              # Pod의 대상 포트 이름(containerPort 참조)
    name: api                    # 서비스 포트 이름
  - port: 9001                   # 콘솔 UI용 포트 번호
    targetPort: console          # Pod의 대상 포트 이름
    name: console                # 서비스 포트 이름
  selector:
    app: minio                   # 트래픽을 라우팅할 Pod 선택 라벨, Deployment template 라벨과 일치
  type: ClusterIP                # 서비스 타입 지정, 클러스터 내부 IP 할당

✅ PVC 상태 확인 및 관리하기

PVC 및 PV 상태를 확인하고 관리하는 명령어를 알아봅시다.

  1. PVC 목록 확인
# 특정 네임스페이스의 모든 PVC 조회
kubectl get pvc -n minio-system

# 자세한 정보 확인
kubectl describe pvc minio-data-claim -n minio-system
  1. PV 목록 확인
# 모든 PV 조회
kubectl get pv

# 특정 PV 상세 정보 확인
kubectl describe pv <pv-name>
  1. 스토리지 용량 확인
# kubectl top 명령어로 스토리지 사용량 확인 (metrics-server 필요)
kubectl top pod -n minio-system

📌 Docker Desktop에서의 PV/PVC 특성

✅ Docker Desktop의 스토리지 제약사항

Docker Desktop은 개발 환경에 최적화된 쿠버네티스 환경을 제공합니다. 그러나 몇 가지 제약사항이 있습니다.

▶️ 주요 제약사항:

  • 노드가 하나만 존재 (단일 노드 클러스터)
  • PV의 실제 데이터는 VM 내부에 저장됨
  • 호스트와 VM 간 볼륨 공유에 제한이 있음

✅ hostPath 기반 PV 사용하기

Docker Desktop에서는 주로 hostPath 타입의 PV를 사용합니다.

apiVersion: v1                   # PV는 핵심 리소스이므로 v1 API 버전 사용
kind: PersistentVolume           # 리소스 종류를 PersistentVolume으로 지정
metadata:
  name: minio-local-pv           # PV 이름 지정
spec:
  capacity:
    storage: 10Gi                # 용량 설정, 실제 물리적 제한은 없지만 논리적 크기 지정
  accessModes:
    - ReadWriteOnce              # 단일 노드에서 읽기/쓰기 접근 모드 설정
  persistentVolumeReclaimPolicy: Retain  # PVC 삭제 시 PV 유지 정책 설정
  hostPath:                      # Docker Desktop에서 사용 가능한 hostPath 볼륨 타입 지정
    path: /tmp/minio-data        # VM 내부의 경로 지정, 컨테이너 재시작 시에도 데이터 유지
    type: DirectoryOrCreate      # 디렉토리가 없으면 생성하도록 설정

✅ Docker Desktop에서 데이터 백업하기

Docker Desktop에서 PV 데이터를 백업하는 방법을 알아봅시다.

  1. 데이터 백업 Job 생성
apiVersion: batch/v1              # Job은 batch API 그룹의 v1 버전 사용
kind: Job                         # 일회성 작업을 위한 Job 리소스 정의
metadata:
  name: minio-backup              # Job 이름 지정
  namespace: minio-system         # Job이 실행될 네임스페이스 지정
spec:
  template:
    spec:
      containers:
      - name: backup              # 컨테이너 이름 지정
        image: alpine:3.14        # 가벼운 Alpine Linux 이미지 사용, 백업 작업에 적합
        command: ["sh", "-c"]     # 실행할 명령어 지정
        args:
        - |
          # 백업 대상 디렉토리 생성
          mkdir -p /backup
          # MinIO 데이터를 tar로 압축하여 백업
          tar -czvf /backup/minio-data-$(date +%Y%m%d).tar.gz /data
          # 백업 완료 메시지
          echo "Backup completed at $(date)"
        volumeMounts:
        - name: minio-data        # MinIO 데이터 볼륨 마운트
          mountPath: /data        # 마운트 경로 지정, 원본 데이터 접근
          readOnly: true          # 읽기 전용으로 마운트하여 데이터 보호
        - name: backup-volume     # 백업 저장 볼륨 마운트
          mountPath: /backup      # 백업 파일 저장 경로
      restartPolicy: Never        # Job 실패 시 재시작하지 않도록 설정
      volumes:
      - name: minio-data          # MinIO 데이터 볼륨 정의
        persistentVolumeClaim:
          claimName: minio-data-claim  # 백업할 데이터가 있는 PVC 이름
      - name: backup-volume       # 백업 저장 볼륨 정의
        hostPath:
          path: /tmp/minio-backups     # 백업 파일이 저장될 호스트 경로
          type: DirectoryOrCreate      # 디렉토리가 없으면 생성

📌 PV/PVC 문제 해결 가이드

✅ 일반적인 문제와 해결 방법

  1. PVC가 Pending 상태에 머무는 경우
    • 원인: 적절한 PV가 없거나 스토리지 클래스가 잘못 지정됨
    • 해결: kubectl describe pvc <pvc-name> 명령으로 이벤트 확인
  2. 볼륨 마운트 오류
    • 원인: 접근 권한 문제나 경로 오류
    • 해결: kubectl describe pod <pod-name> 명령으로 이벤트 확인
  3. PV가 해제(Released)되지 않는 경우
    • 원인: persistentVolumeReclaimPolicy가 Retain으로 설정됨
    • 해결: PV를 수동으로 삭제하거나 재사용 정책 변경

✅ MinIO 특화 문제 해결

  1. MinIO 시작 시 권한 오류
    • 원인: 볼륨 마운트 디렉토리 권한 문제
    • 해결: 적절한 securityContext 설정
spec:
  containers:
  - name: minio
    securityContext:           # 컨테이너 보안 컨텍스트 설정
      runAsUser: 1000          # UID 1000으로 실행하여 적절한 권한 부여
      runAsGroup: 1000         # GID 1000으로 실행
      fsGroup: 1000            # 볼륨에 대한 그룹 ID 설정
  1. 데이터 불일치 문제
    • 원인: 여러 인스턴스가 동일한 PV에 접근 시도
    • 해결: accessMode를 ReadWriteOnce로 설정하고 replicas를 1로 유지

 

📌 Summary

  • PV와 PVC는 쿠버네티스에서 데이터 영속성을 제공하는 핵심 메커니즘
  • 정적/동적 프로비저닝을 통해 스토리지 리소스 할당 가능
  • MinIO에서는 PVC를 통해 객체 스토리지 데이터 보존 가능
  • Docker Desktop에서는 hostPath 타입 PV를 사용하여 개발 환경 구성
  • 적절한 접근 모드와 재사용 정책 설정으로 데이터 안전성 확보
728x90