分布式文件系统 Minio 实战

温馨提醒

分布式文件系统应用场景

互联网海量非结构化数据的存储需求

  • 电商网站:海量商品图片
  • 视频网站:海量视频文件
  • 网盘:海量文件
  • 社交网站:海量图片

Minio 介绍

Minio 是一个基于 Apache License v2.0 开源协议的对象存储服务。它兼容 AWS S3 云存储服务接口,非常适合存储大容量非结构化的数据,如图片、视频、日志文件、备份数据等,而一个对象文件可以是任意大小,从几 kb 到最大 5T 不等。

Minio 是一个非常轻量的服务,可以很简单的和其他应用结合。

官网:https://minio.io

中文官网:https://www.minio.org.cn

对象存储服务(OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件,容量和处理能力弹性扩展。

在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等9000多家企业都在使用 Minio。

Minio 优点

  • 部署简单:一个二进制文件即是一切,还支持各种平台;
  • 支持海量存储:支持单个对象最大 5TB;
  • 兼容Amazon S3 接口
  • 低冗余且磁盘损坏高容忍:标准且最高的数据冗余系数为2(即存储一个 1M 的数据对象,实际占用的磁盘空间为 2M),但在任意 n/2 块磁盘损坏的情况下依然可以读取数据(n 为一个纠删码集合中的磁盘数量)并且这种损坏恢复是基于单个对象的,而不是基于整个存储卷的
  • 读写性能优异

Minio 的基本概念

  • Oject:存储到 minio 的基本对象
  • Bucket:用来存储 Object 的逻辑空间,每个 bucket 之间的数据是相互隔离的
  • Drive:存储数据的磁盘,在 minio 启动时,以参数的方式传入
  • Set:一组 Drive 的集合,分布式部署根据集群规模自动划分一个或多个 Set,每个 Set 中的 Drive 分布在不同的位置,一个对象存储在一个 Set 上。
    • 一个对象存储在一个 Set 上
    • 一个集群划分为多个 Set
    • 一个 Set 包含的 Drive 数量是固定的,默认由系统根据集群规模自动计算得出
    • 一个 Set 中的 Drive 尽可能分布在不同的节点上

纠删码 EC

Minio 使用纠删码机制来保证高可靠性,使用 highwayhash 来处理数据损坏(Bit Rot Protection)。简单来说就是通过数学计算,把丢失的数据进行还原,它可以将 n 份原始数据,增加 m 份数据,并能通过 n+m 份中的任意 n 份数据,还原为原始数据,即如果有任意小于等于 m 份的数据失效,仍然能通过剩下的数据还原出来。

存储形式

文件对象上传到 minio,会在对应的数据存储磁盘中,以 Bucket 名称为目录名,文件名称为下一级目录,文件名下是 part.1 和 xl.meta,前者是编码数据块及校验块,后者是元数据文件

Minio 环境搭建

官方文档:https://docs.min.io/docs/

中文文档:http://docs.minio.org.cn/docs/

1
2
3
4
5
6
Minio 默认9000端口,在配置文件中加入 -address "127.0.0.1:9029" 可更改端口;
MINIO_ACCESS_KEY:用户名,长度最小为5个字符
MINIO_SECRET_KEY:密码,不能设置过于简单,长度最小为8个字符
-config-dir:指定集群配置文件目录
-address:api的端口,默认是9000
--console-address:web端口,默认随机,可以通过 --console-address ":PORT" 来指定静态端口

单机部署

minio server 的 standalone 模式,即要管理的磁盘都在 host 本地,该启动模式一般用于实验环境学习使用,在 standalone 模式下,还可以分为 non-erasure code mode 和 erasure code mode。

  • non-erasure code mode:在此启动模式下,对于每一份对象数据,minio 直接在 data 目录下存储这份数据,不会建立副本,也不会启用纠删码机制,因此,这种模式无论是服务实例还是磁盘都是单点,无任何高可用保障,磁盘损坏就表示数据丢失。
  • erasure code mode:此模式为 minio server 实例传入多个本地磁盘参数,一旦遇到多于一个磁盘参数,minio server 会自动启用 erasure code mode。erasure code 对磁盘的个数是有要求的,如不满足要求,实例启动将失败。erasure code启用后,要求传给 minio server 的磁盘个数至少为 4 个。

基于Centos 7 部署

1
2
3
4
5
6
7
8
9
# 默认用户名和密码:minioadmin/minioadmin,修改默认用户名和密码:
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=123456789

# 默认的配置目录是${HOME}/.minio,可以通过 --config-dir 命令自定义配置目录:
./minio server --config-dir /mnt/config /mnt/data

# 控制台监听端口是动态生成的,可以通过 --console-address ":PORT" 来指定静态端口
./minio server --console-address ":50000" /mnt/data

基于 Docker 部署

1
2
3
4
5
6
7
8
# 启动后,浏览器无法访问控制台,因为没有对外暴露控制台端口
docker run -p 9000:9000 --name minio -v /mnt/data:/data -v /mnt/config:/root/.minio minio/minio server /data

# 对外暴露控制台端口,通过 --console-address ":50000" 指定控制台端口,默认用户名和密码:minioadmin/minioadmin
docker run -d -p 9000:9000 -p 50000:50000 --name minio -v /mnt/data:/data -v /mnt/config:/root/.minio minio/minio server --console-address ":50000" /data

# 自定义用户名密码
docker run -d -p 9000:9000 -p 50000:50000 --name minio -e "MINIO_ROOT_USER=admin" -e "MINIO_ROOT_PASSWORD=123456789" -v /mnt/data:/data -v /mnt/config:/root/.minio minio/minio server --console-address ":50000" /data

纠删码模式

minio 使用纠删码 erasure code 和校验和 check sum 来保护数据免受硬件故障和数据损坏,即使丢失一半数量(n/2)的硬盘,仍然可以恢复数据。

纠删码是一种恢复丢失和损坏数据的数学算法,Minio 采用 Reed-Solomon code 将对象拆分成 n/2 数据和 n/2 奇偶检验块,这就意味着如果是 12 块盘,一个对象会被分成6个数据块、6个奇偶校验块,可以丢失任意6块盘(不管是存放的数据块还是奇偶校验块),仍可以从剩下的盘中的数据进行恢复。

使用 Minio Docker 镜像,在8块盘中启动 Minio 服务:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
docker run -d -p 9000:9000 -p 50000:50000 --name minio \
-e "MINIO_ROOT_USER=admin" \
-e "MINIO_ROOT_PASSWORD=123456789" \
-v /mnt/data1:/data1 \
-v /mnt/data2:/data2 \
-v /mnt/data3:/data3 \
-v /mnt/data4:/data4 \
-v /mnt/data5:/data5 \
-v /mnt/data6:/data6 \
-v /mnt/data7:/data7 \
-v /mnt/data8:/data8 \
minio/minio server /data{1...8} --console-address ":50000"

分布式集群部署

分布式 minio 可以让你将多块磁盘(可以在不同的机器上)组成一个对象存储服务,由于硬盘分布在不同的节点上,分布式 minio 避免了单点故障。

分布式 Minio 优势

  • 数据保护

    分布式 Minio 采用纠删码来防范多个节点宕机和位衰减 bit rot。

    分布式 Minio 至少需要4块硬盘,使用分布式 Minio 自动引入了纠删码功能。

  • 高可用

    单机 Minio 服务存在单点故障,如果一个有 N 块硬盘的分布式 Minio,只要有 N/2 硬盘在线,数据就是安全的,不过需要至少 N/2+1 块硬盘来创建新的对象。

    如:一个16节点的 Minio 集群,每个节点16块硬盘,就算有8个节点宕机,这个集群仍然是可读的,不过需要9个节点才能写数据。

  • 一致性

    Minio 在分布式和单机模式下,所有读写操作都严格遵守 read-after-write 一致性模型。

部署分布式 Minio

运行一个分布式 Minio 实例,只需要把硬盘位置做为参数传给 Minio server 命令即可,然后,需要在所有其他节点运行同样的命令。
  • 分布式 Minio 里所有的节点都需要有同样的 access 秘钥和 secret 秘钥,这样这些节点才能建立联接,新版本使用 MINIO_ROOT_USER 和 MINIO_ROOT_PASSWORD。
  • 分布式 Minio 使用的磁盘必须是干净的,里面没有任何数据。
  • 分布式 Minio 里的节点时间相差不能超过3秒。
1个节点,4块硬盘
  • 挂载磁盘

    1
    2
    3
    4
    
    /dev/sdb1                 20G   33M   20G   1% /data/minio01
    /dev/sdc1                 20G   33M   20G   1% /data/minio02
    /dev/sdd1                 20G   33M   20G   1% /data/minio03
    /dev/sde1                 20G   33M   20G   1% /data/minio04
  • 创建supervisor配置文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    vim /etc/supervisord.d/minio01.ini
    
    [program:minio01]
    environment = MINIO_ROOT_USER=minioadmin,MINIO_ROOT_PASSWORD=minioadmin
    command=/usr/local/bin/minio server --address 0.0.0.0:9001 --console-address 0.0.0.0:19001 --config-dir /etc/minio01 http://192.168.200.179:9001/data/minio01 http://192.168.200.179:9002/data/minio02 http://192.168.200.179:9003/data/minio03 http://192.168.200.179:9004/data/minio04
    autostart=true
    startsecs=10
    autorestart=true
    startretries=3
    user=root
    priority=999
    redirect_stderr=true
    stdout_logfile_maxbytes=20MB
    stdout_logfile_backups=20
    stdout_logfile=/data/logs/stdout.log
    stopasgroup=false
    killasgroup=false
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    vim /etc/supervisord.d/minio02.ini
    
    [program:minio02]
    environment = MINIO_ROOT_USER=minioadmin,MINIO_ROOT_PASSWORD=minioadmin
    command=/usr/local/bin/minio server --address 0.0.0.0:9002 --console-address 0.0.0.0:29001 --config-dir /etc/minio02 http://192.168.200.179:9001/data/minio01 http://192.168.200.179:9002/data/minio02 http://192.168.200.179:9003/data/minio03 http://192.168.200.179:9004/data/minio04
    autostart=true
    startsecs=10
    autorestart=true
    startretries=3
    user=root
    priority=999
    redirect_stderr=true
    stdout_logfile_maxbytes=20MB
    stdout_logfile_backups=20
    stdout_logfile=/data/logs/stdout.log
    stopasgroup=false
    killasgroup=false
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    vim /etc/supervisord.d/minio03.ini
    
    [program:minio03]
    environment = MINIO_ROOT_USER=minioadmin,MINIO_ROOT_PASSWORD=minioadmin
    command=/usr/local/bin/minio server --address 0.0.0.0:9003 --console-address 0.0.0.0:39001 --config-dir /etc/minio03 http://192.168.200.179:9001/data/minio01 http://192.168.200.179:9002/data/minio02 http://192.168.200.179:9003/data/minio03 http://192.168.200.179:9004/data/minio04
    autostart=true
    startsecs=10
    autorestart=true
    startretries=3
    user=root
    priority=999
    redirect_stderr=true
    stdout_logfile_maxbytes=20MB
    stdout_logfile_backups=20
    stdout_logfile=/data/logs/stdout.log
    stopasgroup=false
    killasgroup=false
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    vim /etc/supervisord.d/minio04.ini
    
    [program:minio04]
    environment = MINIO_ROOT_USER=minioadmin,MINIO_ROOT_PASSWORD=minioadmin
    command=/usr/local/bin/minio server --address 0.0.0.0:9004 --console-address 0.0.0.0:49001 --config-dir /etc/minio04 http://192.168.200.179:9001/data/minio01 http://192.168.200.179:9002/data/minio02 http://192.168.200.179:9003/data/minio03 http://192.168.200.179:9004/data/minio04
    autostart=true
    startsecs=10
    autorestart=true
    startretries=3
    user=root
    priority=999
    redirect_stderr=true
    stdout_logfile_maxbytes=20MB
    stdout_logfile_backups=20
    stdout_logfile=/data/logs/stdout.log
    stopasgroup=false
    killasgroup=false
4个节点,每个节点1块硬盘
启动分布式 Minio 实例,4个节点,每个节点1块硬盘,需要在4个节点上都运行下面的命令:
  • 挂载磁盘

    1
    
    mount /dev/sdb1 /data
  • 配置所有节点时钟同步

    1
    
    ntpdate ntp.aliyun.com
  • 创建 supervisor 启动文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    vim /etc/supervisord.d/minio.ini
    
    [program:minio]
    environment = MINIO_ROOT_USER=minioadmin,MINIO_ROOT_PASSWORD=minioadmin
    command=/usr/local/bin/minio server --address 0.0.0.0:9000 --console-address 0.0.0.0:9001 --config-dir /etc/minio http://192.168.200.178:9000/data http://192.168.200.179:9000/data http://192.168.200.180:9000/data http://192.168.200.181:9000/data
    autostart=true
    startsecs=10
    autorestart=true
    startretries=3
    user=root
    priority=999
    redirect_stderr=true
    stdout_logfile_maxbytes=20MB
    stdout_logfile_backups=20
    stdout_logfile=/data/logs/stdout.log
    stopasgroup=false
    killasgroup=false
扩展现有的分布式集群

例如我们是通过分区的方式启动 Minio 集群,命令如下:

1
2
3
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=123456789
minio server http://host{1...32}/data{1...32}

Minio 支持通过命令,指定新的集群来扩展现有集群(纠删码模式),命令如下:

1
2
3
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=123456789
minio server http://host{1...32}/data{1...32} http://host{33...64}/data{1...32}

现在整个集群就扩展了1024块磁盘,总磁盘变成了2048个,新的对象上传请求会自动分配到最少使用的集群上,通过以上扩展策略,就可以按需要扩展集群。重新配置后重启集群,会立即在集群中生效,对现有集群无影响。如上命令中,可以把原来的集群看作是一个区,新增的集群看作另一个区,新对象按每个区域中的可用空间比例放置在区域中,在每个区域内,基于确定性哈希算法确定位置。

说明:添加的每个区域必须具有与原始区域相同的磁盘数量大小,以便维持相同的数据冗余。例如,第一个区有8块磁盘,可以将集群扩展为16个、32个或1024个磁盘的区域,只需要确保部署的 SLA 是原始区域的倍数即可。

基于 docker-compose部署
4个节点,每个节点一块硬盘
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: "3.7"
services:
  minio:
    image: minio/minio:RELEASE.2021-11-09T03-21-45Z
    command: server --address ":9001" --console-address ":50001" http://minio0{1...4}/data
    restart: always
    hostname: minio01
    container_name: minio01
    environment:
      MINIO_ROOT_USER: admin
      MINIO_ROOT_PASSWORD: jzzx123456
      TZ: Asia/Shanghai
    extra_hosts:
      - "minio01:172.16.20.233"
      - "minio02:172.16.20.234"
      - "minio03:172.16.20.235"
      - "minio04:172.16.20.236"
    ports:
      - 9001:9001
      - 50001:50001
    volumes:
      - /data:/data
    network_mode: "host"
基于 Nginx 实现负载均衡
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
upstream minio_api {
    server 192.168.1.10:9001;
    server 192.168.1.11:9001;
    server 192.168.1.12:9001;
    server 192.168.1.13:9001;
}

upstream minio_console {
	server 192.168.1.10:50001;
	server 192.168.1.11:50001;
	server 192.168.1.12:50001;
	server 192.168.1.13:50001;
}

server {
    listen	19001;
    server_name localhost;
    
    ignore_invalid_headers off;
    client_max_body_size 0;
    proxy_buffering 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_connect_timeout 300;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        chunked_transfer_encoding off;
        proxy_ignore_client_abort on;
        proxy_pass http://minio_api;
    }
}

