名称定义说明:

  1. 对象存储服务:
    • 对象存储服务OSS(Object Storage Service)是一种海量、安全、低成本和高可靠的云存储服务,适合存放任意类型的文件。
    • 对象存储对打优势在于:可以存储大容量非结构化数据,比如图片、视频、日志文件、备份数据和容器/虚拟机镜像。
  1. MinIO
    • MinIO是基于Golang编写的开源对象存储套件,基于Apache License v2.0开源协议。
    • 诸多特点:高性能、可扩展、云原生、AmazonS3兼容、可对接多种后端、SDK支持、Lambda计算、功能简单、图形化界面以及支持纠删码。

1. 基础概念

  1. 存储的对象: Object; 可以存储的有很多,例如文件、字节流和anything …
  2. Drive: 存储数据的磁盘,在MinIO启动时,以参数方式传入。MinIO中所有对象数据都会存在Drive中。
  3. Set: 即一组Drive的集合,分布式部署根据集群规模自动划分一个或多个Set,每个Set中的Drive分布在不同位置。一个对象存储在一个Set上。(for example: {1…64} is divided into 4 sets each of size 16) — 这个是纠删码将文件保存多份。
    • 一个对象存放在一个Set上
    • 一个句群划分成多个set
    • 一个set包含的Drive数量是固定的,默认有系统根据集群规模自动计算得出
    • 一个Set中的Drive尽可能分布在不同节点上
  4. Bucket: 用来存储Object的逻辑空间。每个Bucket之间数据是相互隔离的。对客户端言,相当于存放文件的顶层文件夹(根目录)。

Set / Drive的关系:

Set/Drive 这两个概念是MinIO里最重要两个概念,一个对象最终是存储在Set上面的;

看下MinIO集群存储示意图,每一行是一个节点机器, 节点有一个小方块被我们称为Drive,Drive可以简单理解成是一个硬盘。

Set则表示一组Drive的集合,所有蓝色、橙色背景的Drive就组成一个Set。如图每个Set上面的Drive都是3。
image.png

一个集群包含多个 Set,每个对象最终存储在哪个 Set 上是根据对象的名称进行哈希,然后影射到唯一的 Set 上面,这个方式从理论上保证数据可以均匀的分布到所有的 Set 上。

根据的观测,数据分布的也非常均匀,一个 Set 上包含多少个 Drive 是由系统自动根据集群规模算出来的,当然,也可以自己去配置。

一个 Set 的 Drive 系统会考虑尽可能把它放在多的节点上面,保证它的可靠性。

纠删码EC (Erasure Code):

MinIO使用纠删码机制来保证高可靠性,使用highwayhash来处理数据损坏(Bit Rot Protection:位衰保护,用于校验)。关于纠删码,简单来说纠删码是一种恢复丢失和损坏数据的数学算法, Minio采用Reed-Solomon code 算法将对象拆分成N/2数据和N/2 奇偶校验块。 这就意味着如果是12块盘,一个对象会被分成6个数据块、6个奇偶校验块,你可以丢失任意6块盘(不管其是存放的数据块还是奇偶校验块)。

2. 环境搭建

1. 容器部署
  1. docker run -p 9000:9000 -p 9001:9001 --name minio \
  2. -v /etc/localtime:/etc/localtime \
  3. -v /usr/local/docker/minio/data:/data \
  4. -v /usr/local/docker/minio/config:/root/.minio \
  5. -e "MINIO_ROOT_USER=admin" \
  6. -e "MINIO_ROOT_PASSWORD=admin" \
  7. minio/minio server --console-addresses ":9001" --address ":9000" /data

OR

# Docker compose的部署方式:
version: '2'
services:
  minio:
    image: minio/minio:RELEASE.2021-08-31T05-46-54Z
    container_name: minio
    restart: always
    ports:
      - 19091:9001
      - 19090:9000
    command: server /data --console-address ":9001" --address ":9000"
    volumes:
      - /usr/local/qif/docker/minio/data:/data
      - /usr/local/qif/docker/minio/config:/root/.minio  
    environment:
      - TZ=Asia/Shanghai
      - MINIO_ROOT_USER=admin
      - MINIO_ROOT_PASSWORD=admin

【说明】:

  1. 上述的部署方式,是采用了单机版的方式,没有使用到纠删码,不涉及Set的概念。
  2. 我们目前的部署方式,也是通过启动单个容器的方式,来实现文件存储的功能。
# 单机版的 纠删码方式部署:
docker run -p 9000:9000 -p 9001:9001 --name minio \
-v /usr/local/qif/docker/minio/data/data1:/data1 \
-v /usr/local/qif/docker/minio/data/data2:/data2 \    
-v /usr/local/qif/docker/minio/data/data3:/data3 \
-v /usr/local/qif/docker/minio/data/data4:/data4 \
-v /usr/local/qif/docker/minio/data/data5:/data5 \
-v /usr/local/qif/docker/minio/data/data6:/data6 \    
-v /usr/local/qif/docker/minio/config:/root/.minio \
-e "MINIO_ROOT_USER=admin" \
-e "MINIO_ROOT_PASSWORD=admin" \
minio/minio server --console-addresses ":9001" --address ":9000"  /data{1...8}

