言成言成啊 | Kit Chen's Blog

Minio分布式对象存储的部署与使用

发布于2022-07-11 00:52:18,更新于2023-01-04 21:53:54,标签:devops  文章会持续修订,转载请注明来源地址:https://meethigher.top/blog

本文版本环境

  • minio服务器:minio version RELEASE.2022-07-08T00-05-23Z

历史版本下载地址

此处简单放置一个下载方式

1
2
3
4
curl -X GET -o minio.rpm https://meethigher.top/cloud/download/0/sh/19a5fd77a60dc33ecfb22bbbe6247585
rpm -Uvh --force --nodeps *.rpm
rm -rf minio.rpm
minio --version

一、部署

下载Minio直接Github搜索即可,minio/minio: Multi-Cloud Object Storage

1.1 单机部署

单机部署命令,指定静态端口9001。

一般会占用两个端口,9000和指定的9001,实际访问是9001。

1
2
3
4
5
mkdir data
# 授予执行权限
chmod +x minio
# 启动命令
MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=minioadmin nohup ./minio server data/ --console-address=:9001 >log 2>&1 &

建议将启动命令创建成bash脚本,方便执行

我的本机ip是10.0.0.10,所以直接访问10.0.0.10:9000即可,会自动跳转到9001。

1.2 集群部署

集群部署,多台机器使用同一套启动命令即可。

硬性要求:至少4个driver,此处我就理解成分区。

至少4个driver,是由于分布式Minio启用了纠删码算法来保证数据的安全,这个算法保证了,只要不超过N/2块分区坏掉,数据就不会丢失。

部署集群,我可以选用2个节点,每节点2个driver,或者4个节点,每节点1个driver

我采用的方式是后者。

准备4台服务器

1
2
3
4
10.0.0.10
10.0.0.11
10.0.0.12
10.0.0.13

每台机器执行下面的命令。

1
2
3
4
5
6
7
8
9
10
11
# 创建minio数据存储目录
mkdir /minio
# 查看所有分区情况
fdisk -l
# 带*的为主分区,我的是/dev/sda1,将数据存储目录挂载到主分区
mount /dev/sda1 /minio
# 临时的环境变量,配置root的用户名密码
export MINIO_ROOT_USER=xiangwan
export MINIO_ROOT_PASSWORD=xiangwan
# 启动集群
nohup /root/minio server http://10.0.0.10/minio http://10.0.0.11/minio http://10.0.0.12/minio http://10.0.0.13/minio --console-address=:9001 >log 2>&1 &

四台机器都执行后,可通过cat log 查看日志,如下图。

任意访问其中一台即可,我就直接访问10.0.0.10:9000,可以查看节点监控信息

二、使用官方SDK

示例demo是纯maven项目,meethigher/minio-usage: 对象存储minio使用

2.1 基础配置

pom.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>top.meethigher</groupId>
<artifactId>minio-usage</artifactId>
<version>1.0.0</version>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.1.0</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

创建配置文件application.properties

1
2
3
endpoint=http://10.0.0.10:9000
accessKey=xiangwan
secretKey=xiangwan

创建配置类MinioConfig

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
package top.meethigher.config;

import java.io.IOException;
import java.util.Properties;

/**
* minio配置
*
* @author chenchuancheng
* @since 2022/7/8 14:41
*/
public class MinioConfig {
//连接url
public static String endpoint;
//公钥
public static String accessKey;
//私钥
public static String secretKey;

static {
Properties prop = new Properties();
try {
prop.load(MinioConfig.class.getClassLoader().getResourceAsStream("application.properties"));
endpoint=prop.getProperty("endpoint");
accessKey=prop.getProperty("accessKey");
secretKey=prop.getProperty("secretKey");
} catch (IOException e) {
e.printStackTrace();
}
}
}

创建MinioClientBuilder

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
package top.meethigher.utils;

import io.minio.MinioClient;
import top.meethigher.config.MinioConfig;

/**
* 获取MinioClientBuilder
*
* @author chenchuancheng
* @since 2022/7/8 14:42
*/
public class MinioClientBuilder {

private static MinioClient minioClient = null;

private MinioClientBuilder() {
minioClient = MinioClient.builder()
.endpoint(MinioConfig.endpoint)
.credentials(MinioConfig.accessKey, MinioConfig.secretKey)
.build();
}

private static final class MinioClientBuilderHolder {
static final MinioClientBuilder minioClientBuilder = new MinioClientBuilder();
}

public static MinioClient build() {
MinioClientBuilder minioClientBuilder = MinioClientBuilderHolder.minioClientBuilder;
return minioClientBuilder.getMinioClient();
}

private MinioClient getMinioClient() {
return minioClient;
}
}

2.2 api使用

上传功能