server {
    listen	15000;
    server_name localhost;
    
    ignore_invalid_headers off;
    client_max_body_size 0;
    proxy_buffering 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_connect_timeout 300;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        chunked_transfer_encoding off;
        proxy_ignore_client_abort on;
        proxy_pass http://minio_console;
    }
}

S3客户端使用

Minio Client(mc)

  • 命令

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    
    ls			# 列出文件或目录
    mb			# 创建一个桶
    cat			# 显示文件和对象内容
    pipe		# 将一个 STDIN 重定向到一个对象或文件或 STDOUT
    share		# 生成用于共享的 URL
    cp			# 拷贝文件或对象
    mirror		# 给桶做镜像
    find		# 查找文件
    diff		# 比较两个文件或桶的差异
    rm			# 删除文件或对象
    events		# 管理对象通知
    watch		# 监视文件或对象事件
    policy		# 管理访问策略
    config		# 管理 mc 配置文件
    update		# 检查软件更新
    version		# 查看版本信息
  • 配置 mc

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    mc 将所有的配置信息都存储在 ~/.mc/config.json 文件中
    
    # 查看 mc host 配置
    mc config host ls
    
    # 添加 minio 服务
    mc config host add minio-server http://192.168.1.10:9001 admin 123456789		# 配置 api 接口
    
    # 删除 host
    mc config host remove minio-server
  • 上传下载文件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    # 查询所有的桶
    mc ls minio-server
    
    # 下载文件
    mc cp minio-server/test/1.jpg /tmp
    
    # 删除文件
    mc rm minio-server/test/1.jpg 
    
    # 上传文件
    mc cp 2.jpg minio-server/test/
  • Bucket 管理

    1
    2
    3
    4
    5
    
    # 创建 Bucket
    mc mb minio-server/bucket01
    
    # 删除 Bucket(如果 Bucket 不为空,使用 --force 强制删除)
    mc rb --force minio-server/bucket01
  • mc admin 使用

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    
    mc 提供了 admin 子命令来对 minio 部署执行管理任务
    
    service			# 管理 minio 服务
    update			# 更新 minio 服务
    info			# 显示 minio 服务器信息
    user			# 管理用户
    group			# 管理组
    policy			# 管理策略
    config			# 管理 minio 服务器配置
    heal			# 修复 minio 服务器上的磁盘、桶或对象
    profile
    top				# 查看 minio 的统计信息
    trace			# 显示 minio 的http 跟踪信息
    console			# 显示 minio 控制台日志
    prometheus		# 管理 prometheus 配置
    kms
  • 用户管理

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    # 创建用户
    mc admin user add minio-server test01
    mc admin user add minio-server test02 123456789
    
    # 查看用户
    mc admin user list minio-server
    
    # 禁用用户
    mc admin user disable minio-server test01
    
    # 启用用户
    mc admin user enable minio-server test01
    
    # 查看用户信息
    mc admin user info minio-server test01
    
    # 删除用户
    mc admin user remove minio-server test01
  • 策略管理

    1
    2
    3
    4
    5
    6
    7
    
    policy 命令用于添加、删除、列出策略
    
    # 列出 minio 上的所有固定策略
    mc admin policy list minio-server
    
    # 查看 policy 信息
    mc admin policy info minio-server readwrite