跳到主要内容

部署与高可用

从单机到分布式​

单机版跑通之后,生产要考虑的事情立刻变成三件:容量不够了怎么办、一块盘坏了数据还在不在、一台机器挂了服务还能不能用。MinIO 的答案是同一个:分布式模式。

分布式模式和单机模式的差别,不是「多起几个进程」,而是:

  • 所有节点共用同一个对象命名空间,客户端连任意节点都能访问全部数据;
  • 每个对象被切成纠删码分片,分散在多个节点上,节点故障时靠其他节点的分片重建;
  • 集群状态通过节点间通信维护,没有中心元数据节点,也就不存在元数据单点。

拓扑规划​

最小可用形态​

官方推荐、也是最常见的起点是 4 节点 × 4 盘 = 16 块盘,正好组成一个 16 盘的纠删码集合,默认 EC:4:

部署规模拓扑纠删码集合可用容量比可容忍故障
开发验证1 节点 4 盘4 盘 1 集合50%2 块盘
最小生产4 节点 4 盘16 盘 1 集合75%4 块盘 / 1 个节点
中等规模8 节点 4 盘2 个 16 盘集合75%每集合 4 块盘
大规模16 节点 8 盘8 个 16 盘集合75%每集合 4 块盘

注意最后两行的差别:集合是独立的,一个集合坏 4 块盘只影响这个集合里的对象,其他集合照常工作;但单个集合丢超过 4 块盘,这部分数据就永久丢失了。

硬性约束​

规划阶段有几条不能违背的规则,违反了下场都很惨:

  • 至少 4 块盘才能启用纠删码;少于 4 块只能用单机单盘模式,没有冗余。
  • 节点数、每节点盘数尽量取偶数,集合划分更规整,扩容时也好算。
  • 同一池内的盘要同类型、同容量:MinIO 会把每块盘的可用容量限制为池内最小盘,混插一块小盘等于全体缩水。
  • 不要用 RAID:MinIO 自己就是冗余层,RAID 会隐藏磁盘故障,还会让纠删码分片分布失真。盘要直通(JBOD/HBA 直通模式)。
  • 不要用 NAS/SAN/NFS:网络存储的延迟和一致性保证撑不住纠删码的读写仲裁。
  • 文件系统用 XFS,挂载点连续编号(/mnt/disk1 到 /mnt/disk4)。
磁盘独占

MinIO 要求对磁盘有独占访问权。不要在数据盘上放别的东西,更不要写脚本去移动、修改、删除盘上的分片文件或 xl.meta 元数据——这些操作会绕过 MinIO 的校验,直接造成不可恢复的损坏。迁移数据只能用 mc mirror 这类 S3 层面的工具。

容量怎么算​

原始容量乘上纠删码效率,再打一个安全余量:

可用容量 = 节点数 × 每节点盘数 × 单盘容量 × (K / N)
= 4 × 4 × 4TiB × (12 / 16) = 48TiB

再留 30% 余量应对突发增长和后台扫描,实际可写入量大约 33TiB。MinIO 官方建议一次性规划至少两年的容量,并在使用率达到 70% 之前完成扩容准备——频繁小步扩容通常说明规划没做好。

分布式部署​

前置准备​

每台节点都要做:

# 主机名和 hosts 解析(没有内部 DNS 时手工写)
# 192.168.10.11 minio1.example.net
# 192.168.10.12 minio2.example.net
# 192.168.10.13 minio3.example.net
# 192.168.10.14 minio4.example.net
sudo hostnamectl set-hostname minio1.example.net

# 时间同步、XFS 数据盘、独立服务账号,和单机部署完全一样
sudo systemctl enable --now chrony
sudo mkfs.xfs -f /dev/vdb
sudo mkdir -p /mnt/disk1 && sudo mount /dev/vdb /mnt/disk1

四台机器之间必须双向网络可达,防火墙放通 9000 端口(节点间通信也走这个端口)。所有节点必须使用相同的监听端口,这是硬性要求。

环境变量文件​

每个节点的 /etc/default/minio 内容完全一致,区别只在数据盘路径(如果各节点盘符相同则连路径也一样):

# /etc/default/minio(四个节点内容一致)
MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=ChangeMe-Str0ng-Pass

