手动重新平衡您的 MinIO 现代数据湖

Manually Rebalance your MinIO Modern Datalake

当 MinIO Modern Datalake 部署通过添加新的服务器池进行扩展时,默认情况下它不会重新平衡对象。相反,MinIO 会将新的文件/对象写入具有更多可用空间的池中。手动触发 MinIO 的重新平衡会扫描整个部署,然后对象会在服务器池之间移动(如果需要),以确保所有池在之后都具有几乎相同的可用空间级别。对于 MinIO 部署来说,这是一个代价高昂的操作,应谨慎触发。虽然重新平衡可以在任何时候停止和重新启动。

在独立部署中模拟重新平衡场景并不容易,无论它是基于 Kind 的集群还是使用目录作为驱动器的独立部署。为了实际触发重新平衡,我们需要将现有的池填充到几乎满载,然后在添加新的服务器池后,手动触发重新平衡。出于这个原因,使用虚拟机模拟此场景总是更容易且更好。

为了快速简便地模拟重新平衡的开发者模式,LXD(Linux 容器虚拟机管理程序)是一个不错的选择。本博文将列出所需的设置并描述如何实现模拟重新平衡的过程。

设置基础设施

按照以下步骤模拟 MinIO Modern Datalake 部署中的重新平衡。为此,我们应该使用 Ubuntu 启动总共 8 个 LXD 虚拟机。我们将使用前 4 个虚拟机启动初始 MinIO 实例,然后使用接下来的 4 个虚拟机进行扩展。为了限制可以加载的对象的大小,我们将使用主机上的循环设备向所有虚拟机添加大小为 1GiB 的虚拟磁盘。所以,让我们开始吧!请按照以下步骤操作。

LXD 可作为 snap 包正式提供,因此请先安装 snapd。

$ sudo apt install snapd

$ sudo ln -s /var/lib/snapd/snap /snap

$ snap version

$ sudo systemctl restart snapd.service

现在安装 lxd。

$ sudo snap install lxd

验证安装并启动 LXD。

$ sudo snap enable lxd

$ sudo snap services lxd

$ sudo snap start lxd

将您的用户名添加到 lxd 组。

$ sudo usermod -a -G lxd <USERNAME>

$ id <USERNAME>

$ newgrp lxd

初始化 LXD。

$ lxd init

这将引导您完成一系列问题,大多数默认问题都可以接受。

您是否要使用 LXD 集群?(yes/no) [default=no]

您是否要配置新的存储池?(yes/no) [default=yes]

新存储池的名称 [default=default]

要使用的存储后端的名称 (btrfs, ceph, dir, lvm) [default=btrfs]

创建新的 BTRFS 池?(yes/no) [default=yes]

您是否要使用现有的块设备?(yes/no) [default=no]

新块设备的大小(以 GB 为单位)(最小 1GB)(默认 30GB)

您是否要连接到 MAAS 服务器?(yes/no) [default=no]

您是否要创建一个新的本地网络桥接?(yes/no) [default=yes]

新桥接的名称是什么?(默认 lxdbr0)

应使用什么 IPv4 地址?(CIDR 子网表示法,“auto”或“none”)[default=auto]

应使用什么 IPv6 地址?(CIDR 子网表示法,“auto”或“none”)[default=auto]: none

您是否希望 LXD 可通过网络访问?(yes/no) [default=no]

您是否希望过时的缓存映像自动更新?(yes/no) [default=yes]

您是否希望打印 YAML "lxd init" 按钮?(yes/no) [default=no]

使用以下命令创建虚拟机。

$ lxc init images:ubuntu/jammy vm-01 --profile=default -c boot.autostart=true -c security.privileged=true -c security.syscalls.intercept.mount=true -c security.syscalls.intercept.mount.allowed=ext4 -c limits.memory=1024MB -c limits.cpu.allowance=10%

$ lxc start vm-01

对所有 8 个虚拟机重复这些命令。现在,为了使所有虚拟机的 IPv4 IP 都有序,请执行以下命令重置它们的 IP。

$ lxc stop vm-01

$ lxc network attach lxdbr0 vm-01 eth0 eth0

$ lxc config device set vm-01 eth0 ipv4.address 10.115.111.111

$ lxc start vm-01

类似地,对于其他虚拟机,IP 可以设置为 10.115.111.112、10.115.111.113 等。

现在进入虚拟机内部,创建大小为 1GiB 的虚拟磁盘映像,并使用 mkfs.ext4 对其进行格式化。还为主机上的循环设备创建一个挂载路径。