2. 集群部署

启动分布式MinIO,只需把硬盘位置做为参数传给minIO server命令即可,然后,需要在所有其他节点运行同样命令:

  1. 分布式MinIO里所有节点需要同样的access秘钥和secret秘钥,这样这些节点才能建立连接。为实现这个目的,需要执行minIO server命令前,现将access秘钥和secret秘钥 export成环境变量。新版本使用 MINIO_ROOT_USER & MINIO_ROOT_PASSWORD
  2. 分布式MinIO使用的磁盘里必须是干净的,没有数据的
  3. 分布式MINIO的节点时间差不能超过3秒,需要使用NTP确保时间的一致性
  4. 在windows环境下,分布式MinIO仍处于试验阶段。
mino server http://host{1...n}/export{1...m}

# 案例: 启动分布式MinIO的实例
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=admin
minio server http://192.168.1.11/export1 http://192.168.1.12/export2 \
             http://192.168.1.13/export3 http://192.168.1.14/export4 \
             http://192.168.1.15/export5 http://192.168.1.16/export6 \
             http://192.168.1.17/export7 http://192.168.1.181/export8
# 启动的脚本 --伪集群
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=admin
MINIO_HOME=/usr/local/soft
MINIO_HOST=192.168.3.14
for i in {01..04}; do
    nohup ${MINIO_HOME}/minio server --address ":1090${i}" --console-address "1990${i}" 
          http://${MINIO_HOST}:9001/mnt/data01  http://${MINIO_HOST}:9002/mnt/data02
          http://${MINIO_HOST}:9003/mnt/data03  http://${MINIO_HOST}:9004/mnt/data04 > ${MINIO_HOME}/minio-90{i}.log 2>&1 &   done

# 再使用Nginx,实现loadBalancer
upstream minio {
    server 192.168.3.14:10901;
    server 192.168.3.14:10902;
    server 192.168.3.14:10903;
    server 192.168.3.14:10904;
}

upsteram console {
    ip_hash;
    server 192.168.3.14:19901;
    server 192.168.3.14:19902;
    server 192.168.3.14:19903;
    server 192.168.3.14:19904;
}

map $http_upgrade $connection_upgrade {
    default        keep-alive;  #默认为keep-alive 可以支持 一般http请求
    'websocket'    upgrade;     #如果为websocket 则为 upgrade 
}

server {
    listen 19090;
    listen[::]:19090;
    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 $remove_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Nginx-Proxy true;

        proxy_connect_timeout 300;
        pass_pass http://minio;
    }
}

docker-compose的部署方式:

# docker compose

version: '3.7'
# Settings and configurations that are common for all containers
x-minio-common: &minio-common
  image: quay.io/minio/minio:RELEASE.2022-01-08T03-11-54Z
  command: server --console-address ":9001" http://minio{1...4}/data{1...2}
  expose:
    - "9000"
    - "9001"
  environment:
    MINIO_ROOT_USER: minio
    MINIO_ROOT_PASSWORD: minio123
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
    interval: 30s
    timeout: 20s
    retries: 3

# starts 4 docker containers running minio server instances.
# using nginx reverse proxy, load balancing, you can access
# it through port 9000.
services:
  minio1:
    <<: *minio-common
    hostname: minio1
    volumes:
      - data1-1:/data1
      - data1-2:/data2

  minio2:
    <<: *minio-common
    hostname: minio2
    volumes:
      - data2-1:/data1
      - data2-2:/data2

  minio3:
    <<: *minio-common
    hostname: minio3
    volumes:
      - data3-1:/data1
      - data3-2:/data2

  minio4:
    <<: *minio-common
    hostname: minio4
    volumes:
      - data4-1:/data1
      - data4-2:/data2

  nginx:
    image: nginx:1.19.2-alpine
    hostname: nginx
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    ports:
      - "9000:9000"
      - "9001:9001"
    depends_on:
      - minio1
      - minio2
      - minio3
      - minio4

## By default this config uses default local driver,
## For custom volumes replace with volume driver configuration.
volumes:
  data1-1:
  data1-2:
  data2-1:
  data2-2:
  data3-1:
  data3-2:
  data4-1:
  data4-2:

3. minIO的部署方式:

# 在portainer中的创建单机的方式
version: '2'
services:
  minio:
    image: minio/minio:RELEASE.2021-08-31T05-46-54Z
    container_name: minio
    restart: always
    ports:
      - 19091:9001
      - 19090:9000
    command: server /data --console-address ":9001" --address ":9000"
    volumes:
      - /usr/local/qif/docker/minio/data:/data
      - /usr/local/qif/docker/minio/config:/root/.minio  
    environment:
      - TZ=Asia/Shanghai           #  当前时间段
      - MINIO_ROOT_USER=admin      #  访问用户名
      - MINIO_ROOT_PASSWORD=admin  # 访问密码
    networks:
      - custom_net
networks:
  custom_net:
    external:
      name: yours_network

参考文档:

  1. https://blog.csdn.net/crazymakercircle/article/details/120855464
  2. https://raw.githubusercontent.com/minio/minio/master/docs/orchestration/docker-compose/docker-compose.yaml