# MinIO 기준 ## 목적 이 문서는 Kubernetes 환경에서 MinIO를 1000+ 서비스의 S3 호환 object storage로 운영하기 위한 기준을 고정한다. - MinIO Operator + **Tenant CRD** (`minio.min.io/v2`)를 기본 배포 모델로 둔다 - Erasure coding 최소 요건 (`servers × volumesPerServer ≥ 4`)을 명시한다 - KES sidecar + Vault transit backend로 SSE-KMS를 구성한다 - STS + OIDC (Keycloak)로 서비스 인증을 수행한다 - 버전 관리 / object lock / replication / lifecycle rule을 운영 필수 요소로 둔다 ## 공식 의미 (MinIO Operator + Tenant CRD 기준) - MinIO Operator는 `minio.min.io/v2` API group의 **Tenant** CR을 watch하여 StatefulSet, Service, PVC, 인증서를 자동 생성한다. - Tenant는 **namespace당 1개**를 권장한다 (namespace = 소유/정책/쿼터 경계). - MinIO는 erasure coding을 사용한다. **`servers × volumesPerServer`는 최소 4이어야** 기동한다. EC:N parity (기본 EC:4 ~ EC:8)는 parity drive 수를 결정하며, 장애 허용 drive 수 = parity 수. - MinIO pool은 불변이다(immutable). pool 내 servers / volumesPerServer는 Tenant 생성 후 변경 불가. 용량 확장은 **새 pool 추가**로 수행. - **Health endpoints**: - `/minio/health/live` — 프로세스 liveness (인증 없음) - `/minio/health/cluster` — **write quorum** 기준 (rolling update 중 false 가능, readiness 비권장) - `/minio/health/cluster/read` — **read quorum** 기준 (rolling update 허용, readiness 권장) - **Metrics endpoints**: - `/minio/v2/metrics/cluster` — cluster-wide (기본 Bearer token 필요) - `/minio/v2/metrics/node` — per-node - `/minio/v2/metrics/bucket/api/` — bucket API metrics - `mc admin prometheus generate` 로 scrape config + token 생성. 또는 `prometheusAuthType: public` 설정으로 unauth scrape 허용. - **KES** (Key Encryption Service)는 별도 sidecar/Deployment로 Vault transit backend와 통신해 SSE-KMS / SSE-S3 per-object key를 발급한다. - MinIO **service account**는 root access key의 하위 derived credential이다(IAM role 개념 아님). 앱은 service account만 사용하고 root는 bootstrap 전용. - **Object lock**은 bucket 생성 시점에 활성화해야 하며, `GOVERNANCE` (bypass 권한자 우회 가능) vs `COMPLIANCE` (root도 우회 불가) 두 모드. - **Site replication**은 최대 16개 MinIO 클러스터를 동기화한다 (IAM, bucket config, object 전체). **Bucket replication**은 특정 bucket만 대상. - Console은 9090 port, API는 9000 port. ## 기본 규칙 ### 1. 배포는 MinIO Operator + Tenant CR 기본: - `kubectl apply -k "https://github.com/minio/operator?ref=v6.0.4"` 또는 Helm `minio-operator` + `tenant` chart - Tenant CR로 pool, credential, TLS, KES, logging, monitoring 선언 - 수제 StatefulSet 운영 금지 ### 2. Tenant는 namespace당 1개 기본: - `minio-prod` namespace에 Tenant 1개 - 테넌트 간 격리가 필요하면 namespace를 복수 생성 - 동일 namespace에 다른 워크로드와 공존 금지 ### 3. Erasure coding 요건: `servers × volumesPerServer ≥ 4` 기본 topology 후보: | servers | volumesPerServer | 총 drive | 기본 EC parity | 장애 허용 drive | |---------|------------------|----------|----------------|-----------------| | 4 | 4 | 16 | EC:4 | 4 | | 4 | 8 | 32 | EC:4 | 4 | | 8 | 4 | 32 | EC:4 | 4 | | 8 | 8 | 64 | EC:4 ~ EC:8 | 4 ~ 8 | 기본: - 최소 `4 × 4 = 16` drive 시작 (prod) - `MINIO_STORAGE_CLASS_STANDARD=EC:4` 이상, critical data는 `EC:8` - parity 증가 = 용량 감소 + 신뢰성 증가 기본 금지: - `servers × volumesPerServer < 4` → Tenant가 기동 실패 ### 4. Pool은 immutable — 확장은 새 pool 추가 기본: - 초기 pool의 `servers`, `volumesPerServer`, `volumeClaimTemplate.size`는 평생 고정 - 용량 부족 시 `spec.pools[]`에 `pool-1`, `pool-2` 추가 - pool 간 데이터 rebalance는 `mc admin rebalance start` ### 5. StorageClass 명시 (local-path 금지) 기본: - prod: `volumeClaimTemplate.spec.storageClassName: ceph-rbd-retain` / `ebs-gp3` / `local-volume-xfs` (명시적) - 파일시스템은 `xfs` 권장 (MinIO는 ext4보다 xfs에 최적화) - `reclaimPolicy: Retain` + PVC 삭제 가드 (Tenant 삭제 시 데이터 소실 방어) 기본 금지: - k3s local-path prod 사용 - default StorageClass fallback ### 6. Credential: root는 bootstrap 전용, 앱은 service account 기본: - `spec.configuration.name`에 root credential Secret (MINIO_ROOT_USER, MINIO_ROOT_PASSWORD) - Vault KV에 root credential 저장, VSO로 Secret 동기화 - 앱용 access는 `mc admin accesskey create`로 서버 생성 credential을 발급하고 inline policy로 권한을 축소한다 - 생성 결과의 secret key는 한 번만 수신해 stdin으로 Vault에 기록하며, `--secret-key` 또는 `mc admin user add`로 secret을 argv에 전달하지 않는다 - service account는 최소 권한 policy 바인딩 ### 7. TLS는 기본 활성화 기본: - `spec.requestAutoCert: true` → Operator가 Kubernetes CSR로 인증서 자동 발급 (MinIO 자체 CA) - 사내 PKI 사용 시 `spec.externalCertSecret` + cert-manager Certificate - API (9000), Console (9090), KES 전부 TLS ### 8. KES + Vault transit으로 SSE-KMS 기본: - `spec.kes` 필드에 KES 사이드카 spec - KES는 Vault transit engine을 key store로 사용 - bucket 생성 시 `mc encrypt set sse-kms minio-backup/critical key-id=my-app-key` - per-object DEK를 KES에서 받아 암호화 기본 금지: - KES 없이 SSE-S3만 사용 (master key가 MinIO 내부에만 존재 → 분실 위험) - KES가 local filesystem key store 사용 (prod) ### 9. Versioning + Object Lock은 critical bucket 기본값 기본: - 금융/감사 데이터: `mc version enable` + Object Lock `COMPLIANCE` 모드 - 백업 bucket: Object Lock `GOVERNANCE` + retention 30일 - 일반 app bucket: versioning만 (실수 복구) - lifecycle rule로 오래된 버전 자동 정리 (`mc ilm add --expire-noncurrent-days 90`) ### 10. Replication: site vs bucket 기본: - 전체 IAM/config 동기화 필요: **site replication** (`mc admin replicate add`) - 특정 bucket만 cross-region 복제: **bucket replication** (`mc replicate add`) - async replication 특성 인지 (RPO > 0) - `mc mirror`는 DR 전략 아님 — 일회성 migration/sync 용도 ### 11. STS + OIDC (Keycloak) 통합 기본: - Keycloak에 `minio` client 생성 (confidential) - MinIO 설정: ``` mc admin config set ALIAS identity_openid \ config_url="https://auth.example.com/realms/platform/.well-known/openid-configuration" \ client_id="minio" \ client_secret="..." \ claim_name="policy" \ scopes="openid,profile,email" ``` - 앱은 `AssumeRoleWithWebIdentity`로 JWT → 임시 STS credential 교환 - MinIO policy에 JWT `policy` claim으로 매핑 ### 12. Health probe: read quorum을 readiness로 기본: - `livenessProbe`: `/minio/health/live` (프로세스 생존) - `readinessProbe`: `/minio/health/cluster/read` (read quorum) — rolling update 허용 - `startupProbe`: `/minio/health/live` + `failureThreshold` 넉넉하게 기본 금지: - `readinessProbe`로 `/minio/health/cluster` (write quorum) 사용 → rolling update 시 전체 pod unready ### 13. Metrics: 내부 scrape 전용 기본: - `spec.prometheus` 또는 `prometheusAuthType: public` (내부 network만) - 또는 `mc admin prometheus generate` 로 scrape token 발급 후 `bearerTokenSecret` - ServiceMonitor는 `/minio/v2/metrics/cluster` 대상 - 외부 Ingress 공개 금지 ### 14. API Ingress — Console은 내부 전용 기본: - API (9000): 필요한 경우 Ingress로 공개 (S3 API host: `s3.example.com`) - Console (9090): 내부/운영자 전용, 외부 공개 금지 (별도 host + IP whitelist + OIDC forward-auth) - Console을 공개하면 root credential UI 로그인 표면 확장 ### 15. Lifecycle rule로 용량 관리 기본: - 로그 bucket: 30~90일 expire - tmp / cache bucket: 7일 expire - versioning enabled bucket: noncurrent version 90일 expire - incomplete multipart upload: 7일 abort (`mc ilm add --expire-incomplete-upload-days 7`) ### 16. 로깅 기본: - `spec.log.audit` → bucket에 audit log 저장 또는 webhook으로 외부 전송 - stdout으로 console log → fluent-bit / Loki 수집 - audit log는 Object Lock bucket에 저장해 변조 방지 ### 17. SecurityContext + Resource 기본: - `spec.securityContext`: `runAsNonRoot: true`, `runAsUser: 1000`, `fsGroup: 1000`, `runAsGroup: 1000` - Restricted PSS 준수 - 단일 pod resource (4 server cluster 기준): - requests: `cpu: 500m`, `memory: 2Gi` - limits: `cpu: 4`, `memory: 8Gi` - 데이터 규모/동시 요청 수에 따라 조정 ### 18. Anti-affinity + topologySpread 기본: - `podAntiAffinity`: hostname 기준 required (같은 node에 MinIO pod 복수 금지) - `topologySpreadConstraints`: zone 분산 - EC:4 + 4-zone = 1 zone 장애 허용 ### 19. Console은 분리, auth는 OIDC 기본: - Console endpoint에 `MINIO_IDENTITY_OPENID_*` OIDC 설정 - root credential UI 로그인은 break-glass 전용 - 일반 운영자는 OIDC 로그인 + group → policy 매핑 ### 20. 현재 스택 기본 권장안 - 배포: MinIO Operator + Tenant CR (`minio.min.io/v2`) - Topology: 최소 `4 × 4 = 16` drive, prod는 `8 × 4 = 32` 이상 - EC: `EC:4` 기본, critical data `EC:8` - StorageClass: 명시적 (xfs, Retain) - TLS: `requestAutoCert: true` - KMS: KES sidecar + Vault transit - 인증: root는 VSO 주입, 앱은 service account, 사용자는 Keycloak OIDC - Health: live / cluster-read (readiness) - Metrics: Prometheus bearer-token scrape - Versioning + Object Lock: critical bucket 기본값 - Replication: site (전체) / bucket (부분) 구분 - Console: 내부 전용 ## 프로젝트 기준 요약 - MinIO Operator + Tenant CR 기본 배포 - namespace당 Tenant 1개 - `servers × volumesPerServer ≥ 4` erasure coding 요건 - Pool immutable — 확장은 새 pool - StorageClass 명시 + xfs 권장 + Retain - KES + Vault transit으로 SSE-KMS - Root credential은 Vault → VSO → Secret 경로 - 앱 접근은 service account, 사용자는 Keycloak OIDC STS - Health: `/minio/health/live` + `/minio/health/cluster/read` - Metrics: Bearer token scrape - Console 외부 비공개, API만 필요 시 Ingress - Versioning + Object Lock + Lifecycle rule로 데이터 보호 - site/bucket replication으로 DR (`mc mirror`는 DR 아님)