# 扩展写法:minio1 到 minio4,每台 4 块盘
MINIO_VOLUMES="https://minio{1...4}.example.net:9000/mnt/disk{1...4}/minio"

MINIO_OPTS="--console-address :9001"

https 表示启用 TLS,证书配好后才能用;先用 http 验证通了再换 https 也可以。

启动​

四个节点要几乎同时启动,不要滚动启动:

# 在每台机器上执行(或用 ansible/pssh 并发执行)
sudo systemctl daemon-reload
sudo systemctl enable minio
sudo systemctl start minio
禁止滚动重启

MinIO 的写操作需要跨节点仲裁,滚动重启(一台一台来)会让集群反复进出「降级」状态,极端情况下触发写拒绝。升级、改配置、扩容,都应该所有节点同时重启。MinIO 的读写是原子的,同时重启不会丢数据。

验证:

mc alias set cluster https://minio1.example.net:9000 admin 'ChangeMe-Str0ng-Pass'
mc admin info cluster

输出里确认:Servers 是 4 个且全部 online,Drives 是 16 块且全部 online,Usage 和 Capacity 有正常数值。管理命令连任意一个节点都可以。

数据路由与一致性哈希​

理解数据怎么分布,才能理解扩容和故障时的行为。

MinIO 对每个对象的完整命名空间(BUCKET/PREFIX/OBJECT,含版本)算一个确定性的哈希,据此选定服务器池,再选定池内的纠删码集合。这就是「一致性哈希」的思路:同一个对象永远映射到同一个位置,不需要中心元数据表去记录「它在哪」。

多池部署时,写入还会按各池的空闲空间比例加权——空闲多的池分到更多新对象。对象落在哪个池,写完之后就记在对象的元数据里,后续读请求以元数据为准,不会因为池的权重变了就找不到数据。

这带来几个直接结论:

  • 任意节点都能处理任意请求:客户端连谁都可以,节点内部会转发到正确的集合,所以负载均衡器不需要做「一致性哈希」,普通的 least_connections 就够。
  • 没有元数据热点:不存在「元数据服务器」这个性能和故障瓶颈。
  • 扩容只影响新写入的路由:新加的池只承接新数据,已经写下的对象还在老池里,除非手动重平衡。
  • 单个池整体掉线会影响全集群:MinIO 无法判断请求原本该去哪个池,会暂停整个部署的 I/O——这是多池部署最需要注意的风险点。

TLS 证书配置​

MinIO 检测到证书目录里有合法的 public.crt 和 private.key 就自动启用 TLS 1.2+,不需要改任何配置。

证书目录按进程用户的 home 走:

# systemd 以 minio-user 运行,所以是这个路径
sudo mkdir -p /home/minio-user/.minio/certs/CAs
sudo cp fullchain.crt /home/minio-user/.minio/certs/public.crt
sudo cp privkey.key /home/minio-user/.minio/certs/private.key
sudo chown -R minio-user:minio-user /home/minio-user/.minio
sudo chmod 600 /home/minio-user/.minio/certs/private.key
sudo systemctl restart minio

也可以用 --certs-dir 指定别的目录,把这个参数加到 MINIO_OPTS 里即可。

几个关键点:

  • 证书 SAN 必须包含客户端实际访问的域名,用 IP 访问就要把 IP 写进 SAN,否则客户端报证书不匹配。
  • 内部 CA 或自签证书必须分发 CA:把 CA 证书放到所有节点的 certs/CAs/ 下,MinIO 只信任这里的 CA。集群内部节点互访也走 TLS,缺一个节点的 CA 就会导致节点间通信失败。
  • 客户端也要信任 CA:mc 会把 CA 证书装在系统信任链里;临时测试可以加 --insecure,生产别这么干。
  • 多域名用 SNI:想同时用 s3.example.net 和 s3-internal.example.net 访问,就把两个证书分别放到 certs/s3.example.net/ 这样的子目录里。
  • 换证书要重启:MinIO 不会热加载证书,续期后必须重启服务,记得把自动续期的 hook 配上。

扩容:加池,不是加盘​