$ lxc exec vm-01 bash

$ truncate -s 1GiB /media/disk.img

$ mkfs.ext4 /media/disk.img

$ mkdir /mnt/virtual-disk

对所有虚拟机重复此操作。

现在,我们将主机上可用的循环设备附加到虚拟机。这些只是列为 /dev/loop* 的文件,并不一定所有列出的文件都可用。如果在虚拟机内挂载时遇到问题 mount: /mnt/virtual-disk: failed to setup loop device for /media/disk.img.,请在主机上创建一个新的循环设备并尝试使用新的设备。使用命令 sudo losetup -f 获取一个新的可用循环设备。请按照以下步骤在虚拟机内附加和挂载循环设备

$ lxc config device add vm-01 loop-control unix-char path=/dev/loop-control

$ lxc config device add vm-01 loop4 unix-block path=/dev/loop4

从虚拟机内部挂载它。

$ lxc exec vm-01 bash

$ mount -t ext4 -o loop /media/disk.img /mnt/virtual-disk

对所有虚拟机重复此过程。要验证挂载是否成功,请在虚拟机内运行以下命令。

$ mount | grep virtual-disk

/media/disk.img on /mnt/virtual-disk type ext4 (rw,realtime)

虚拟机现在已准备就绪,我们可以开始 MinIO 部署了

设置 MinIO

我们需要创建许多对象,我们稍后会将其推送到 MinIO 存储桶。在主机节点上执行以下命令以执行此操作

$ mkdir -p $HOME/test-minio-rebal

$ cd $HOME/test-minio-rebal

$ for index in {1..4500}; do truncate -s 1M file$index; done

这将创建 4500 个大小均为 1M 的随机文件。

在所有虚拟机上安装 MinIO 二进制文件

$ wget -O https://dl.min.io/server/minio/release/linux-amd64/minio

$ chmod +x minio

$ mv minio /usr/local/bin

MinIO 客户端可以安装在主机本身上。

$ wget -O https://dl.min.io/client/mc/release/linux-amd64/mc

$ chmod +x mc

$ sudo mv mc /usr/local/bin

启动 MinIO 实例并加载对象。首先获取所有正在运行的 lxc 虚拟机的列表并记下它们的 IPv4 IP。

$ lxc list

+-------+---------+---------------------+----------------------------------------------+-----------+-----------+

| NAME  |  STATE  |    IPV4     |                 IPV6                 |   TYPE | SNAPSHOTS |

+-------+---------+---------------------+----------------------------------------------+-----------+-----------+

| vm-01 | RUNNING | 10.49.238.61 (eth0) | fd42:9cd0:6055:a53:216:3eff:fef3:f0f (eth0)  | CONTAINER | 0     |

+-------+---------+---------------------+----------------------------------------------+-----------+-----------+

| vm-02 | RUNNING | 10.49.238.62 (eth0) | fd42:9cd0:6055:a53:216:3eff:fe16:4d04 (eth0) | CONTAINER | 0     |

+-------+---------+---------------------+----------------------------------------------+-----------+-----------+

| vm-03 | 运行中 | 10.49.238.63 (eth0) | fd42:9cd0:6055:a53:216:3eff:fe34:44cd (eth0) | 容器 | 0     |

+-------+---------+---------------------+----------------------------------------------+-----------+-----------+

| vm-04 | 运行中 | 10.49.238.64 (eth0) | fd42:9cd0:6055:a53:216:3eff:fef9:4262 (eth0) | 容器 | 0     |

+-------+---------+---------------------+----------------------------------------------+-----------+-----------+

| vm-05 | 运行中 | 10.49.238.65 (eth0) | fd42:9cd0:6055:a53:216:3eff:fe16:2e02 (eth0) | 容器 | 0     |

+-------+---------+---------------------+----------------------------------------------+-----------+-----------+

| vm-06 | 运行中 | 10.49.238.66 (eth0) | fd42:9cd0:6055:a53:216:3eff:fe94:4610 (eth0) | 容器 | 0     |

+-------+---------+---------------------+----------------------------------------------+-----------+-----------+

| vm-07 | 运行中 | 10.49.238.67 (eth0) | fd42:9cd0:6055:a53:216:3eff:fef1:40f3 (eth0) | 容器 | 0     |

+-------+---------+---------------------+----------------------------------------------+-----------+-----------+

| vm-08 | 运行中 | 10.49.238.68 (eth0) | fd42:9cd0:6055:a53:216:3eff:fef5:d909 (eth0) | 容器 | 0     |

