Files
project-infra/docs/standards/infra/minio.md
T

242 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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>` — 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 아님)