使用MINIO搭建私有云文件服务器
MinIO 是一款高性能、分布式的对象存储系统. 它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。
在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品
本文链接:https://blog.focc.cc/archives/135
看官网的简介,是不是吹得很厉害,确实很厉害!
1.MINIO是什么
如果有同学用过阿里云的OOS(Object Storage Service)产品,或者腾讯云的COS(Cloud Object Storage)产品,
那么你将很快理解MINIO是什么,minio能够提供的功能与OOS和COS无异~是一个开源的分布式对象文件存储系统。
1.1为什么要用minio?
我们平常接触的业务难免会有些文件上传下载的功能,如果公司有钱的话~那么可能就会去买大厂的产品,直接使用,这样的好处就是花钱买服务,也有售后,如果公司的资料文件很重要(游戏策划素材、合同发票...),那么就可能不允许存储到外网之上,这个时候你或许会搞一台服务器,文件存到物理盘上,通过一些服务器(nginx)来实现上传or下载的功能,也不是不行,但肯定不好,例如你要考虑备份,容灾,性能...等等一系列问题,这个时候你就可以选择使用minio来快速部署一个文件服务器来开发你的应用!
1.2为什么要选择minio?
首先肯定是开源免费,可以自己部署使用,其次呢社区活跃度也很高,毕竟东西好用~ 和其它开源的文件服务器(fastDFS、MogileFS...)对比来说,minio用起来真的是很方便,仅需一点运维知识,就可以快速上手开发。
2.部署前的准备
文件服务器搭建单机版的没有意思,我们直接搭建4个节点(官网推荐最低4个)4块盘的集群。
2.1环境准备
先准备四台服务器
192.168.152.128
192.168.152.129
192.168.152.130
192.168.152.131
在每台服务器上都创建一个存储目录
root@machine1:~# mkdir /opt/data
使每台服务器都同步一下时间 我这里使用的是ubuntu server 所以使用apt 下载了 ntpdate工具,按需更换
root@machine1:~# apt install ntpdate
root@machine1:~# ntpdate -u time.pool.aliyun.com
很重要的一点,分布式部署最好使用裸机部署,存储目录一定要求是空的
3.开始部署
minio提供了二进制、docker、k8s、源码方式部署。我这里就演示下二进制和docker的部署方式,其它的可以参考文末的链接自己部署一下。
3.1二进制方式部署
个人习惯还是先从二进制部署,因为查问题比较方便~
以下步骤在四台服务器都要执行
下载二进制文件
root@machine1:~# wget http://dl.minio.org.cn/server/minio/release/linux-amd64/minio
给二进制文件授权
root@machine1:~# chmod +x minio
设置密钥
root@machine1:~# export MINIO_ACCESS_KEY=minio
root@machine1:~# export MINIO_SECRET_KEY=minio123456
做完上边三步之后,就可以通过一行命令启动了~
很简单,server后边跟着四台机器的存储盘目录就OK了~ 四台机器都要执行这串命令的。
root@machine1:~# ./minio server http://192.168.152.128/opt/data \
http://192.168.152.129/opt/data \
http://192.168.152.130/opt/data \
http://192.168.152.131/opt/data
通过上边命令启动的话是前台启动的~ 我写了个脚本 启动方式可以变成这样 记得把二进制文件和脚本放在同级目录
root@machine1:~# ./minio.sh start
root@machine1:~# ./minio.sh stop
root@machine1:~# ./minio.sh restart
下载脚本:minio.sh
下载之后记得把里边的挂载目录修改一下~
WebConsole
minio为我们提供了web页面,直接集成到了二进制文件中 启动之后你就会看到输出以下信息,
Waiting for all MinIO sub-systems to be initialized.. lock acquired
Verifying if 3 buckets are consistent across drives...
All MinIO sub-systems initialized successfully
Waiting for all MinIO IAM sub-system to be initialized.. lock acquired
IAM initialization complete
Status: 4 Online, 0 Offline.
Endpoint: http://192.168.152.128:9000 http://127.0.0.1:9000
Browser Access:
http://192.168.152.128:9000 http://127.0.0.1:9000
Object API (Amazon S3 compatible):
Go: https://docs.min.io/docs/golang-client-quickstart-guide
Java: https://docs.min.io/docs/java-client-quickstart-guide
Python: https://docs.min.io/docs/python-client-quickstart-guide
JavaScript: https://docs.min.io/docs/javascript-client-quickstart-guide
.NET: https://docs.min.io/docs/dotnet-client-quickstart-guide
随便复制一个节点的链接到浏览器中打开 非常简洁的登录界面~ 账号密码就是上边我们设置的密钥
主页也很简洁,通过右下角的按钮创建一个桶,便可直接上传文件
同时它还支持分享文件和预览
到这里我们就部署完成了~
3.2docker部署
docker部署,其实是单节点伪分布式部署的,节点挂了那整个分布式集群就挂了~ 当然它也可以多节点容器部署,不过我没去细看
下载docker-compose.yaml
如果机器上没有docker,是需要提前安装的。
root@machine1:~# wget https://raw.githubusercontent.com/minio/minio/master/docs/orchestration/docker-compose/docker-compose.yaml
修改配置
修改下载的配置文件,修改里边的挂载目录和密钥即可
root@machine1:~# vi docker-compose.yaml
拉取镜像
root@machine1:~# docker-compose pull
启动minio
root@machine1:~# docker-compose up
启动之后 是和二进制启动之后一样的效果,挂载端口是9000,页面访问就行了
4.分布式存储
我们随便打开一个节点上传文件然后你去另外一个节点查看文件
你会发现每一个节点的控制台里都有这个文件,都可以进行查看
去机器上看存储的目录
逆回发现每一个机器上都有这个文件(目录)
看下边这张图
数据对象在MinIO集群中进行存储时,先进行纠删分片,后打散存储在各硬盘上。具体为:MinIO自动在集群内生成若干纠删组,每个纠删组包含一组硬盘,其数量通常为4至16块;对数据对象进行分片,默认策略是得到相同数量的数据分片和校验分片;而后通过哈希算法计算出该数据对象对应的纠删组,并将数据和校验分片存储至纠删组内的硬盘上。
高可用
这个时候,即使你宕掉一台机器,仍然可以进行上传或者下载。
5.数据恢复
如果其中一个节点down掉,那再启动的话,是不是这段时间内这台节点就没这个文件的数据了?实践出真理
5.1 关掉节点
们把130节点关掉 其它节点就会检测到130出现故障 这个时候我们可以通过接入Prometheus来监控告警(后边会写个Prometheus的文章)
5.2 上传文件
我们在130down掉的时候向集群中上传文件
5.3 启动节点
重新启动130机器
可以发现,在宕机过程中上传的文件数据,自动恢复了~
4.负载均衡
我们通过分布式部署集群后,会出现四台节点端口,我没找到官网给出的解释,但是当我宕掉其中一台,集群是正常的,但是我就无法使用这台的端口来进行服务,所以我们需要把这四台机器的端口做一下负载,应该另外起一台服务器来负载,我这里为了方便,直接在128机器上做负载了
4.1配置ngxin
配置一下nginx.conf的http内容
...
http {
upstream minio {
server 192.168.152.128:9000;
server 192.168.152.129:9000;
server 192.168.152.130:9000;
server 192.168.152.131:9000;
}
server {
listen 80;
server_name testminio.com;
location / {
# 反向代理地址,注意 /
proxy_pass http://minio;
}
}
}
...
修改本地host
有条件的直接域名解析,我这里就修改本地的host做下映射来验证下 参考文末
...
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
192.168.152.128 testminio.com
这样就可以实现负载了,其中一个宕掉,也可以通过域名访问其它的服务
5.Demo开发
minio提供了js、java、go、python、.net、hs的客户端sdk包,可以更快速的开发程序
我在这里就使用go来简单使用下sdk,其它语言大家可以自己去看看,链接在文末
package main
import (
"github.com/minio/minio-go/v6"
"log"
"time"
)
func main() {
//endpoint := "testminio.com"
endpoint := "192.168.152.128:9000"
accessKeyID := "minio"
secretAccessKey := "minio123456"
useSSL := false
// 初使化minio client对象。
minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, useSSL)
if err != nil {
log.Fatalln(err)
}
log.Printf("初始化客户端 %s\n",minioClient)
// 创建一个叫mymusic的存储桶。
bucketName := "myapp"
location := "cn-north-1"
err = minioClient.MakeBucket(bucketName, location)
if err != nil {
// 检查存储桶是否已经存在。
exists, err := minioClient.BucketExists(bucketName)
if err == nil && exists {
log.Printf("We already own %s\n", bucketName)
} else {
log.Fatalln(err)
}
}
log.Printf("Successfully created %s\n", bucketName)
// 上传一个zip文件。
objectName := "ubuntu-20.04.2-live-server-amd64.iso"
filePath := "D:\\install\\ubuntu-20.04.2-live-server-amd64.iso"
contentType := ""
// 使用FPutObject上传一个zip文件。
log.Printf("开始上传 ")
timeUnix:=time.Now().Unix()
n, err := minioClient.FPutObject(bucketName, objectName, filePath, minio.PutObjectOptions{ContentType:contentType})
if err != nil {
log.Fatalln(err)
}
endTimeUnix:=time.Now().Unix()
diff := endTimeUnix - timeUnix
log.Printf("Successfully uploaded %s of size %d time %d ", objectName, n,diff)
log.Printf("开始下载 ")
timeUnix=time.Now().Unix()
err = minioClient.FGetObject("mymusic", objectName, "C:\\Users\\fangpengbo.101\\Desktop\\ubuntu-20.04.2-live-server-amd64.iso", minio.GetObjectOptions{})
if err != nil {
log.Fatalln(err)
return
}
endTimeUnix=time.Now().Unix()
diff = endTimeUnix - timeUnix
log.Printf("Successfully download %s of size %d time %d ", objectName, n,diff)
}
这里我使用了IP+端口来进行创建客户端,因为使用域名的话需要https协议。
可以看到,上传1.13G的文件,大概在10s以内,下载在15s左右。 速度还是非常快的~
我们刷新下浏览器,就可以看到了。
有兴趣的同学可以尝试使用下minio~