知足常乐

知足常乐

使用MINIO搭建私有云文件服务器

2021-07-07

MinIO 是一款高性能、分布式的对象存储系统. 它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。
在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品

本文链接:https://blog.focc.cc/archives/135

看官网的简介,是不是吹得很厉害,确实很厉害!
image.png

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

随便复制一个节点的链接到浏览器中打开 非常简洁的登录界面~ 账号密码就是上边我们设置的密钥
image.png
主页也很简洁,通过右下角的按钮创建一个桶,便可直接上传文件
image.png
同时它还支持分享文件和预览
image.png
image.png
到这里我们就部署完成了~

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.分布式存储

我们随便打开一个节点上传文件然后你去另外一个节点查看文件
你会发现每一个节点的控制台里都有这个文件,都可以进行查看
image.png

去机器上看存储的目录
逆回发现每一个机器上都有这个文件(目录)
image.png

看下边这张图
数据对象在MinIO集群中进行存储时,先进行纠删分片,后打散存储在各硬盘上。具体为:MinIO自动在集群内生成若干纠删组,每个纠删组包含一组硬盘,其数量通常为4至16块;对数据对象进行分片,默认策略是得到相同数量的数据分片和校验分片;而后通过哈希算法计算出该数据对象对应的纠删组,并将数据和校验分片存储至纠删组内的硬盘上。
image.png

高可用
这个时候,即使你宕掉一台机器,仍然可以进行上传或者下载。

5.数据恢复

如果其中一个节点down掉,那再启动的话,是不是这段时间内这台节点就没这个文件的数据了?实践出真理

5.1 关掉节点

们把130节点关掉 其它节点就会检测到130出现故障 这个时候我们可以通过接入Prometheus来监控告警(后边会写个Prometheus的文章)
image.png

5.2 上传文件

我们在130down掉的时候向集群中上传文件
image.png

5.3 启动节点

重新启动130机器
可以发现,在宕机过程中上传的文件数据,自动恢复了~
image.png

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

这样就可以实现负载了,其中一个宕掉,也可以通过域名访问其它的服务
image.png

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左右。 速度还是非常快的~
image.png
我们刷新下浏览器,就可以看到了。
image.png

有兴趣的同学可以尝试使用下minio~

参考资料

1.部署minio
2.host解析
3.MINIO SDKS