Minio集群部署

Posted by elrond on February 28, 2022

1. 准备部署

三台服务器,每台服务器挂一块磁盘,每台挂一块500g的磁盘,分成五个区,没个区100G,挂到同的数据目录 minio的数据和元数据都直接写在linux文件系统上,不关注是linux文件系统类型,只需配置好minio数据目录即可

172.16.11.250 test001
172.16.11.21  test002
172.16.11.206 test003

architecture-diagram_distributed_nm

1.1. 版本说明

组件 版本 备注
操作系统 CentOS Linux release 7.9.2009 (Core)  
minio RELEASE.2022-02-18T01-50-10Z  
Prometheus prom/prometheus:v2.7.2 容器镜像版本

1.2. 分区配置

每个区一个分区,挂载到一个目录,每个目录是一个minio的存储单元

DEVICE=/dev/vdc
parted -s  $DEVICE mklabel gpt
parted -s  $DEVICE mkpart primary 1 100G
parted -s  $DEVICE mkpart primary 100G 200G
parted -s  $DEVICE mkpart primary 200G 300G
parted -s  $DEVICE mkpart primary 300G 400G
parted -s  $DEVICE mkpart primary 400G 500G

for i in {1..5};do mkfs.ext4 $DEVICE$i;done
for i in {1..5};do mkdir -p /data/minio/data$i;done
for i in {1..5};do mount $DEVICE$i /data/minio/data$i;done

2. 部署minio

2.1. 二进制包

mkdir -p /data/minio/{bin,scripts,etc}
wget https://dl.min.io/server/minio/release/linux-amd64/minio -O /data/minio/bin/minio
chmod +x /data/minio/bin/minio
ln -s /data/minio/bin/minio /usr/local/bin/minio

2.2. 启动minio

cat > /data/minio/scripts/run.sh << EOF
#!/bin/env bash
export MINIO_ROOT_USER=Minio
export MINIO_ROOT_PASSWORD=Minio123456
minio server --config-dir /data/minio/etc \
  --console-address ":9001" \
  http://test00{1...3}/data/minio/data{1...5}
EOF

chmod +x /data/minio/scripts/run.sh

cat > /usr/lib/systemd/system/minio.service << EOF
[Unit]
Description=Minio service
Documentation=https://docs.minio.io/

[Service]
WorkingDirectory=/data/minio/
ExecStart=/data/minio/scripts/run.sh

Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl start minio
systemctl enable minio
systemctl status minio.service

此时可以通过三台服务器中的任意一台访问console http://ceph01:9001, 密码为上面启动脚本中设置的密码

3. prometheus监控

3.1. 安装mc

wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /data/minio/bin/mc
chmod +x /data/minio/bin/mc
ln -s /data/minio/bin/mc /usr/local/bin/mc

3.2. 配置mc

mc alias set myminio http://172.16.11.250:9000  Minio Minio123456
  • 生成prometheus配置
mc admin prometheus generate myminio
scrape_configs:
- job_name: minio-job
  bearer_token: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ3OTkxOTgzMjMsImlzcyI6InByb21ldGhldXMiLCJzdWIiOiJNaW5pbyJ9.sFSa4d9O7xFVBzQSkAjMHv2Q0WGBxXdm7vtZ-D6ay1c7BZjS_mp3XwgJrJHtpwkDdvcza2lhmachV9iBRUVb5g
  metrics_path: /minio/v2/metrics/cluster
  scheme: http
  static_configs:
  - targets: ['172.16.11.250:9000']
  • 配置增加到prometheus,重启服务
  • 将prometheus配置增加到minio中,重启minio
cat /data/minio/scripts/run.sh
#!/bin/env bash
# 新增这行
export MINIO_PROMETHEUS_URL=http://172.16.10.10:9092
export MINIO_ROOT_USER=Minio
export MINIO_ROOT_PASSWORD=Minio123456
minio server --config-dir /data/minio/etc \
  --console-address ":9001" \
  http://test00{1...3}/data/minio/data{1...5}

所有节点都需修改,修改完重启

systemctl restart minio

使用mc重启

mc admin service restart myminio

重启完之后即可看到dashboard http://172.16.11.250:9001/tools/dashboard

mino_dashboard

4. 附录

4.1. 数据在磁盘的组织形式

4.1.1. 小文件

4.1.1.1. 探索

元数据组织形式如下下图 2

minio-meta-layout

上传一个txt文件

  • 准备文件
echo "helloworld" > test.txt

上传上去之后看下本地目录文件结构如图, 15个data目录下各有一份数据

