痛点
云厂商对象存储(S3、OSS)按量计费,当数据规模超过 50TB 且读写频繁时,月账单轻松突破万元。尤其在以下场景:
- AI 训练数据集:模型训练频繁读取大量文件,出流量费惊人
- 日志归档:ELK 冷数据外存,每月增量 5-10TB
- 私有化部署:合规要求数据不出境,不能用公有云存储
MinIO 是目前最成熟的开源 S3 兼容对象存储。它性能强悍(单集群可达 325 GiB/s 吞吐)、API 100% 兼容 S3,并且原生支持 Kubernetes Operator 部署。用自有硬件跑 MinIO,50TB 数据的月成本可从 S3 的 ¥8000+ 降到硬件折旧 ¥1500 左右。
方案
使用 MinIO Operator 在 Kubernetes 集群中部署分布式 MinIO,采用 Erasure Coding(纠删码)保证数据安全,通过 Ingress 暴露 S3 API,实现生产可用的私有对象存储。
架构要点:
- 4 节点 × 4 磁盘 = 16 块盘组成一个 Erasure Set
- 默认 EC:4 配置,允许同时丢失 4 块盘而不丢数据
- 通过 Kubernetes PV 使用本地 NVMe/SSD 磁盘
- MinIO Console 提供 Web 管理界面
实操步骤
第 1 步:安装 MinIO Operator
# 安装 MinIO Operator(需要 Kubernetes 1.25+)
kubectl krew install minio
# 初始化 Operator
kubectl minio init
# 验证 Operator 运行
kubectl get pods -n minio-operator
输出应看到 minio-operator 和 console Pod 均为 Running。
第 2 步:创建 Tenant(MinIO 集群实例)
准备 Tenant YAML,4 节点 × 4 盘配置:
# minio-tenant.yaml
apiVersion: minio.min.io/v2
kind: Tenant
metadata:
name: prod-storage
namespace: minio-tenant
spec:
image: quay.io/minio/minio:RELEASE.2026-06-01T00-00-00Z
pools:
- servers: 4
volumesPerServer: 4
volumeClaimTemplate:
spec:
storageClassName: local-nvme
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Ti
resources:
requests:
cpu: "2"
memory: 8Gi
limits:
cpu: "4"
memory: 16Gi
requestAutoCert: true
prometheusOperator: true
env:
- name: MINIO_STORAGE_CLASS_STANDARD
value: "EC:4"
kubectl create namespace minio-tenant
kubectl apply -f minio-tenant.yaml
# 等待所有 Pod 就绪(约 2-3 分钟)
kubectl get pods -n minio-tenant -w
第 3 步:配置 Ingress 暴露 S3 API
# minio-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minio-s3
namespace: minio-tenant
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-buffering: "off"
spec:
ingressClassName: nginx
tls:
- hosts:
- s3.internal.example.com
secretName: minio-tls
rules:
- host: s3.internal.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: minio
port:
number: 443
kubectl apply -f minio-ingress.yaml
# 验证连通性
aws s3 ls --endpoint-url https://s3.internal.example.com \
--access-key minioadmin --secret-key minioadmin
第 4 步:配置生命周期与监控
# 安装 mc 客户端
curl -O https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc && mv mc /usr/local/bin/
# 添加别名
mc alias set prod https://s3.internal.example.com minioadmin minioadmin
# 创建 bucket 并设置生命周期(90 天后转到低频层)
mc mb prod/logs-archive
mc ilm rule add prod/logs-archive \
--transition-days 90 \
--storage-class WARM
# 设置配额防止写爆
mc quota set prod/logs-archive --size 20TB
Prometheus 监控已在 Tenant 中通过 prometheusOperator: true 启用,关键指标:
# 磁盘使用率告警
minio_cluster_disk_free_bytes / minio_cluster_disk_total_bytes < 0.15
# 请求延迟 P99
histogram_quantile(0.99, rate(minio_s3_requests_duration_seconds_bucket[5m]))
# 离线磁盘数(>0 需立即处理)
minio_cluster_disk_offline_total > 0
避坑
坑 1:磁盘数量不能随意扩
MinIO 的 Erasure Set 在创建时固定。已有 Pool 不能加盘,只能新增 Pool(Server Pool Expansion)。所以初始规划时预留足够容量,建议单 Pool 至少预留 30% 空间。
坑 2:不要用网络存储(NFS/Ceph RBD)做后端
MinIO 对磁盘 IOPS 和延迟敏感。用 NFS 做 PV 会导致: - 小文件 PUT 延迟飙升 10 倍 - Erasure Coding 校验超时导致写入失败
务必用 Local PV + 本地 NVMe/SSD。如果用云盘,至少选 io2 或 gp3 with 高 IOPS。
坑 3:TLS 证书过期导致集群不可用
MinIO 开启 requestAutoCert: true 后使用自签证书,默认有效期 2 年。证书过期后整个集群无法通信。建议:
# 定期检查证书有效期
kubectl get secret -n minio-tenant | grep tls
openssl x509 -in /tmp/cert.pem -noout -enddate
# 或者直接使用 cert-manager 管理证书自动续期
总结
MinIO 是自建对象存储的首选方案。核心建议:
- 规划先行:预估 1-2 年数据增量再定磁盘规格,扩容只能加 Pool
- 本地盘 + Erasure Coding:性能和可靠性的最优组合
- 监控必配:磁盘离线、空间不足、请求延迟三板斧
- 成本对比:50TB 以上数据量,自建 MinIO 相比云 S3 通常节省 60-80%
对于已有 Kubernetes 集群的团队,通过 Operator 部署 MinIO 的运维成本很低,S3 兼容 API 意味着现有代码零改动迁移。