MinIO
MinIO는 S3 호환 분산 오브젝트 스토리지입니다. Lumie 플랫폼에서 파일 업로드, 백업 저장소, WAL 아카이브 등 다양한 용도로 사용됩니다.
개요
주요 기능
| 기능 | 설명 |
|---|---|
| S3 호환성 | AWS S3 API 완전 호환 |
| 분산 스토리지 | Erasure Coding으로 데이터 보호 |
| 고가용성 | 4개 노드 분산 배치 |
| 웹 콘솔 | 브라우저 기반 관리 인터페이스 |
| 메트릭 | Prometheus 통합 모니터링 |
아키텍처
설치 및 구성
분산 모드 설정
# MinIO Helm Values - Distributed Mode
replicas: 4
drivesPerNode: 1
# 4개 노드 × 1개 드라이브 = 4개 드라이브 총합
# Erasure Coding: EC:2 (2개 패리티)
이미지 설정
image:
repository: quay.io/minio/minio
tag: RELEASE.2025-01-20T14-49-07Z
pullPolicy: IfNotPresent
부트스트랩 단계에서는 외부 레지스트리(quay.io)를 사용합니다. Zot 레지스트리가 아직 사용 불가능하기 때문입니다.
스토리지 설정
전용 스토리지 클래스
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: minio-local
provisioner: kubernetes.io/no-provisioner
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
PersistentVolume 구성
# 노드별 전용 PV (각 45Gi, /mnt/minio-data)
- name: minio-pv-worker1 # k3s-master (worker-1 디스크 이전)
nodeAffinity: k3s-master
- name: minio-pv-worker2 # k3s-worker-2
nodeAffinity: k3s-worker-2
- name: minio-pv-worker3 # k3s-worker-3
nodeAffinity: k3s-worker-3
- name: minio-pv-worker4 # k3s-worker-4
nodeAffinity: k3s-worker-4
디스크 할당:
| PV 이름 | 노드 | 계정 | 비고 |
|---|---|---|---|
minio-pv-worker1 | k3s-master | 0214 | 구 worker-1 디 스크 이전 (2026-04) |
minio-pv-worker2 | k3s-worker-2 | 0214 | |
minio-pv-worker3 | k3s-worker-3 | 0213 | |
minio-pv-worker4 | k3s-worker-4 | 0213 |
k3s-worker-1은 2026-04에 제거되었습니다. 해당 노드의 MinIO 디스크 데이터는 k3s-master의 /mnt/minio-data로 이전되었습니다.
Helm 차트 추가 설정
# MinIO Helm Values - Additional Configuration
enableServiceLinks: false # Kubernetes 서비스 링크 비활성화 (MINIO_SERVICE_PORT 충돌 방지)
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule # 마스터 노드 스케줄링 허용
priorityClassName: high-priority # 중요 스토리지 인프라를 위한 높은 우선순위
customCommandJob:
resources:
requests:
cpu: 10m
memory: 128Mi
limits:
memory: 128Mi # Kyverno 정책 준수를 위한 리소스 제한
보안 설정
자격 증명 관리
# Vault Static Secret을 통한 자격 증명 관리
existingSecret: minio-root-password
rootUserSecretKey: root-user
rootPasswordSecretKey: root-password
Vault 경로: infrastructure/minio
CORS 설정
environment:
MINIO_API_CORS_ALLOW_ORIGIN: "*"
브라우저에서 직접 파일 업로드를 위한 CORS 허용 설정입니다.
네트워킹
업로드 프록시 IngressRoute
MinIO Helm 차트의 표준 Ingress는 비활성화되어 있습니다(ingress.enabled: false, consoleIngress.enabled: false). 외부 노출은 Traefik 전용 IngressRoute CRD로만 이루어집니다.
# bootstrap/minio/manifests/upload-proxy-ingress.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: minio-upload-proxy
namespace: minio
spec:
entryPoints:
- websecure
routes:
- match: Host(`lumie-edu.com`) && PathPrefix(`/lumie/tmp/`) && (Method(`PUT`) || Method(`OPTIONS`))
kind: Rule
services:
- name: minio
port: 9000
- match: Host(`dev.lumie-infra.com`) && PathPrefix(`/lumie-dev/tmp/`) && (Method(`PUT`) || Method(`OPTIONS`))
kind: Rule
services:
- name: minio
port: 9000
tls: {}
특징:
- 표준
Ingress사용 안 함: Traefik 표준 Ingress는 메서드 필터 미들웨어를 지원하지 않아, 메서드 매칭이 가능한IngressRouteCRD를 사용 - 경로 제한:
prod→/lumie/tmp/,dev→/lumie-dev/tmp/(임시 업로드 경로만 노출) - 메서드 제한:
PUT(업로드)와OPTIONS(CORS preflight)만 허용; IngressRoute 라우터 규칙에서 직접 처리 - 인증: JWT 없음 — Presigned URL의 AWS Signature V4로 인증
- TLS:
tls: \{\}(빈 설정) — Traefik이 SNI를 통해 인증서 스토어에서 자동 선택
콘솔 UI
커스텀 콘솔 배포
components:
- name: minio-ui
replicaCount: 1
image:
repository: zot.lumie-infra.com/minio/console
tag: "v1.9.1"
containerPort: 9090
env:
- name: CONSOLE_MINIO_SERVER
value: "http://minio.minio.svc.cluster.local:9000"
접근 방법:
- 내부:
minio-ui.minio.svc.cluster.local:9090 - 외부: Teleport Web App 터널
Helm 차트의 기본 콘솔 대신 별도 배포를 사용하여 더 나은 제어와 보안을 제공합니다.
성능 최적화
CPU 최적화
environment:
# 복제 워커 수 제한 (CPU 사용량 감소)
MINIO_API_REPLICATION_MAX_WORKERS: "1"
MINIO_API_REPLICATION_MAX_LRG_WORKERS: "1"
MINIO_API_TRANSITION_WORKERS: "1"
MINIO_SCANNER_SPEED: "slowest"
# Go 런타임 CPU 매칭
GOMAXPROCS: "2"
리소스 할당
resources:
requests:
cpu: 15m
memory: 256Mi
limits:
memory: 422Mi
# CPU 제한 없음 (안정성 우선)
안티 어피니티
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- minio
topologyKey: kubernetes.io/hostname
각 MinIO Pod를 서로 다른 노드에 배치하여 고가용성을 보장합니다.
데이터 관리
버킷 구조
| 버킷 | 용도 | 보존 정책 |
|---|---|---|
lumie | 애플리케이션 파일 (시험지, OMR 이미지 등) | 영구 보존 (omr/tmp/ 제외) |
velero-backups | Kubernetes 리소스 + PVC 백업 (Velero) | 7일 (168h TTL) |
CloudNativePG WAL 아카이브와 베이스 백업은 MinIO가 아닌 Cloudflare R2(
s3://lumie-dr/cnpg/*)에 저장됩니다.
ILM (Information Lifecycle Management)
customCommands:
- command: ilm rule add myminio/lumie --prefix "omr/tmp/" --expire-days 1
자동 정리 규칙:
- 경로:
omr/tmp/(임시 OMR 이미지) - 보존 기간: 24시간
- 목적: 스토리지 공간 절약
백업 제외 설정
podAnnotations:
backup.velero.io/backup-volumes-excludes: export
MinIO 데이터 볼륨을 Velero 백업에서 제외합니다. 순환 백업(velero-backups 버킷 백업)을 방지하기 위함입니다.
모니터링
Prometheus 메트릭
metrics:
serviceMonitor:
enabled: true
includeNode: true
additionalLabels:
release: prometheus
interval: 30s
scrapeTimeout: 10s
주요 메트릭
| 메트릭 | 설명 |
|---|---|
minio_cluster_nodes_online_total | 온라인 노드 수 |
minio_cluster_drive_online_total | 온라인 드라이브 수 |
minio_bucket_usage_total_bytes | 버킷별 사용량 |
minio_s3_requests_total | S3 API 요청 수 |
minio_s3_errors_total | S3 API 오류 수 |
알림 규칙
# 예시 알림 규칙
- alert: MinIONodeDown
expr: minio_cluster_nodes_online_total < 4
for: 5m
labels:
severity: critical
annotations:
summary: "MinIO node is down"
description: "MinIO cluster has {{ $value }} nodes online, expected 4"