+-------+---------+---------------------+----------------------------------------------+-----------+-----------+

现在使用前四台虚拟机启动一个 MinIO 实例,如下所示。此命令应在前面四台虚拟机内部运行。

$ minio server http://10.49.238.{61...64}/mnt/virtual-disk/disk{1...4}

实例稳定后,为集群创建 mc 别名,如下所示。

mc alias set ALIAS http://10.49.238.61:9000 minioadmin minioadmin

现在可以将对象加载到集群中了。运行以下命令执行此操作。

$ mc mb ALIAS/test-bucket

$ mc cp $HOME/test-minio-rebal/* ALIAS/test-bucket

您可能会在最后看到磁盘空间不足的错误,这是正常的,因为集群现在已将对象加载到极限。等待几秒钟,然后验证对象是否已加载到池中。

$ mc admin info ALIAS --json | jq -r '.info.pools'

{                                                                                                           

  "0": {                                                                                                           

"0": {                                                                                                           

   "id": 0,                                                                                                           

   "rawUsage": 3785478144,                                                                                                           

   "rawCapacity": 3800956928,                                                                                                           

   "usage": 1155530752,                                                                                                           

   "objectsCount": 1102,                                                                                                           

   "versionsCount": 0,                                                                                 

   "healDisks": 0                                                                                 

}                                                                                

  }                                                                               

}

现在我们可以用一组新的节点扩展集群了。停止前 4 台虚拟机上的 MinIO 进程,然后从所有 8 台虚拟机运行以下命令。

$ minio server http://10.49.238.{61...64}/mnt/virtual-disk/disk{1...4} http://10.49.238.{65...68}/mnt/virtual-disk/disk{1...4}

等待集群稳定,并检查是否添加了新的池。

$ mc admin info ALIAS --json | jq -r '.info.pools'

{

  "0"

"0": {                                                                                                                  

   "id": 0,                                                                                                               

   "rawUsage": 3785478144,                                                                                            

   "rawCapacity": 3800956928,                                                                                          

   "usage": 1155530752,                                                                                            

   "objectsCount": 1102,                                                                                                                                                

   "versionsCount": 0,                                                                                                                                                

   "healDisks": 0                                                                                                                                                     

}                                                                                                                                                                    

  },                                                                                                                                                                     

  "1": {                                                                                                                                                                 

"0": {                                                                                                                  

   "id": 0,                                                                                                               

   "rawUsage": 376832,                                                                                                                                                

   "rawCapacity": 3800956928,                                                                                          

   "usage": 0,                                                                                                                                                      

   "objectsCount": 0,                                                                                                                                                 

   "versionsCount": 0,                                                                                                                                                

   "healDisks": 0                                                                                                                                                     

}                                                                                                                                                                    

  }                                                                                                                                                                      

}

现在您可以安全地在集群上运行重新平衡操作。

$ mc admin rebalance start ALIAS

您可以跟踪正在运行的重新平衡状态,如下所示。

$ mc admin rebalance status ALIAS

每个池的使用情况

┌─────────┬────────┐

│ 池-0  │ 池-1      │

│ 0.85% * │ 0.14%       │

└─────────┴────────┘

摘要

数据: 390 MiB (195 个对象,195 个版本)

时间: 11.40798155s (完成时间 52.794879439s)

一旦重新平衡完成并且没有更多对象需要移动,您应该能够验证如下内容。

$ mc admin info ALIAS --json | jq -r '.info.pools'

{

  "0": {

"0": {

   "id": 0,

   "rawUsage": 2029391872,

   "rawCapacity": 3800956928,

   "usage": 1394606080,

   "objectsCount": 1330,

   "versionsCount": 0,

   "healDisks": 0

}

  },

  "1": {

"0": {

   "id": 0,

   "rawUsage": 1756606464,

   "rawCapacity": 3800956928,

   "usage": 435159040,

   "objectsCount": 415,

   "versionsCount": 0,

   "healDisks": 0

}

  }

}

就这么简单。

最终思考

通常,当添加或删除新的存储池时,MinIO 不需要任何手动重新平衡。MinIO 足够智能,可以将新数据添加到有可用空间的位置,同时牢记擦除编码要求。重新平衡是一个非常占用资源的操作,因此不建议在集群使用最频繁的高峰时段运行它。相反,如果需要重新平衡集群,则必须在集群使用最少的非高峰时段进行。

如果您对重新平衡以及如何管理 MinIO 现代数据湖有任何疑问,请务必在Slack上与我们联系!