饮墨

子安饮墨馀三斗,留与卿儿作赋来

MinIO 自建对象存储实战:4 步在 Kubernetes 上部署生产级 S3 兼容存储

痛点

云厂商对象存储(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-operatorconsole 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. 规划先行:预估 1-2 年数据增量再定磁盘规格,扩容只能加 Pool
  2. 本地盘 + Erasure Coding:性能和可靠性的最优组合
  3. 监控必配:磁盘离线、空间不足、请求延迟三板斧
  4. 成本对比:50TB 以上数据量,自建 MinIO 相比云 S3 通常节省 60-80%

对于已有 Kubernetes 集群的团队,通过 Operator 部署 MinIO 的运维成本很低,S3 兼容 API 意味着现有代码零改动迁移。

您还没有登录,请登录后发表评论。