1
2
3
4
5
6
7
8
9
MinioClient minioClient = MinioClientBuilder.build();
UploadObjectArgs args = UploadObjectArgs.builder()
.bucket("xiangwan")
.object("wuhuang.jpg")
//创建并上传到test文件夹
//.object("test/wuhuang.jpg")
.filename("C:\\Users\\14251\\Desktop\\吾皇.png")
.build();
minioClient.uploadObject(args);

下载功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
MinioClient minioClient = MinioClientBuilder.build();
GetObjectArgs args = GetObjectArgs.builder()
.bucket("xiangwan")
.object("wuhuang.jpg")
.build();
InputStream is = minioClient.getObject(args);
FileOutputStream fos = new FileOutputStream("xiangwan.jpg");
int len;
byte[] b=new byte[1024];
while((len=is.read(b))!=-1) {
fos.write(b,0,len);
}
fos.close();
is.close();

查询功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
MinioClient minioClient = MinioClientBuilder.build();
ListObjectsArgs args= ListObjectsArgs.builder()
.bucket("xiangwan")
//指定文件夹
//.prefix("test/")
.build();
Iterable<Result<Item>> results = minioClient.listObjects(args);
for (Result<Item> next : results) {
Item item = next.get();
boolean dir = item.isDir();
if (dir) {
System.out.printf("文件名:%s,文件修改时间:0,文件大小:0,文件类型:%s\n", item.objectName(),
item.isDir());
} else {
System.out.printf("文件名:%s,文件修改时间:%s-%s-%s %s:%s:%s,文件大小:%s,文件类型:%s\n", URLDecoder.decode(item.objectName(), "utf-8"),
item.lastModified().getYear(), item.lastModified().getMonthValue(), item.lastModified().getDayOfMonth(),
item.lastModified().getHour(), item.lastModified().getMinute(), item.lastModified().getSecond(),
item.size(),
item.isDir());
}
}

运行结果如图

删除功能

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
MinioClient minioClient = MinioClientBuilder.build();
//删除单个
RemoveObjectArgs args= RemoveObjectArgs.builder()
.bucket("xiangwan")
.object("log")
.build();
minioClient.removeObject(args);

//删除多个
Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
.bucket("xiangwan")
.prefix("test/")
.build());
List<DeleteObject> deleteObjects=new LinkedList<>();
for (Result<Item> result : results) {
Item item = result.get();
deleteObjects.add(new DeleteObject(URLDecoder.decode(item.objectName(),"utf-8")));
}
RemoveObjectsArgs argss= RemoveObjectsArgs.builder()
.bucket("xiangwan")
.objects(deleteObjects)
.build();
//该方法是懒加载,类似于Feature,需要拿到返回值执行
Iterable<Result<DeleteError>> removeObjects = minioClient.removeObjects(argss);
for (Result<DeleteError> removeObject : removeObjects) {
DeleteError error = removeObject.get();
System.out.printf("minio删除错误->bucketName=%s,objectName=%s,message=%s\n", error.bucketName(), error.objectName(), error.message());
}

删除文件夹没有提供直接方式

如有需求就走删除多个对象

三、配置权限

3.1 用户和组

直接创建用户或者组即可,最终用户的权限=用户权限+组权限。

3.2 密钥

具体参照MinIO多用户快速入门指南 | Minio中文文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"Version": "2012-10-17",
"Statement": [

{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}

比如我授权一个token,只能调用删除。只需要添加动作DeleteObject即可。

会发现,只能删除,连查询都做不了。

3.3 通过桶名和文件名访问

配置资源可以通过ip:端口/桶名/资源路径访问单个资源。

就如桶管理,找到Access Rules。

放行所有,都有readOnly权限即可。

通过ip:端口/桶名/资源路径即可访问。

四、参考致谢

MinIO Quickstart Guide| Minio中文文档

Issues · minio/minio

Minio(一) | 搭建Minio服务器(单节点)_Ruby丶彬的博客-CSDN博客_minio单节点

Minio(二) | Minio多用户权限控制_Ruby丶彬的博客-CSDN博客_minio权限控制

Minio(三) | Minio分布式集群搭建_Ruby丶彬的博客-CSDN博客_minio集群搭建

搭建minio分布式测试环境_wdtmn的博客-CSDN博客

文档服务器minio 可通过文件路径进行访问_领风者的博客-CSDN博客_minio 文件访问路径

Minio 批量删除文件失效的问题分析 (Java SDK) - 简书

MinIO关闭公开桶的列表展示_李硕硕的博客-CSDN博客_minio 数据泄露

Linux中挂载到底什么意思!!!为你解答_404~的博客-CSDN博客_linux挂载是什么意思

发布:2022-07-11 00:52:18
修改:2023-01-04 21:53:54
链接:https://meethigher.top/blog/2022/minio/
标签:devops 
付款码 打赏 分享
Shift+Ctrl+1 可控制工具栏