初识对象存储MinIO
## 基于minIO建立对象存储服务
搭建高可用集群
探索横向扩展可行性
影响性能的关键点和基础性能测试结果
培训minio的数据可靠性解决方案、基本使用方法
承接内部离线镜像、yum源、python源,前端流水线更新
调研harbor、nexus是否可以对接s3对象存储(解决无共享存储环境下的数据可靠性问题)
目录
[MinIO简介](#MinIO简介)
[产品特点](#产品特点)
[高级特性](#高级特性)
[存储机制](#存储机制)
[运行模式](#运行模式)
[mc配置与管理](#mc配置与管理)
[应用场景](#应用场景)
[性能测试](#性能测试)
[优势和不足](#优势和不足)
1. ### MinIO简介
MinIO是一个基于Apache License v2.0开源协议的高性能对象存储服务。它兼容亚马逊S3云存储服务接口,单个对象的最大可达5TB,适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等。
2. ### 产品特点
* 云原生:容器化、基于K8S的编排、`多租户`支持。
* 高性能:作为高性能对象存储,在标准硬件条件下它能达到183GB/s的读、171GB/s的写速率。
* 高度可用:Minio服务器可以容忍分布式设置中高达`(N/2)-1`个节点故障。而且,您可以配置Minio服务器在Minio与任意Amazon S3兼容服务器之间存储数据。
* 可扩容:不同MinIO集群可以组成`联邦`,并形成一个全局的`命名空间`,并跨越多个数据中心。
* Amazon S3兼容:Minio使用Amazon S3 v2/v4 API。可以使用Minio SDK,Minio Client,AWS SDK和AWS CLI访问Minio服务器。
* 可对接后端存储:除了Minio自己的文件系统,还支持DAS、 JBODs、NAS、Google云存储和Azure Blob存储。
* Lambda计算:Minio服务器通过其兼容AWS SNS/SQS的`事件通知`服务触发Lambda功能。支持的目标是消息队列,如Kafka,NATS,AMQP,MQTT,Webhooks以及Elasticsearch,Redis,Postgres和MySQL等数据库。
* Minio提供有操作页面。
* 功能简单: 这一设计原则让MinIO不容易出错、更快启动。
* 部署简单:只有一个可执行文件,参数极少。部署非常简单。如只需要一条命令:minio server /data,即可启动一个MinIO系统。
* 无元数据数据库:避免元数据库成为整个系统的性能瓶颈,并将故障限制在单个集群之内,而不会涉及其他集群。
* 精细化修复:修复操作可以精细化到`单个对象`。
* S3 Select支持:对于超大的对象,可通过`执行SQL语句`以加速人工智能与大数据分析处理。
* 多语言客户端支持:提供JavaScript、Java、Python、Golang、.Net、Haskell多种语言的客户端开发SDK。
* 服务器端操作系统:Linux, Unix, Windows, Max OS等主流操作系统。
* 性能极其优异:在开源对象存储软件中,性能非常优异。
3. ### 高级特性
* 支持纠删码:针对CPU进行汇编级优化后的纠删码`保护每一个对象`。
* 比特位保护:用户未知的情况下的`静默错误/比特位衰减`是磁盘的一个严重的问题。MinIO使用高度优化的`HighwayHash算法`保证从不读到错误的数据。MinIO使用纠删码、Checksum来`防止硬件错误和静默数据污染`。在最高冗余度配置下,即使丢失1/2的磁盘也能恢复数据。
* 加密和防篡改:Minio为加密数据`提供了机密性,完整性和真实性保证`,而且性能开销微乎其微。使用AES-256-GCM,ChaCha20-Poly1305和AES-CBC支持服务器端和客户端加密。加密的对象使用AEAD服务器端加密进行防篡改。支持HashiCorp的秘钥管理解决方案。
* 单写多读(worm):该特性一旦开启,MinIO将`禁止可能改变`对象数据、元数据的所有API。
* 持续备份:支持快速增量备份到NAS、公有云等。
* 多云网关:可以做为多种公有云、NAS设置的网关,对外提供S3访问。
* 用户身份管理:支持与OpenID connect规范,支持临时密码,支持`高度细化的、可配置的`访问策略。
4. ### 存储机制
Minio使用纠删码erasure code和校验和checksum。即便丢失一半数量`(N/2)`的硬盘,仍然可以恢复数据。
校验和
保护数据免受硬件故障和无声数据损坏
纠删码
纠删码是一种`恢复丢失和损坏数据`的数学算法,目前,纠删码技术在分布式存储系统中的应用主要有三类,`阵列纠删码`(Array Code: RAID5、RAID6等)、`RS(Reed-Solomon)里德-所罗门类`纠删码和`LDPC`(LowDensity Parity Check Code)低密度奇偶校验纠删码。Erasure Code是一种编码技术,它可以将n份原始数据,`增加m份数据`,并能通过n+m份中的任意n份数据,还原为原始数据。即如果有任意小于等于m份的数据失效,仍然能通过剩下的数据还原出来。
Minio采用`Reed-Solomon code`将对象拆分成`N/2数据和N/2奇偶校验块`。这就意味着如果是12块盘,一个对象会被分成6个数据块、6个奇偶校验块,可以丢失任意6块盘(不管其是存放的数据块还是奇偶校验块),仍可以从剩下的盘中的数据进行恢复。
RS code编码数据恢复原理
RS编码`以word为编码和解码单位`,大的数据块拆分到字长为w(取值一般为8或者16位)的word,然后对word进行编解码。 数据块的编码原理与word编码原理相同,后文中以word为例说明,变量Di, Ci将代表一个word。
把输入数据视为向量D=(D1,D2,..., Dn), 编码后数据视为向量(D1, D2,..., Dn, C1, C2,.., Cm),RS编码可视为如下(图1)所示矩阵运算。
图1最左边是编码矩阵(或称为`生成矩阵`、分布矩阵,Distribution Matrix),编码矩阵需要满足任意n*n子矩阵可逆。为方便数据存储,编码矩阵上部是单位矩阵(n行n列),下部是m行n列矩阵。下部矩阵可以选择`范德蒙德矩阵`或柯西矩阵。

RS最多能`容忍m个数据块`被删除。 数据恢复的过程如下:
(1)假设D1、D4、C2丢失,从编码矩阵中删掉丢失的数据块/编码块对应的行。(图2、3)
(2)由于B' 是`可逆的`,记B'的逆矩阵为 (B'^-1),则B' * (B'^-1) = I 单位矩阵。两边左乘B' 逆矩阵。 (图4、5)
(3)得到如下原始数据D的计算公式 。

(4)对D重新编码,可得到丢失的编码
5. ### 运行模式
MinIO有server和gateway两种运行模式,前者`适用于有自己的硬盘等`存储硬件设备的情况,后者可以理解为`代理模式`,目前可以代理Azure、GCS、NAS、S3以及其它兼容S3的OSS服务商。
代理模式下,MinIO对外部请求`进行解析和转发`至被代理方(比如阿里云OSS),间接提供存储服务。当然,MinIO不只是做了请求转发,还提供了多种额外的功能,比如`文件缓存、服务监控`等。
#### minio server启动模式
minio支持多种server启动模式:

图:minio server启动模式
minio server的单机模式,要管理的磁盘都在host本地。该启动模式一般仅用于实验环境、测试环境的验证和学习使用。在单机模式下,还可以分为`非纠删码模式`和`纠删码模式`。
非纠删码模式,minio server启动时`仅传入一个本地磁盘`目录参数:
```
$ ./minio server data
```
在这样的启动模式下,对于每一份对象数据,minio直接在data下面存储这份数据,不会建立副本,也不会启用纠删码机制。因此,这种模式无论是服务实例还是磁盘都是“单点”,无任何高可用保障,磁盘损坏就表示数据丢失。
同样在minio server的单机模式下,`纠删码模式`即为minio server实例传入多个本地磁盘参数。一旦遇到多于一个磁盘参数,minio server会自动启用纠删码模式。纠删码模式对磁盘的个数是有要求的,如不满足要求,实例启动将失败:
```
$ ./minio server data1 data2
ERROR Invalid command line arguments: Incorrect number of endpoints provided [data1 data2]
> Please provide an even number of endpoints greater or equal to 4
HINT:
For more information, please refer to https://docs.min.io/docs/minio-erasure-code-quickstart-guide
```
纠删码启用后,要求传给minio server的endpoint(单点模式下,即本地磁盘上的目录)`至少为4个`。minio server启用纠删码机制后,会自动将传入的disk drive划分为多个erasure coding set,每个erasure coding set中的disk drive的数量可以是:4, 6, 8, 10, 12, 14 和16。minio server会根据传入disk drive的数量自动计算set个数和每个set中的disk drive数量。比如下面例子中,我们传入四个endpoint(disk drive)给minio server:
```
$ ./minio server data1 data2 data3 data4
Formatting 1 zone, 1 set(s), 4 drives per set.
WARNING: Host local has more than 2 drives of set. A host failure will result in data becoming unavailable.
Status: 4 Online, 0 Offline.
... ...
```
从minio server的输出日志来看,minio server将这些drive放入了一个 erasure coding set 了。在输出日志中,我们还看到一行WARNING: Host local has more than 2 drives of set. A host failure will result in data becoming unavailable. ,即minio server警告我们:这个erasure coding set中有多于两个的drive都在local host上,这样一旦host宕机,那么数据将无法获取。(每个set 有4个drive,根据纠删码的机制,这个set的最大允许失效的disk数量为4/2=2)。
我们再来看minio server启动的一个 “语法糖” – “省略号”语法:
```
$ ./minio server data{1...18}
Formatting 1 zone, 3 set(s), 6 drives per set.
WARNING: Host local has more than 3 drives of set. A host failure will result in data becoming unavailable.
WARNING: Host local has more than 3 drives of set. A host failure will result in data becoming unavailable.
WARNING: Host local has more than 3 drives of set. A host failure will result in data becoming unavailable.
Status: 18 Online, 0 Offline.
... ...
```
minio server data{1...18} 等价于 minio server data1 data2 data3 data4 data5 data6 data7 data8 data9 data10 data11 data 12 data13 data14 data15 data16 data17 data18 。minio server会自行扩展省略号代表的内容。我们看到:当我们传入18个disk drive后,minio server创建了3个erasure coding set,每个set中有6个disk drive。同样,minio server还针对每个set输出了一行WARNING:每个Set中有三个以上的disk drive都位于同一台host上。
这些WARNING我们可以通过`distributed mode`来解决。顾名思义,distributed mode下,minio server实例和其管理的disk drive分布在多台host上,这种模式可以避免minio server实例单点,数据也将分布在不同host上的不同disk中,`实现了高可用`,提升了整体的`容灾能`力。由于处理多个host上的disk,distribute mode默认就会启动erasure coding set机制。
在distributed mode下,minio server后面的远程的endpoint采用http url编码格式:
```
export MINIO_ACCESS_KEY=<ACCESS_KEY>
export MINIO_SECRET_KEY=<SECRET_KEY>
$ minio server http://host{1...4}:9000/minio/data{1...4}
```
上面例子中的minio server命令相当于4个host,每个host上启动一个minio server实例,每个实例都管理16个disk drive(包括本地和远程的)。上述命令等价于:
```
$ minio server http://host1:9000/minio/data1 http://host1:9000/minio/data2 http://host1:9000/minio/data3 http://host1:9000/minio/data4 http://host2:9000/minio/data1 http://host2:9000/minio/data2 http://host2:9000/minio/data3 http://host2:9000/minio/data4 http://host3:9000/minio/data1 http://host3:9000/minio/data2 http://host3:9000/minio/data3 http://host3:9000/minio/data4 http://host4:9000/minio/data1 http://host4:9000/minio/data2 http://host4:9000/minio/data3 http://host4:9000/minio/data4
```
minio同样会自动将这些disk drive划分为若干个erasure coding set。每个endpoint用http://address/disk-drive-path的形式编码。注意:这条命令在host1、host2、host3和host4上都要执行。
minio有一个`zone`的概念,比如下面这个例子:
```
$minio server data{1...8} data{9...16}
Formatting 1 zone, 1 set(s), 8 drives per set.
WARNING: Host local has more than 4 drives of set. A host failure will result in data becoming unavailable.
Formatting 2 zone, 1 set(s), 8 drives per set.
WARNING: Host local has more than 4 drives of set. A host failure will result in data becoming unavailable.
Status: 16 Online, 0 Offline.
... ...
```
我们在命令行中给minio server传入两组采用“省略号”语法的参数,minio认为每组就是一个“zone”,这里有两组,因此minio创建了两个zone 。在每个zone内,minio创建了一个 erasure coding set ,每个set中有8个disk drive。对于外部的写数据请求,minio server会首先查找可用空间多的zone,然后再在zone内选择set和disk drive。
如果不用“省略号”语法,那么minio server会将后面传入的所有disk drive放入一个zone中。
分布式的Minio的优势:
• 数据保护: 采用`纠错码erasure code`防止多节点或者驱动器异常,采用bit rot来进行数据保护。一个分布式的Minio集群最小需要4块盘(其实是纠错码要求最小4块)来驱动整个集群,当我们启动分布式集群后,纠错码会自动启动。
• 高可用: `多节点组成`的分布式minio可保证服务的高可用(一个N节点的分布式Minio,只要有N/2节点在线,你的数据就是安全的。不过你需要至少有N/2+1个节点才能创建新的对象。)
• 一致性保障: MinIO在所有的IO操作中都严格遵循read‐after‐write和list‐after‐write`一致性模型`。
#### minio gateway启动模式
MinIO网关使用NAS存储支持Amazon S3。你可以在`同一个共享NAS卷上`运行多个minio实例,作为一个分布式的对象网关。
为NAS存储运行MinIO网关
```
export MINIO_ACCESS_KEY=minioaccesskey
export MINIO_SECRET_KEY=miniosecretkey
minio gateway nas /shared/nasvol
```
使用mc进行验证
```
mc config host add mynas http://gateway-ip:9000 access_key secret_key
```
列举nas上的存储桶
```
mc ls mynas
```
6. ### mc配置与管理
minio官方提供了mc命令行工具,用于对minio server进行管理。我们首先要为mc创建一个管理本地minio server(:9000)的配置:
```
# mc config host add myminio http://localhost:9000 minioadmin minioadmin
Added `myminio` successfully.
```
这里我们使用mc添加了一个所谓”host”,指向上面创建的minio server(:9000)。上面的命令实质上是在~/.mc/config.json中写入了如下配置:
```
# cat ~/.mc/config.json
{
"version": "9",
"hosts": {
"myminio": {
"url": "http://localhost:9000",
"accessKey": "minioadmin",
"secretKey": "minioadmin",
"api": "s3v4",
"lookup": "auto"
}
}
}
```
#### 查看bucket
```
# 查看minio集群中的bucket
$ mc ls minio
```
```
# 查看bucket的内容
$ mc ls minio/test1
```
#### bucket管理
```
# 创建一个bucket
$ mc mb minio/test2
```
Bucket created successfully `minio/test2`.
```
$ mc ls minio/ | grep test2
```
```
# rb可以直接删除指定的bucket
$ mc rb minio/test2
```
Removed `minio/test2` successfully.
```
# tree可以打印出来bucket组织的文件系统树形结构
$ mc tree ‐‐depth 2 ‐‐files minio/test2
```
minio/test2
└─ hostname.txt
```
# du可以查看某个bucket或者object的大小
$ mc du minio/test2
```
```
$ mc du minio/
```
#### 对象管理
```
# 将本地文件拷贝到minio的oss服务
# 并直接使用cat命令访问
$ hostname > hostname.txt
$ mc cp hostname.txt minio/test2/
```
```
$ mc ls minio/test2/
```
```
$ mc cat minio/test2/hostname.txt
```
```
# 使用pipe命令可以将标准输入的数据直接写入到minio的存储中
$ echo ${PATH} | mc pipe minio/test2/path.txt
$ mc ls minio/test2/
```
```
$ mc cat minio/test2/path.txt
```
```
# 受用share命令生成可供外部匿名下载的临时链接地址
# 生成后我们就可以使用共享链接在4小时内随意下载
$ mc share download ‐‐expire 4h minio/test2/hostname.txt
```
```
# 使用mirror指令对bucket内容进行镜像(最实用的一个指令)
# 将minio这个对象服务下的test2的整个bucket的对象镜像到本地
# 使用minio的mc客户端可以在多个minio服务之间进行数据镜像
$ mc mirror minio/test2 .
```
```
# 使用find指令来直接查找内容(相对比较实用,find指令支持很多方便快捷的参数,和Linux本地的find命令内容相似)
# 查找名称为*.txt的文件并打印临时url下载地址
$ mc find minio/test2/ ‐‐name "*.txt" ‐‐print {url}
```
```
# diff命令可以列出两个bucket之间对象的大小,名字,时间的不同
$ mc diff . minio/test2/
```
```
# rm可以直接删除指定的对象(‐‐force ‐‐recursive就相当于我们linux中的rm ‐rf)
$ mc rm ‐‐force ‐‐recursive minio/test2
```
#### minio运维管理
```
# stat可以查看minio服务的元数据信息
$ mc stat minio/test2
```
```
# retention指令可以设置指定前缀的对象的保留时间
# events指令可以查看和添加对象的事件
# watch可以实时监听对象的events
# policy用来管理匿名用户对bucket和object的访问
# 设置test2这个bucket匿名用户仅可以下载(download/public/upload)
$ mc policy set download minio/test2
$ mc policy list minio/test2
```
```
# admin用来管理minio服务
# mc admin info 查看minio服务基本信息
# mc admin service 重启和停止minio服务
# mc admin config 管理minio服务的配置信息
$ mc admin info minio
```
```
# config 用来管理客户端的配置文件(还记得我们刚开始配置本地环境的时候吗)
# minio默认帮我们配置了一些公共的对象存储服务,同时也配置了一个本地的oss服务
$ mc config host list
```
7. ### 应用场景
基于minIO建立对象存储服务 应用场景:
承接内部离线镜像、yum源、python源,前端流水线更新;
内部安装docker,存放镜像的仓库需要用到minIO;
nexus仓库使用minIO;
制品库使用minIO;
命令行下载应用,存放应用使用minIO;
主机驱动的存放;
harbor镜像仓库使用minIO;
etcd的自动备份机制;
流水线制品和日志的持久化。
提供minIO对象存储服务的进度:
- [x] 在研发测试区业务集群(acp-region)部署单节点minIO服务,已完成。
- [x] 单节点minIO服务在离线环境下可重复创建,已完成。
- [x] docker registry存储使用minIO,已完成。
- [ ] harbor镜像仓存储设置为minIO对象存储,待开展。
- [x] rancher有哪些driver,传入minIO,已完成。
(以上操作,先文档化,以后整理成脚本化)
- [x] Minimal的干净环境,启动minio,已完成。
- [x] docker 19.03的依赖,传入minio,制作yum repo仓,已完成。
- [x] 本地yum源离线安装docker工作正常,已完成。
- [x] 整理离线安装的云昊的镜像tar包,传入minio,已完成。
- [x] 命令行、iso、driver的离线安装。
8. ### 性能测试
采用intel开源的测试对象存储系统的性能测试工具或minio官方压测方案对minio进行性能测试:
https://github.com/intel-cloud/cosbench
https://github.com/minio/benchmarks
9. ### 优势和不足
#### 优点:
对象存储,`兼容Amazon S3协议`。
安装运维相对简单,`开箱即用`。
后端除了本地文件系统,还`支持多种存储系统`。
原生支持`bucket事件通知机制`。
可通过多节点集群方式,支持一定的高可用和数据容灾。
有web管理界面和cli,可以用于测试或者管理。
公开bucket中的数据可以`直接通过HTTP获取`。
#### 缺点:
没有经过长时间的使用和验证,`稳定性不确定`。
没有官方的HTTP协议API,`只能使用SDK`。
`不支持`动态增加节点(目前私有化部署场景对此的需求并不强)。
### 知识点修正和补充:
1.高性能 在标准硬件上,读/写速度上高达183 GB/秒和171 GB/秒。 数据来源于http://www.minio.org.cn/
2.可扩容 可扩展性:MinIO利用了Web缩放器的来之不易的知识,为对象存储带来了简单的缩放模型。 这是我们坚定的理念 “简单可扩展.” 在 MinIO, 扩展从单个群集开始,该群集可以与其他MinIO群集联合以创建全局名称空间, 并在需要时可以跨越多个不同的数据中心。 通过添加更多集群可以扩展名称空间, 更多机架,直到实现目标。来源于http://www.minio.org.cn/
3.Lambda计算 minio服务器自身不提供Lambda计算能力,通过其兼容AWS SNS/SQS的事件通知服务触发Lambda功能。来源于http://minio.org.cn/overview.shtml
4.无元数据数据库 MinIO在带有本地驱动器(JBOD / JBOF)的商品服务器上运行。集群中的所有服务器的功能均相同(完全对称的体系结构)。没有名称节点或元数据服务器。
MinIO将数据和元数据作为对象一起写入,从而无需使用元数据数据库。来源于http://minio.org.cn/overview.shtml
5.S3 Select支持
支持完整的AWS S3 SELECT SQL语法;支持所有运算符;支持所有聚合,条件,类型转换和字符串函数。
来源http://docs.minio.org.cn/docs/master/minio-select-api-quickstart-guide
6.单写多读(worm)
启用此选项可开启“一次写入多次读取”。默认设置为关闭。来源于http://www.lw007.cn/docs/minio-server-configuration-guide.html
```
export MINIO_WORM=on
```
通过应用charts的values.yaml设置环境变量environment。
7.Minio为什么选RS纠删码,而没有使用阵列纠删码?
阵列纠删码(Array Code: RAID5、RAID6等)比如RAID5只支持一个盘失效,即使是RAID6也仅支持两个盘失效。
纠删码的工作原理和RAID或者复制不同,像RAID6可以在损失两块盘的情况下不丢数据,而Minio RS纠删码可以在丢失一半的盘的情况下,仍可以保证数据安全。而且Minio RS纠删码是作用在对象级别,可以一次恢复一个对象,而RAID是作用在卷级别,数据恢复时间很长。 Minio对每个对象单独编码,存储服务一经部署,通常情况下是不需要更换硬盘或者修复。Minio RS纠删码的设计目标是为了性能和尽可能的使用硬件加速。https://www.bookstack.cn/read/MinioCookbookZH/3.md
8.为minio server实例传入多个本地磁盘目录参数,可以是本地文件夹目录作为参数或者硬盘位置作为参数。
9.一致性保障 强一致性模型 https://zhuanlan.zhihu.com/p/59119088 《minio白皮书》http://www.cloudbin.cn/?p=2917
MinIO对象存储系统无元数据数据库,所有的操作都是对象级别的粒度的。这种做法的优势是:个别对象的失效,不会溢出为更大级别的系统失效。便于实现“强一致性”这个特性。此特性对于机器学习与大数据处理非常重要。
集群扩展优势特性,集群不会过大(32个节点),可实现可靠的分布式锁管理器,进而保证更新、删除等操作的强一致性。
10.关注gateway启动模式 挂载到一个NAS卷
数据本身的高可用已经得到保证了,但如何保证S3服务的高可用?
如果要求保证harbor的高可用,考虑到会导致无法使用NAS。
Minio本身服务的高可用怎么保证,是否是Client保证,或负载均衡,或自协商?
启动双副本Minio gateway容器,开启Ingress七层负载均衡访问minio,后端挂载同一个路径下的NAS上。
通过任何一个Minio gateway都可以正常访问NAS,提升高可用性。
11.一个分布式的对象网关怎么部署?
可以在同一个共享NAS卷上运行多个minio实例,作为一个分布式的对象网关。负载均衡--minio gateway--nas
12.Minio性能测试使用官网wap工具