k8s 1.28.2 集群部署 MinIO 分布式集群
MinIO 介绍
- MinIO 官网
- MinIO 官方 linux 的部署文档
- 以下内容从官方翻译
- MinIO 是一款软件定义的高性能分布式对象存储服务器
- 所有 MinIO 部署都实施纠删码后端
- MinIO 有以下三种拓扑
SNSD
或者Standalone
:Single-Node Single-Drive
,单节点驱动器
- 除了底层存储卷实现的范围之外,它不会提供额外的可靠性或可用性。这些部署最适合本地测试和评估,或者没有可用性或性能要求的小型数据工作负载。
SNMD
或者Standalone Multi-Drive
:Single-Node Multi-Drive
,单节点多驱动器
- 性能、规模和容量要求较低的工作负载
- 驱动器级可靠性,具有可配置的容差,可丢失高达 1/2 的所有驱动器
MNMD
或者Distributed
:Multi-Node Multi-Drive
,多节点多驱动器
或分布式
- 提供企业级性能、可用性和可扩展性,是所有生产工作负载的推荐拓扑,该配置可容忍部署中最多丢失一半的节点或驱动器,同时继续提供读取操作
- 多节点 / 驱动器级可靠性,可配置的容差,损失高达 1/2 所有节点 / 驱动器
- AI/ML、分布式查询、分析和其他数据湖组件的主存储
- 可针对 PB + 工作负载进行扩展 - 存储容量和性能
- MinIO 有以下三种拓扑
- 站点复制(
Site Replication
)- 站点复制扩展了存储桶复制的功能,包括在所有站点中都相同的 IAM、安全令牌、访问密钥和存储桶功能
- 站点复制将多个 MinIO 部署链接在一起,并使存储桶、对象和 Identity and Access Management (IAM) 设置在所有连接的站点之间保持同步
- 每个 MinIO 部署(“对等站点”)都会在其他对等站点之间同步以下更改:
- 创建、修改和删除存储桶和对象
- 存储桶和对象配置
- Policies
mc tag set
- Locks,锁定,包括保留和依法保留配置
- 加密设置
- 创建、修改和删除存储桶和对象
- 创建和删除 IAM 用户、组、策略以及到用户或组的策略映射(适用于 LDAP 用户或组)
- 为可从本地
root
凭据验证的会话令牌创建安全令牌服务 (STS) 凭据 - 创建和删除访问密钥(
root
用户拥有的密钥除外) - 站点复制为所有复制站点上的所有新存储桶和现有存储桶启用存储桶版本控制
- Not Replicate
- 并非所有内容都可以跨站点复制
- 存储桶通知
- 生命周期管理 (ILM) 配置
- 站点配置设置
- 并非所有内容都可以跨站点复制
MinIO 生产硬件要求
- 以下清单遵循 MinIO 的生产部署推荐配置。提供的指南旨在作为基准,不能取代 MinIO SUBNET 性能诊断、架构审查和直接工程支持
- 与任何分布式系统一样,MinIO 受益于为给定服务器池中的所有节点选择相同的配置。确保在池节点之间一致地选择硬件(CPU、内存、主板、存储适配器)和软件(操作系统、内核设置、系统服务)
- 如果节点具有不同的硬件或软件配置,则部署可能会表现出不可预测的性能。受益于在低成本硬件上存储过时数据的工作负载应部署专用的 “暖” 或 “冷” MinIO 部署,并将数据转换到该层
硬件类型 | 最低要求 | 推荐配置 |
---|---|---|
主机 | 4个专用主机 | 8+ 专用主机 |
每个主机的专用本地驱动器 | 4个用于 MinIO 的驱动器 | 每个 MinIO 服务器 8+ 个驱动器 |
网络基础设施 | 25GbE 网络 | 100GbE 网络 |
支持现代 SIMD 指令 (AVX-512) 的服务器级 CPU | 每台主机 8 个 CPU / 插槽或 vCPU | 每台主机 16+ CPU / 插槽或 vCPU |
可用内存,以合理的缓冲区满足或超过每个服务器的使用量 | 每台主机 32GB 可用内存 | 每台主机 128GB+ 的可用内存 |
- 以下方面对 MinIO 性能的影响最大,按重要性顺序列出
类型 | 影响 |
---|---|
网络基础设施 | 吞吐量不足或受限会限制性能 |
存储控制器 | 旧固件、吞吐量受限或硬件故障会限制性能并影响可靠性 |
存储 (驱动器) | 旧固件或硬件运行缓慢 / 老化 / 故障会限制性能并影响可靠性 |
- 以上最低建议反映了 MinIO 在协助企业客户在各种 IT 基础设施上部署同时保持所需 SLA/SLO 的经验。
- 虽然 MinIO 可能在低于建议的最低拓扑上运行,但任何潜在的成本节省都存在可靠性、性能或整体功能降低的风险
MinIO 存储要求
-
使用本地存储
- 与网络存储(NAS、SAN、NFS)相比,直连存储 (DAS) 具有显著的性能和一致性优势。MinIO 强烈建议将闪存存储(NVMe、SSD)用于主数据或 “热” 数据
-
使用
XFS
文件系统-
MinIO 强烈建议配置 XFS 格式的文件系统进行存储。MinIO 使用 XFS 作为内部测试和验证套件的一部分,为所有规模的性能和行为提供额外的信心
- 将驱动器格式化为 XFS,并将它们作为 JBOD 阵列呈现给 MinIO,没有 RAID 或其他池配置。使用任何其他类型的后备存储(SAN/NAS、ext4、RAID、LVM)通常会导致性能、可靠性、可预测性和一致性降低
-
禁用 XFS 出错时重试
-
MinIO 强烈建议对以下错误类使用
max_retries
配置禁用 retry-on-error 行为EIO
:读取或写入时出错ENOSPC
:device no space left on devicedefault
:所有其他错误
-
默认的
max_retries
设置通常指示文件系统无限期地在出错时重试,而不是传播错误。MinIO 可以适当地处理 XFS 错误,因此 retry-on-error 行为最多会导致不必要的延迟或性能下降。 -
下面是官方提供的脚本,遍历指定挂载路径上的所有驱动器,并将建议的错误类的 XFS
max_retries
设置设置为0
或 “fail immediately on error”。该脚本会忽略任何未挂载的驱动器,无论是手动挂载还是通过/etc/fstab
挂载。修改/mnt/drive
行以匹配用于 MinIO 驱动器的模式-
必须在所有 MinIO 节点上运行此脚本,并将脚本配置为在重新启动时重新运行,因为 Linux 操作系统通常不会保留这些更改
-
#!/bin/bash for i in $(df -h | grep /mnt/drive | awk '{ print $1 }'); do mountPath="$(df -h | grep $i | awk '{ print $6 }')" deviceName="$(basename $i)" echo "Modifying xfs max_retries and retry_timeout_seconds for drive $i mounted at $mountPath" echo 0 > /sys/fs/xfs/$deviceName/error/metadata/EIO/max_retries echo 0 > /sys/fs/xfs/$deviceName/error/metadata/ENOSPC/max_retries echo 0 > /sys/fs/xfs/$deviceName/error/metadata/default/max_retries done exit 0
-
-
-
-
使用一致类型的驱动器
- MinIO 不区分驱动器类型,并且不会从混合存储类型中受益。每个池必须使用相同的类型(NVMe、SSD)
- 例如,部署一个仅包含 NVMe 驱动器的池。如果您将某些驱动器部署为 SSD 或 HDD,则 MinIO 会将这些驱动器视为与 NVMe 驱动器相同。这可能会导致性能问题,因为某些驱动器具有不同或更差的读 / 写特性,并且无法以与 NVMe 驱动器相同的速率响应
-
使用一致大小的驱动器
- MinIO 将每个驱动器使用的大小限制为部署中的最小驱动器
- 例如,部署一个由相同数量的 NVMe 驱动器组成的池,这些驱动器具有相同的容量
7.68TiB
。如果使用3.84TiB
部署一个驱动器,则 MinIO 会将池中的所有驱动器视为具有较小的容量
-
在重新启动后保留驱动器挂载和映射
- Linux 操作系统,需要确保在
/etc/fstab
配置了驱动器挂载- MinIO 强烈建议使用基于标签(
mkfs.xfs /dev/xxx -L MINIODRIVEx
)的挂载规则,而不是基于 UUID 的规则。基于标签的规则允许将运行状况不佳或不工作的驱动器与具有匹配格式和标签的替代驱动器交换。 - 基于 UUID 的规则需要编辑
/etc/fstab
文件以将映射替换为新的驱动器 UUID
- MinIO 强烈建议使用基于标签(
- 非 Linux 操作系统应使用等效的驱动器挂载管理工具
- Linux 操作系统,需要确保在
-
独占驱动器
- MinIO 需要为对象存储提供的驱动器或卷的独占访问权限。任何其他进程、软件、脚本或人员都不应直接对提供给 MinIO 的驱动器或卷或 MinIO 放置在其上的对象或文件执行任何操作
- 除非 MinIO Engineering 指示,否则请勿使用脚本或工具直接修改、删除或移动所提供驱动器上的任何数据分片、奇偶校验分片或元数据文件,包括从一个驱动器或节点移动到另一个驱动器或节点。此类操作很可能导致超出 MinIO 修复能力的大范围损坏和数据丢失
MinIO 内存要求
- 内存主要限制每个节点的并发同时连接数
- 使用以下公式计算每个节点的最大并发请求数
totalRam / ramPerRequest
- 使用以下公式计算每个请求使用的 RAM 量
((2MiB + 128KiB) * driveCount) + (2 * 10MiB) + (2 * 1 MiB)
- 10 MiB 是默认纠删块大小 v1
- 1 MiB 是默认的纠删块大小 v2
- 使用以下公式计算每个节点的最大并发请求数
- 从
RELEASE.2024-01-28T22-35-53Z
开始分布式
设置中为每个节点预分配 2GiB 内存单节点
设置预分配 1GiB 内存
- 下表列出了基于主机驱动器数量和可用系统 RAM 的节点上的最大并发请求数
驱动器 | 32GiB 内存 | 64GiB 内存 | 128GiB 内存 | 256GiB 内存 | 512GiB 内存 |
---|---|---|---|---|---|
4 | 1,074 | 2,149 | 4,297 | 8,595 | 17,190 |
8 | 840 | 1,680 | 3,361 | 6,722 | 13,443 |
16 | 585 | 1,170 | 2.341 | 4,681 | 9,362 |
- 下表提供了根据节点上的本地存储总量分配内存以供 MinIO 使用的一般准则
主机总存储 | 建议的内存大小 |
---|---|
最高 1Ti | 8GiB |
最高 10Ti | 16GiB |
最高 100Ti | 32GiB |
最高 1PB | 64GiB |
超过 1PB | 128GiB |
MinIO 网络要求
- MinIO 建议高速联网以支持附加存储(聚合驱动器、存储控制器和 PCIe 总线)的最大可能吞吐量。下表提供了给定物理或虚拟网络接口支持的最大存储吞吐量的一般准则。下表假定所有网络基础设施组件(如路由器、交换机和物理布线)也支持 NIC 带宽
NIC 带宽 (Gbps) | 估计的聚合存储吞吐量 (GBps) |
---|---|
10Gbps | 1.25GBps |
25Gbps | 3.125GBps |
50Gbps | 6.25GBps |
100Gbps | 12.5GBps |
- 联网对 MinIO 性能的影响最大,其中每个主机的低带宽人为地限制了存储的潜在性能。以下网络吞吐量约束示例假定旋转驱动器具有~100MB/S 的持续 I/O
- 1GbE 网络链接可支持高达 125MB/s 或 1 个旋转驱动器
- 10GbE 网络可以支持大约 1.25GB/s,可能支持 10-12 个旋转驱动器
- 25GbE 网络可以支持大约 3.125GB/s,可能支持~30 个旋转驱动器
MinIO 部署架构
分布式 MinIO
- 生产 MinIO 部署由至少 4 个 MinIO 主机组成,这些主机具有同构存储和计算资源
MinIO 将这些资源聚合在一起作为一个池,并将自身呈现为单个对象存储服务
- MinIO 会自动将池中的驱动器分组到纠删集中
- MinIO 使用基于对象名称和路径的确定性哈希算法来选择为给定对象设置的纠删集
- 对于每个唯一的对象命名空间
BUCKET/PREFIX/[PREFIX/...]/OBJECT.EXTENSION
,MinIO 始终为读 / 写操作选择相同的纠删集。MinIO 处理池和纠删集中的所有路由,使选择 / 读 / 写过程对应用程序完全透明
- 对于每个唯一的对象命名空间
- 每个 MinIO 服务器都有分布式拓扑的完整图,因此应用程序可以连接部署中的任何节点并针对部署中的任何节点执行直接操作
- MinIO 响应节点会自动处理将内部请求路由到部署中的其他节点,并将最终响应返回给客户端
- 应用程序通常不应管理这些连接,因为对部署拓扑的任何更改都需要应用程序更新。生产环境应部署负载均衡器或类似的网络控制平面组件来管理与 MinIO 部署的连接。例如,您可以部署 NGINX 负载均衡器,以对部署中的可用节点执行 “最少连接” 或 “循环” 负载均衡
- 可以通过
池扩展
来扩展 MinIO 部署的可用存储- 每个池都由一组独立的节点组成,这些节点具有自己的纠删集。MinIO 必须查询每个池,以确定它将读取和写入操作定向到的正确擦除集,以便每个额外的池都会增加每次调用的节点间流量。然后,包含正确纠删集的池将响应该操作,对应用程序保持完全透明
- 如果您通过池扩展修改 MinIO 拓扑,则可以通过修改负载均衡器以包含新池的节点来更新您的应用程序。应用程序可以继续使用 MinIO 部署的负载均衡器地址,而无需进行任何更新或修改。这可确保在所有池中均匀分配请求,同时应用程序继续使用单个负载均衡器 URL 进行 MinIO 操作
复制的 MinIO
- MinIO 对等站点的站点复制,可以在不同的机架、数据中心或地理区域中部署对等站点,以此来实现 BC/DR (业务连续性与灾难恢复:
Business Continuity and Disaster Recovery
)或提升读 / 写性能等功能 - 复制性能主要取决于每个对等站点之间的网络延迟
- 对于地理位置分散的对等站点,站点之间的高延迟可能会导致严重的复制滞后。这可能会与接近或等于部署整体性能容量的工作负载复合,因为复制过程本身需要足够的可用 I/O 来同步对象
- 部署支持 Site-to-Site 故障转移协议的 Global Load Balancer 或类似网络设备对于多站点部署的功能至关重要
- 负载均衡器应支持运行状况探测 / 检查设置,以检测一个站点的故障并自动将应用程序重定向到任何剩余的运行状况良好的对等体
- 负载均衡器应满足与单站点部署相同的连接平衡和标头保留要求。MinIO 复制通过对要复制的对象进行排队来处理暂时性故障
部署 MinIO
我这里是自己学习使用的,部署的是 4 节点的 MinIO 分布式集群
创建目录
MinIO 运行的节点都需要创建目录
mkdir -p /approot/k8s_data/minio
节点打标签
MinIO 运行的节点都需要打标签,以自己的节点为准
kubectl label node 192.168.22.122 minio=true
kubectl label node 192.168.22.123 minio=true
kubectl label node 192.168.22.124 minio=true
kubectl label node 192.168.22.125 minio=true
创建 namespace
kubectl create ns storage
创建 pv
- pv 采用 hostPath 的方式,并且 pv 绑定到不同的节点,我这边是 4 节点的 MinIO 集群,要创建 4 个 pv,并且绑定到 4 个不同的节点(目的是让 pod 的副本固定节点运行,如果节点发生飘移,会导致 MinIO 不可用,可以参考官方的文档:local 卷),下面的 pv yaml 内容是我自己环境的,大家需要修改成自己环境的 ip 地址
- pvc 会直接采用
volumeClaimTemplates
的方式自动申领
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: minio-minio-0
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: minio-minio-0
namespace: storage
hostPath:
path: /approot/k8s_data/minio
type: DirectoryOrCreate
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- 192.168.22.122
persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: minio-minio-1
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: minio-minio-1
namespace: storage
hostPath:
path: /approot/k8s_data/minio
type: DirectoryOrCreate
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- 192.168.22.123
persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: minio-minio-2
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: minio-minio-2
namespace: storage
hostPath:
path: /approot/k8s_data/minio
type: DirectoryOrCreate
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- 192.168.22.124
persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: minio-minio-3
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 10Gi
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: minio-minio-3
namespace: storage
hostPath:
path: /approot/k8s_data/minio
type: DirectoryOrCreate
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- 192.168.22.125
persistentVolumeReclaimPolicy: Retain
创建 MinIO
---
apiVersion: v1
kind: Service
metadata:
labels:
app: minio
name: minio-svc
namespace: storage
spec:
ports:
- name: http
port: 9000
protocol: TCP
targetPort: 9000
- name: console
port: 8000
protocol: TCP
targetPort: 8000
selector:
app: minio
type: ClusterIP
---
apiVersion: v1
kind: Secret
metadata:
name: minio-secret
namespace: storage
stringData:
password: 1q@W3e$R
username: admin
type: kubernetes.io/basic-auth
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: minio
namespace: storage
spec:
podManagementPolicy: Parallel
replicas: 4
selector:
matchLabels:
app: minio
serviceName: minio-svc
template:
metadata:
labels:
app: minio
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: minio
operator: In
values:
- "true"
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- minio
topologyKey: kubernetes.io/hostname
containers:
- args:
- server
- http://minio-{0...3}.minio-svc.storage.svc.cluster.local/data
- --console-address
- :8000
- --address
- :9000
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
key: username
name: minio-secret
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: minio-secret
image: m.daocloud.io/minio/minio:RELEASE.2024-09-22T00-33-43Z
imagePullPolicy: IfNotPresent
name: minio
ports:
- containerPort: 9000
name: http
protocol: TCP
- containerPort: 8000
name: console
protocol: TCP
resources:
limits:
cpu: 1000m
memory: 2048Mi
requests:
cpu: 100m
memory: 100Mi
volumeMounts:
- mountPath: /data
name: minio
# 自动申领 pvc
volumeClaimTemplates:
- metadata:
name: minio
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
配置 ingress
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minio
namespace: storage
spec:
ingressClassName: nginx
rules:
- host: minio.devops.icu
http:
paths:
- backend:
service:
name: minio-svc
port:
number: 8000
path: /
pathType: Prefix
通过浏览器访问
minio.devops.icu
就可以了,用户名密码是secret
里面配置的username
和password
,找到metrics
界面,查看当前的集群情况
然后可以自己创建
Buckets
,然后上传文件尝试
问题记录
通过代理服务器访问 MinIO 的 Object Browser
界面一直显示 loading
通过浏览器的开发者工具,可以看到 console 这里很多
websocket
的报错,需要让代理服务器支持websocket
- 对应的 location 这块加上下面三个参数来支持
websocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
- 重载 nginx 的配置,或者重启 nginx 服务来生效配置文件,刷新一下就发现正常了
然后可以自己创建
Buckets
,然后上传文件尝试