当你的业务已经全面拥抱 Kubernetes,存储层却还在裸机上手工维护,这本身就是一种架构割裂。MinIO 作为云原生时代对象存储的代表,对 K8s 有着近乎原生的支持——它本身就被设计为在容器化环境中运行。
这篇文章,我们不谈概念,只讲实操:如何在你的 K8s 集群里,用 Helm 一键部署一套高可用的 MinIO 分布式集群。整个过程大约 20 分钟,读完后你可以立即在环境里复现。
前置准备
开始之前,请确保你的环境满足以下条件:
| Kubernetes 集群 | 1.20+,至少 3 个 Worker 节点 |
| Helm | 3.8+ |
| StorageClass | 集群内已配置可用的 SC(如 NFS、Ceph RBD、云盘等) |
| 内存 | 每个 Worker 节点建议 8GB+ |
| 磁盘 | Worker 节点挂载 SSD 数据盘(用于 PV) |
关于 StorageClass 的特别提醒:MinIO 在 K8s 中运行需要持久化存储。如果你使用云厂商托管 K8s(如阿里云 ACK、腾讯云 TKE、AWS EKS),通常默认就带有云盘 StorageClass。如果是自建集群,请提前部署好 NFS、Ceph 或 OpenEBS 等存储方案。
验证你的 StorageClass:
kubectl get sc
如果输出中有 (default) 标记的 StorageClass,说明存储就绪。
方案选择:Operator vs Helm Chart
MinIO 在 K8s 生态中提供两种部署方式:
| 定位 | 企业级全功能管理平台 | 轻量级快速部署 |
| 功能 | 支持多租户、TLS自动配置、监控集成、升级管理 | 仅部署 MinIO 服务 |
| 复杂度 | 高,需要学习 Operator 概念 | 低,一条命令安装 |
| 适用场景 | 大规模生产环境、多团队共享 | 中小型集群、快速验证、DevOps 场景 |
本文选择 Helm Chart 方案,原因是:
第一步:添加 MinIO Helm 仓库
# 添加官方仓库
helm repo add minio https://charts.min.io/
# 更新索引
helm repo update
# 查看可用的 Chart 版本
helm search repo minio/minio –versions | head -5
你会看到类似输出:
NAME CHART VERSIONAPP VERSIONDESCRIPTION
minio/minio 5.2.0 RELEASE.2024-… Multi-Cloud Object Storage
版本选择建议:生产环境不要追最新版,选择一个已发布 1~2 个月的稳定版本。本文以 5.2.0 为例。
第二步:定制 values.yaml
Helm Chart 的强大之处在于可配置。MinIO 官方 Chart 有上百个参数,但我们只需要关注生产环境最核心的那些。
创建一个 minio-values.yaml:
# ========================================
# 基础配置
# ========================================
# 集群模式:true = 分布式,false = 单机
mode: distributed
# 分布式模式的节点数(必须是 4 的倍数,推荐 4)
replicas: 4
# 每个节点的磁盘数(总磁盘数 = replicas × drivesPerNode)
drivesPerNode: 1
# Root 凭证(生产环境请务必修改!)
rootUser: "minioadmin"
rootPassword: "minioadmin"
# ========================================
# 持久化存储配置
# ========================================
persistence:
enabled: true
storageClass: "" # 留空则使用集群 default SC;也可指定如 "nfs-client"
accessMode: ReadWriteOnce
size: 100Gi # 每个节点的存储配额
# ========================================
# 服务暴露方式
# ========================================
service:
type: ClusterIP # 集群内访问,配合 Ingress 暴露
port: 9000
consoleService:
type: ClusterIP
port: 9001
# Ingress 配置(推荐生产环境使用)
ingress:
enabled: true
ingressClassName: nginx # 根据你的 Ingress Controller 调整
hostname: minio–api.yourdomain.com
path: /
pathType: Prefix
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-read-timeout: "900"
nginx.ingress.kubernetes.io/proxy-send-timeout: "900"
# Console 的独立 Ingress
consoleIngress:
enabled: true
ingressClassName: nginx
hostname: minio–console.yourdomain.com
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
# ========================================
# 资源限制(生产环境必须配置)
# ========================================
resources:
requests:
memory: "4Gi"
cpu: "2000m"
limits:
memory: "8Gi"
cpu: "4000m"
# ========================================
# 节点调度策略
# ========================================
# 反亲和性:确保每个 Pod 分布在不同节点,避免单节点故障导致数据丢失
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
– labelSelector:
matchLabels:
app: minio
topologyKey: kubernetes.io/hostname
# 容忍与污点(可选,如果 Worker 节点打了专用污点)
tolerations: []
# ========================================
# 监控与日志
# ========================================
# 启用 Prometheus 监控指标
metrics:
enabled: true
serviceMonitor:
enabled: true
namespace: monitoring
# 启用 Pod 安全上下文
securityContext:
enabled: true
runAsUser: 1000
runAsGroup: 1000
# 启用 TLS(推荐生产环境)
tls:
enabled: false
certSecret: ""
publicCrt: ""
privateKey: ""
关键参数解读:
mode: distributed + replicas: 4:开启分布式模式,4 个 Pod 组成一个高可用集群。为什么是 4?因为这是 MinIO 纠删码(EC:2)的最小规模。
persistence.storageClass:留空表示使用集群默认的 StorageClass。如果你有多个存储后端(如 SSD 和 SATA),建议显式指定性能更好的那个。
podAntiAffinity:这是生产环境的硬性要求。它确保 4 个 MinIO Pod 分布在不同的 Worker 节点上。如果某台物理机宕机,只会影响 1 个 Pod,集群仍然可用。
resources:MinIO 对内存和 CPU 有一定要求,尤其是纠删码编解码会消耗计算资源。给每个 Pod 预留 4GB 内存和 2 核 CPU 是比较稳妥的起步配置。
第三步:部署 MinIO
配置文件准备就绪后,一条命令完成部署:
# 创建命名空间(推荐隔离部署)
kubectl create namespace minio-system
# Helm 安装
helm install minio minio/minio \\
–namespace minio-system \\
–version 5.2.0 \\
-f minio-values.yaml \\
–wait \\
–timeout 600s
参数说明:
- –wait:等待所有 Pod 就绪后才返回,便于脚本化部署
- –timeout 600s:分布式模式初始化可能需要几分钟,给足时间
当看到以下输出时,说明安装成功:
NAME: minio
LAST DEPLOYED: Mon Jan 15 09:30:00 2026
NAMESPACE: minio-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the MinIO URL by running these commands:
…
第四步:验证集群状态
4.1 查看 Pod 分布
kubectl get pods -n minio-system -o wide
理想状态应该是 4 个 Pod,每个都 Running,并且分布在不同的节点上:
NAME READY STATUS RESTARTS AGE IP NODE
minio-0 1/1 Running 0 2m 10.244.1.10 k8s-node-01
minio-1 1/1 Running 0 2m 10.244.2.15 k8s-node-02
minio-2 1/1 Running 0 2m 10.244.3.20 k8s-node-03
minio-3 1/1 Running 0 2m 10.244.4.25 k8s-node-04
4.2 查看 PVC 绑定
kubectl get pvc -n minio-system
每个 Pod 会对应一个 PVC,状态应为 Bound:
NAME STATUS VOLUME CAPACITY
data-minio-0 Bound pvc-abc123-… 100Gi
data-minio-1 Bound pvc-def456-… 100Gi
data-minio-2 Bound pvc-ghi789-… 100Gi
data-minio-3 Bound pvc-jkl012-… 100Gi
4.3 查看持久化卷详情
kubectl get pv | grep minio
确认每个 PV 的容量、访问模式和回收策略都符合预期。
第五步:访问 MinIO
5.1 方式一:通过 Ingress(生产环境推荐)
如果你配置了 Ingress,直接通过域名访问:
- API 端点:http://minio-api.yourdomain.com
- Console 控制台:http://minio-console.yourdomain.com
用 values.yaml 中配置的 rootUser 和 rootPassword 登录。
5.2 方式二:通过 kubectl port-forward(本地调试)
# 端口转发 API
kubectl port-forward svc/minio 9000:9000 -n minio-system &
# 端口转发 Console
kubectl port-forward svc/minio-console 9001:9001 -n minio-system &
然后本地访问 http://localhost:9001。
5.3 方式三:通过 NodePort(无 Ingress 环境)
修改 values.yaml 中的 service.type 为 NodePort,重新执行 helm upgrade:
helm upgrade minio minio/minio \\
–namespace minio-system \\
–set service.type=NodePort \\
–set consoleService.type=NodePort
查看分配的 NodePort:
kubectl get svc -n minio-system
第六步:使用 mc 连接 K8s 中的 MinIO
在 K8s 内运行 MinIO 只是第一步,你的业务应用还需要连接它。在集群外的一台机器上配置 mc:
# 下载 mc 客户端
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
mv mc /usr/local/bin/
# 添加 K8s MinIO 别名
mc alias set k8s-minio http://minio-api.yourdomain.com minioadmin minioadmin
# 查看集群信息
mc admin info k8s-minio
# 创建 bucket
mc mb k8s-minio/mybucket
# 上传测试文件
mc cp ./test.txt k8s-minio/mybucket/
# 验证文件
mc ls k8s-minio/mybucket/
如果一切正常,你会看到 Network 和 Drives 都显示 4/4 OK,说明分布式集群健康运行。
第七步:生产环境必做的 3 件事
7.1 修改默认密码
在 values.yaml 中修改 rootPassword,然后执行:
helm upgrade minio minio/minio \\
–namespace minio-system \\
-f minio-values.yaml
注意:Helm upgrade 会触发 RollingUpdate,MinIO Pod 会逐个重启,但服务不会中断(因为有 4 个节点,可以同时容忍 2 个节点离线)。
7.2 启用 TLS
生产环境必须启用 HTTPS。推荐方案是:Ingress 层终止 TLS,MinIO 本身跑 HTTP。
如果你已经配置了 cert-manager,只需修改 Ingress 注解:
ingress:
enabled: true
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod" # 或你的 CA Issuer
nginx.ingress.kubernetes.io/ssl-redirect: "true"
tls:
– secretName: minio–api–tls
hosts:
– minio–api.yourdomain.com
重新 apply 后,cert-manager 会自动签发并挂载证书。
7.3 配置监控告警
values.yaml 中已经启用了 metrics.enabled: true 和 serviceMonitor.enabled: true。接下来在 Prometheus 中导入 MinIO Dashboard(Grafana ID: 13502),并配置以下告警规则:
groups:
– name: minio–alerts
rules:
– alert: MinioNodeOffline
expr: minio_cluster_nodes_offline_total > 0
for: 2m
annotations:
summary: "MinIO 节点离线"
– alert: MinioDiskOffline
expr: minio_cluster_drive_offline_total > 0
for: 1m
annotations:
summary: "MinIO 磁盘离线"
– alert: MinioHighDiskUsage
expr: (minio_cluster_capacity_usable_free_bytes / minio_cluster_capacity_usable_total_bytes) < 0.2
for: 5m
annotations:
summary: "MinIO 可用空间不足 20%"
常见问题与排查
Q1:Pod 一直处于 Pending 状态
kubectl describe pod minio-0 -n minio-system
最常见的原因:
- PVC 无法绑定 → 检查 StorageClass 和底层存储 provisioner 是否正常
- 资源不足 → 检查节点是否有足够的 CPU/内存
- 节点亲和性冲突 → 如果配置了 podAntiAffinity,确保有足够的节点(至少 replicas 数量)
Q2:Helm 安装超时
分布式 MinIO 初始化时需要格式化磁盘和建立纠删码组,这个过程在慢速存储上可能需要 5~10 分钟。增加 timeout:
helm install ... –timeout 1200s
Q3:mc 连接报 “Server not initialized, please try again”
说明集群还在初始化中,等 2~3 分钟后重试。如果持续报错,检查 Pod 日志:
kubectl logs minio-0 -n minio-system
Q4:如何扩容?
Helm Chart 的分布式模式不支持在线扩容 replicas。如果需要扩容,必须:
注意:这会导致服务中断。生产环境建议使用 MinIO Operator,它支持 Server Pool 在线扩容。
总结
通过这篇文章,我们在 Kubernetes 集群中完成了以下工作:
MinIO 在 K8s 上的部署,核心优势在于基础设施即代码(IaC):整个存储集群的配置都收敛在一个 values.yaml 中,版本管理、回滚、重建都变得极其简单。当你的应用已经容器化,存储层没有理由还停留在手工运维时代。
如果你在部署过程中遇到问题,欢迎在评论区交流。