这是 MinIO 最容易被误解的地方:分布式模式不能给已有的池加盘。扩容的唯一方式是新增一个服务器池,然后把所有节点的启动参数改成包含新旧两个池。

# 原有一个 4 节点池,新增一个 4 节点池,空格分隔两个池
MINIO_VOLUMES="https://minio{1...4}.example.net:9000/mnt/disk{1...4}/minio https://minio{5...8}.example.net:9000/mnt/disk{1...4}/minio"

新池的准入条件:

  • 每个池至少提供 2 × EC:N 块盘。默认 EC:4 就是至少 8 块盘,4 节点 × 2 盘也能满足,但更推荐 4 节点 × 4 盘保持拓扑一致。
  • 所有节点使用相同端口,主机名连续编号,用扩展写法。
  • 加完必须所有节点同时重启,改完配置直接 systemctl restart minio 全量执行。

扩容之后的行为:

  • 老数据不会自动迁移。新写入按各池的「空闲空间占比」分配:A 池空 3TiB、B 池空 5TiB,那新对象落到 B 池的概率就是 62.5%。
  • 需要让老数据也分布过去,用 mc admin rebalance start 手动触发重平衡,mc admin rebalance status 看进度。重平衡很吃 I/O,挑业务低峰期做。
  • 想退役旧池用 mc admin decommission start,它会先把数据迁走再下线池。
扩容解决容量,不解决容灾

加池只增加容量和吞吐,不提供跨站点容灾。而且只要有一个池整体不可用,整个部署的 I/O 都会停止。真正的容灾要靠站点复制(mc replicate add)或异地 mc mirror,这两件事不要混为一谈。

负载均衡与健康检查​

生产环境不要让客户端直连某个节点,前面挂一层负载均衡:

upstream minio_api {
least_conn; # MinIO 官方推荐,不要用 ip_hash
server minio1.example.net:9000 max_fails=3 fail_timeout=10s;
server minio2.example.net:9000 max_fails=3 fail_timeout=10s;
server minio3.example.net:9000 max_fails=3 fail_timeout=10s;
server minio4.example.net:9000 max_fails=3 fail_timeout=10s;
}

server {
listen 443 ssl;
server_name s3.example.net;

client_max_body_size 0; # 不限上传大小,大对象必配
proxy_buffering off; # 流式转发,别把大对象缓到内存/磁盘
proxy_request_buffering off;
chunked_transfer_encoding off;

location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_connect_timeout 300;
proxy_read_timeout 300;
proxy_pass http://minio_api;
}
}

健康检查用哪个端点,取决于你要探什么:

端点含义用途
/minio/health/live进程活着就返回 200负载均衡摘除故障节点、K8s livenessProbe
/minio/health/cluster集群达到仲裁(quorum)才返回 200判断整个集群是否可服务,告警用
/minio/health/ready节点准备好服务读请求K8s readinessProbe
健康检查别探太频繁

/minio/health/cluster 会真的检查集群仲裁状态,高频率探测会给集群增加负担。负载均衡的被动检查(max_fails)配合 30 秒一次的主动探测就够了,不要设成 1 秒一次。

小结​

  • 生产从 4 节点 × 4 盘起步,EC:4 下可用容量 75%、能扛住 4 块盘或 1 个节点故障;容量按两年规划、70% 水位前扩容。
  • 硬性约束记牢:至少 4 盘、盘要直通不要 RAID、文件系统 XFS、所有节点同端口、时间必须同步。
  • 对象路由靠命名空间哈希,无中心元数据;任意节点都能处理请求,负载均衡用 least_conn。
  • MINIO_VOLUMES 用扩展写法列出所有池,配置变更、升级、扩容都要全节点同时重启,禁止滚动(单节点硬件维修是例外)。
  • TLS 靠 certs/public.crt + private.key 自动启用,内部 CA 要分发到每个节点的 certs/CAs。
  • 扩容只能加池(每池至少 2 × EC:N 块盘),老数据不自动迁移,按空闲空间比例写新对象,必要时 mc admin rebalance。
  • 健康检查分三层:live 探进程、ready 探节点、cluster 探仲裁。

集群跑起来只是开始。下一篇《运维与监控》讲日常巡检、heal 修复、Prometheus 指标和容量治理。