-- data5
   `-- test002
       `-- test.txt
           `-- xl.meta

解析每台的元数据看看,从上面的元数据组织形式,我们能得知数据是存在最后面,所以我们看最后几行就好,通过下面最后几行我们能粗略的组合出我们写入的 helloworld

test001

[root@test001 minio]# for i in {1..5};do hexdump -Cv /data/minio/data$i/test002/test.txt/xl.meta|tail -n 2;done
00000520  3a 18 1c 65 95 4a 65                              |:..e.Je|
00000527
00000520  2c 18 cc 94 98 cf 6f                              |,.....o|
00000527
00000520  c6 c5 7a de bc 54 72                              |..z..Tr|
00000527
00000520  92 92 aa 9d 12 dc 0a                              |.......|
00000527
00000520  a9 6c 34 dc 03 65 13                              |.l4..e.|
00000527
00000378

test002

[root@test002 minio]# for i in {1..5};do hexdump -Cv /data/minio/data$i/test002/test.txt/xl.meta|tail -n 2;done
00000520  66 a7 75 97 da d3 6c                              |f.u...l| -- 数据 l
00000527
00000520  2e 3e f8 23 24 88 77                              |.>.#$.w| -- 数据 w
00000527
00000520  66 a7 75 97 da d3 6c                              |f.u...l| -- 数据 l
00000527
00000520  15 d3 29 3c d2 cc bf                              |..)<...| -- 校验
00000527
00000520  0b ae 7e 37 7e 6a 7f                              |..~7~j.| -- 校验
00000527

test003

[root@test003 minio]# for i in {1..5};do hexdump -Cv /data/minio/data$i/test002/test.txt/xl.meta|tail -n 2;done
00000520  66 a7 75 97 da d3 6c                              |f.u...l| -- 数据 l
00000527
00000520  2c 18 cc 94 98 cf 6f                              |,.....o| -- 数据 o
00000527
00000520  05 fe f5 e8 9c fc 64                              |......d| -- 数据 d
00000527
00000520  64 c6 a6 e7 d0 0c 69                              |d.....i| -- 校验 -- 因为helloworld中没有i
00000527
00000520  64 69 e4 50 ee e4 68                              |di.P..h| -- 数据
00000527

单词太少分布不均,解析的参考意义不大,单词多的话不好解析,这里得不出比较有效的结论

通过元数据结构,再看下

00000070  63 b2 53 05 9c a6 45 63  41 6c 67 6f 01 a3 45 63  |c.S...EcAlgo..Ec|
00000080  4d 0b a3 45 63 4e 04 a7  45 63 42 53 69 7a 65 d2  |M..EcN..EcBSize.|
	ErasureM           int               `json:"EcM" msg:"EcM"`                                  // Erasure data blocks
	ErasureN           int               `json:"EcN" msg:"EcN"`                                  // Erasure parity blocks

EcM EcN 为数据块和校验块数量,通过ascii表可知 EcM EcN后面0b 04转化成10进制正好为 11 4

我们还可以解析出块的序号

for i in {1..5};do hexdump -Cv /data/minio/data$i/test002/test/xl.meta|grep EcIndex;done
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 05 a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 08 a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 0b a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 0e a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 02 a6 45 63  |.....EcIndex..Ec|
for i in {1..5};do hexdump -Cv /data/minio/data$i/test002/test/xl.meta|grep EcIndex;done
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 06 a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 09 a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 0c a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 0f a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 03 a6 45 63  |.....EcIndex..Ec|
for i in {1..5};do hexdump -Cv /data/minio/data$i/test002/test/xl.meta|grep EcIndex;done
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 07 a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 0a a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 0d a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 01 a6 45 63  |.....EcIndex..Ec|
00000090  00 10 00 00 a7 45 63 49  6e 64 65 78 04 a6 45 63  |.....EcIndex..Ec|

倒数第四列 05 08 0b 0e 02 06 09 0c 0f 03 07 0a 0d 01 04 从01-0f就可以把纠删码块的序列排出来,启用版本管理的话元数据是多条在同一个文件的,会有多个EcIndex

尝试从上面数据解析道数据块和校验块,由于单词太少分布不均,解析的参考意义不大,单词多的话不好解析,先不走这条路

4.1.1.2. 结论

小文件元数据和数据存储在一起,通过纠删码算法打散,每个数据目录都存一份

4.1.2. 大文件

dd一个大文件

dd if=/dev/zero of=testbigfile bs=4m count=250

上传到minio之后查看磁盘数据

|-- data5
|   `-- test002
|       |-- testbigfile
|       |   |-- 713daa2d-4466-44bc-bb94-b55f30f361f2
|       |   |   `-- part.1
# 15个块都是91M
du -sh data5/test002/testbigfile/713daa2d-4466-44bc-bb94-b55f30f361f2/
91M	data5/test002/testbigfile/713daa2d-4466-44bc-bb94-b55f30f361f2/
15 * 91 / 1000 = 0.73

这里的纠删码算法空间利用率为0.73左右,应该是4/15 4个校验块,11个数据块,符合默认的EC4 3

4.1.2.1. 结论

大文件元数据与数据分开存储,数据分布通过纠删码块数量分配到各个数据盘,每块盘一份

4.2. 扩容

增加新的 server pool

新加server pool需要修改所有minio服务器的配置,并重启服务,只有当所有服务重启完成时minio开始提供服务

4.3. 更换硬盘/更换主机

Recover after Hardware Failure

服务无需停机

  • 更换数据盘: 卸载坏盘、格式化、挂载新盘即可
  • 更换主机: 做单机的minio配置,修改主机名启动服务即可

4.4. 推荐配置

Reference Hardware

推荐配置还蛮高的

4.5. server pool1

serverpools

一个server pool就是一个纠删码集合,一个对象只会被分布到一个server pool, 多个server pool的情况下对象会分布到使用最少的一个

4.6. io读写链路

落盘分为两步 4:

  • hash 通过对象名算hash值, 模set数目,获取到set的Index hash 算法早期版本用的是 crc 5 现在用的是 siphash 6
  • 纠删码切片分布到数据目录 7
    • 根据set中磁盘数量,算出校验块和数据块数量
    • 磁盘排序
    • 写数据

5. 参考

  1. https://blog.min.io/server-pools-streamline-storage-operations/  2

  2. https://blog.min.io/minio-versioning-metadata-deep-dive/ 

  3. https://docs.min.io/minio/baremetal/concepts/erasure-coding.html#erasure-sets 

  4. https://github.com/minio/minio/blob/master/docs/distributed/DESIGN.md 

  5. https://github.com/minio/minio/blob/890e526bdee894e303c0a4252d8625ef75715547/cmd/erasure-sets.go#L804 

  6. https://github.com/minio/minio/blob/890e526bdee894e303c0a4252d8625ef75715547/cmd/erasure-sets.go#L793 

  7. https://github.com/minio/minio/blob/890e526bdee894e303c0a4252d8625ef75715547/cmd/erasure-object.go#L730