前置条件
官网:https://www.minio.org.cn/download.shtml#/kubernetes
命令
# 查看系统上的网络连接和监听端口信息
netstat -tpnl
# 检查系统的指定端口占用情况
sudo netstat -tuln | grep 9000
systemctl status firewalld
# 临时关闭
systemctl stop firewalld
# 永久关闭
systemctl disable firewalld
安装
官网有不同系统的下载安装方式
Linux
注意:./是当前目录
# 下载
wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio
# 修改权限
chmod +x minio
# 启动
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001"
#也可以下面这样,他会默认用户名和密码
./minio server /mnt/data --console-address ":9001"
- MINIO_ROOT_USER 指定 MinIO 的用户名;
- MINIO_ROOT_PASSWORD 指定 MinIO 的密码;
- /mnt/data 指定 MinIO 服务器用于存储数据的目录;
- console-address “:9001” 指定 MinIO 控制台的监听地址和端口
后台启动(&结束):./minio server /mnt/data --console-address “:9001” &
docker
# 安装前查看系统是否已经安装了Docker
yum list installed | grep docker
# 卸载Docker 把查出来的都卸载就行了
yum remove docker.x86_64 -y
# 安装 这种方式安装的Docker版本比较旧;(查看版本:docker -v)
yum install docker -y
# 安装最新版的Docker
yum install yum-utils -y
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
安装启动
# 搜索MinIO镜像
docker search minio
# 拉取MinIO镜像
docker pull minio/minio
# 启动MinIO容器 不指定的话默认最新 这个启动命令官网是 podman 改成docker
docker run -p 9000:9000 -p 9001:9001 minio/minio server /data --console-address :9001
没有指定用户名和密码,默认是 minioadmin
- p (映射端口) 虚拟机 : 容器
- minio/minio 镜像名
- server 启动参数
- /data 数据文件存放的路径
- console-address :9001 web 访问地址和端口
windows
下载 minio:https://dl.min.io/server/minio/release/windows-amd64/minio.exe
进入到 minio.exe 所在的目录
执行 minio.exe server D:\minio\data 启动 minio 服务,其中 D:\minio\data 是 MinIO 存储数据的目录路径
在浏览器输入:http://localhost:9000/ ,登录 MinIO 服务器 web 管理后台,默认用户名密码都是 minioadmin
springboot 集成
Bucket 是存储 Object 的逻辑空间,每个 Bucket 之间的数据是相互隔离的,对用户而言,相当于存放文件的顶层文件夹;
Object 是存储到 MinIO 的基本对象,对用户而言,相当于文件;
添加依赖
https://min.io/docs/minio/linux/developers/minio-drivers.html#java
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.10</version>
</dependency>
配置类 MinioClientConfig
@Configuration
public class MinioClientConfig {
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint("http://192.168.64.100:9000")
.credentials("minioadmin", "minioadmin")
.build();
}
}
测试连接
@SpringBootTest
public class TestMain {
@Autowired
private MinioClient minioClient;
@Test
public void test() {
System.out.println(minioClient);
}
}
MinioClient 的常用 API:
-
bucketExists():用于检查指定的存储桶是否存在,返回布尔值,表示存储桶是否存在;
-
makeBucket():用于创建一个新的存储桶(bucket),需要指定存储桶的名称;
-
listBuckets():用于列出用户有权访问的所有存储桶,返回存储桶的列表;
-
removeBucket():用于删除一个已存在的存储桶(bucket),删除失败会抛出异常;
-
putObject():用于上传文件到指定的存储桶;
-
statObject():用于检查指定的对象(文件)的状态;
-
getPresignedObjectUrl():用于生成一个对象(文件)的签名 URL,以便可以通过 HTTP 访问;
-
getObject():用于从指定的存储桶中下载文件;
-
listObjects():用于列出指定存储桶中的所有对象(文件);
-
removeObject():用于删除指定存储桶中的对象,需要指定存储桶名称和对象键;
Buckets 代码实现
@SpringBootTest
public class TestBucket {
@Autowired
private MinioClient minioClient;
@Test
public void removeBucket() throws Exception {
// 删除bucket
minioClient.removeBucket(RemoveBucketArgs.builder().bucket("test").build());
}
@Test
public void listBuckets() throws Exception {
// 列出所有有权访问的 bucket
minioClient.listBuckets().forEach(bucket -> {
System.out.println(bucket.name()+bucket.creationDate());
});
}
@Test
public void createBucket() throws Exception {
// 创建bucket
minioClient.makeBucket(MakeBucketArgs.builder().bucket("test").build());
}
@Test
public void bucketExists() throws Exception {
boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket("test").build());
System.out.println("test目录是否存在:"+bucketExists);
}
@Test
public void test() {
System.out.println(minioClient);
}
}
Object 代码实现
@SpringBootTest
public class TestObject {
@Autowired
private MinioClient minioClient;
@Test
public void removeObject() throws Exception {
//用于删除指定存储桶中的指定对象(文件)
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket("test")
.object("1.jpg")
.build());
}
@Test
public void listObjects() {
//用于列出指定存储桶中的所有对象(文件)
Iterable<Result<Item>> test = minioClient.listObjects(ListObjectsArgs.builder()
.bucket("test").build());
test.forEach(result -> {
try {
Item item = result.get();
System.out.println(item.objectName());
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
@Test
public void getObject() throws Exception {
//用于从指定的存储桶中下载文件
GetObjectResponse response = minioClient.getObject(GetObjectArgs.builder()
.bucket("test")
.object("1.jpg")
.build());
//io.minio.GetObjectResponse@6a5dd083
System.out.println(response);
System.out.println(response.transferTo(new FileOutputStream("D:\\Desktop\\projects\\springoot3-vues\\minio\\day01\\src\\main\\resources\\static\\1.jpg")));
}
@Test
public void getPresignedObjectUrl() throws Exception {
//用于生成一个对象(文件)的签名URL,以便可以通过HTTP访问
String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.bucket("test")
.expiry(3, TimeUnit.MINUTES)//设置过期时间
.object("1.jpg").method(Method.GET).build());
System.out.println("url = " + url);
}
@Test
public void statObject() throws Exception {
StatObjectResponse test = minioClient.statObject(StatObjectArgs.builder()
.bucket("test").object("1.jpg").build());
//用于检查指定的对象(文件)的状态;
//ObjectStat{bucket=test, object=1.jpg, last-modified=2024-05-10T08:30:35Z, size=1145359}
System.out.println(test);
}
@Test
public void putObject() throws Exception {
File file = new File("D:\\Pictures\\0.jpg");
ObjectWriteResponse test = minioClient.putObject(PutObjectArgs.builder()
.bucket("test").object("1.jpg")//上传到minio后的文件名
.stream(new FileInputStream(file), file.length(), -1).build());
//test = io.minio.ObjectWriteResponse@1815577b
System.out.println("test = " + test);
ObjectWriteResponse test1 = minioClient.uploadObject(UploadObjectArgs.builder()
.bucket("test").object("1.jpg").filename("D:\\Pictures\\0.jpg").build());
}
}
集群
纠删码模式部署
纠删码(Erasure Code)简称 EC,是一种数据保护方法,也是一种算法;
MinIO 对纠删码模式的算法进行了实现,采用 Reed-Solomon code(简称 RScode)纠错码将对象拆分成 N/2 数据和 N/2 奇偶校验块,Reed Solomon 利用范德蒙矩阵(Vandermonde matrix)、柯西矩阵(Cauchy matrix)的特性来实现;
即将数据拆分为多个数据块和多个校验块,分散存储在不同的磁盘上,即使在部分磁盘损坏或丢失的情况下,也可以通过剩余的数据块和校验块恢复出原始数据;
举个例子,现在有 12 块磁盘,一个对象数据会被分成 6 个数据块、6 个奇偶校验块,你可以损坏或丢失任意 6 块磁盘(不管其是存放的数据块还是奇偶校验块),你仍可以从剩下的磁盘中恢复数据
linux 启动纠删码模式
wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio
# 修改权限
chmod +x minio
# 单机多磁盘的部署 记得执行上行命令 在/usr/local/minio下 /opt/minio/data 数据卷目录
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password /usr/local/minio/minio server --console-address ":9001" /opt/minio/data/data{1...12}
单机多磁盘的部署,会报错
执行命令:lsblk
lsblk 是 Linux 中的一个命令,用于列出所有可用的块设备(数据存储设备,如硬盘、闪存驱动器)的信息,如设备名称、大小、挂载点等;
执行命令:lsblk
lsblk 是 Linux 中的一个命令,用于列出所有可用的块设备(数据存储设备,如硬盘、闪存驱动器)的信息,如设备名称、大小、挂载点等;
添加一块磁盘,上图是没加磁盘
# 不重启,直接刷新磁盘数据总线,获取新加的磁盘
for host in $(ls /sys/class/scsi_host) ; do echo "- - -" > /sys/class/scsi_host/$host/scan; done
再次执行 lsblk
启动纠删码
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password /usr/local/minio/minio server --console-address ":9001" /opt/minio/data/data{1...12}
登录 minio 查看
上传一个文件查看数据目录发现每个目录都存了文件
linux 启动纠删码模式-后台启动
# 这样就不能设置用户名和密码了,咱也不知道为啥一会必须设置一会不能设置,默认用户名密码 minioadmin 不知道是不是版本原因
nohup /usr/local/minio/minio server --console-address ":9001" /opt/minio/data/data{1...12} > /opt/minio/data/minio.log 2>&1 &
- nohup: 这是一个 Unix 命令,用于运行另一个命令在后台,并且忽略挂起(HUP)信号,也就是即使你退出了终端或关闭了会话,该命令也会继续运行;
- > /opt/minio/data/minio.log: 这部分是将标准输出(stdout)重定向到 /opt/minio/data/minio.log 文件,这意味着 MinIO 服务器的所有正常输出(如启动信息、状态更新等)都会被写入到这个日志文件中;
- 2>&1: 这部分是将标准错误输出(stderr)重定向到标准输出(stdout),即输出到 /opt/minio/data/minio.log 文件,这样,无论是标准输出还是错误输出,都会被写入到同一个日志文件中;
- &: 这个符号是在命令的末尾,用于将命令放到后台执行,也就是即使你启动了 MinIO 服务器,你的终端或 shell 会话也不会被阻塞,你可以继续执行其他命令;
docker 启动纠删码模式
docker logs minio
# 这里的密码也不能少于八位 不然容器就会一直处于重启状态(查看日志就会说密码少于八位了)
docker run -d \
-p 9000:9000 \
-p 9001:9001 \
--name=minio \
--restart=always \
-e "MINIO_ROOT_USER=root" \
-e "MINIO_ROOT_PASSWORD=password" \
-v /home/minio/data1:/data1 \
-v /home/minio/data2:/data2 \
-v /home/minio/data3:/data3 \
-v /home/minio/data4:/data4 \
-v /home/minio/data5:/data5 \
-v /home/minio/data6:/data6 \
-v /home/minio/data7:/data7 \
-v /home/minio/data8:/data8 \
--privileged=true \
minio/minio server /data{1...8} \
--console-address ":9000" \
--address ":9001"
上传个文件并使用 tree 命令查看目录 /home/minio
安装 tree:yum install tree
集群部署-Linux
纠删码模式是单机多磁盘方式,如果这台机器宕机了,那么 minio 就不能对外提供服务了
准备 4 台机器;(根据 MinIO 的架构设计,至少需要 4 个节点来构建集群,这是因为在一个 N 节点的分布式 MinIO 集群中,只要有 N/2 节点在线,数据就是安全的,同时,为了确保能够创建新的对象,需要至少有 N/2+1 个节点,因此,对于一个 4 节点的集群,即使有两个节点宕机,集群仍然是可读的,但需要有 3 个节点才能写数据;)
准备四台虚拟机—下面的操作四台都需要执行
192.168.64.100
192.168.64.102
192.168.64.103
192.168.64.104
minio 集群需要独占磁盘块,不能使用 Linux 的 root 磁盘块
都添加一块硬盘去目录看–> linux 启动纠删码模式
# 不重启,直接刷新磁盘数据总线,获取新加的磁盘
for host in $(ls /sys/class/scsi_host) ; do echo "- - -" > /sys/class/scsi_host/$host/scan; done
将添加的磁盘格式化为 xfs 格式:
mkfs.xfs /dev/sdb
将磁盘挂载到 minio 的存储目录:
# 递归创建文件夹 若文件夹不存在
mkdir -p /opt/minio/data
mount /dev/sdb /opt/minio/data
开机自动挂载-Linux
开机自动挂载,不配置自动挂载的话,重启之后需要手动进行挂载
一、修改 /etc 下的 fstab 文件
vim /etc/fstab
source /etc/fstab
在最后一行加入以下内容
/dev/sdb /opt/minio/data xfs defaults 0 0
- /dev/sdb 是设备的路径。
- /opt/minio/data 是挂载点。
- xfs 是文件系统类型。
- defaults 是一组默认选项。
- 0 0 是用于文件系统检查的选项。
注意:不要写错和少写,我没有写文件系统类型和默认选项,重启后进入了紧急模式
二、修改 /etc 下的 rc.local 文件或者 /etc/rc.d 下的 rc.local 文件
这个配置文件会在用户登陆之前读取,这个文件中写入了什么命令,在每次系统启动时都会执行一次。
vim /etc/rc.local
# 加入 mount /dev/sdb /opt/minio/data
# 重新加载 rc.local 文件
source /etc/rc.local
每台机器上安装好 minio;(安装在 /usr/local/minio 目录下,版本统一)
# 下载
wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio
# 修改权限
chmod +x minio
在四台虚拟机的 /usr/local/minio 下编写 minio.sh 启动脚本
#!/bin/bash
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=password
/usr/local/minio/minio server --config-dir /etc/minio --address :9000 --console-address :9001 \
http://192.168.64.100/opt/minio/data/data1 http://192.168.64.100/opt/minio/data/data2 \
http://192.168.64.100/opt/minio/data/data3 http://192.168.64.100/opt/minio/data/data4 \
http://192.168.64.102/opt/minio/data/data1 http://192.168.64.102/opt/minio/data/data2 \
http://192.168.64.102/opt/minio/data/data3 http://192.168.64.102/opt/minio/data/data4 \
http://192.168.64.103/opt/minio/data/data1 http://192.168.64.103/opt/minio/data/data2 \
http://192.168.64.103/opt/minio/data/data3 http://192.168.64.103/opt/minio/data/data4 \
http://192.168.64.104/opt/minio/data/data1 http://192.168.64.104/opt/minio/data/data2 \
http://192.168.64.104/opt/minio/data/data3 http://192.168.64.104/opt/minio/data/data4 &
给脚本修改权限
chmod 744 minio.sh
启动脚本
# 如果在 minio 的安装目录下 /usr/local/minio
./minio.sh
# 若不在安装目录下,则写全路径
/usr/local/minio/minio.sh
启动可能会报错
查看防火墙的状态关闭防火墙
systemctl status firewalld
# 临时关闭
systemctl stop firewalld
# 永久关闭
systemctl disable firewalld
脚本加入开机启动-Linux
在 /usr/lib/systemd/system 下编写服务
vim /usr/lib/systemd/system/minio.service
加入以下内容
#固定写法,换一下路径即可
#!/bin/sh
[Unit]
Description=xxx-service
Documentation=https://docs.minio.io/
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
# 脚本的位置
ExecStart=/usr/local/minio/minio.sh
WorkingDirectory=/opt/minio
PrivateTmp=true
[Install]
WantedBy=multi-user.target
添加权限
chmod +x /usr/lib/systemd/system/minio.service
可以一台一台的新建脚本,也可以用下列命令把建好的脚本拷贝给其他机器
# 先ssh连一下目标服务器
ssh 192.168.64.102
# 退出 192.168.64.102
exit
scp -r /usr/lib/systemd/system/minio.service 192.168.64.102:/usr/lib/systemd/system/minio.service
如果 ssh 由于秘钥问题连不上可用下面命令
ssh -o StrictHostKeyChecking=no 192.168.64.100
# 重新连接
启动
#将服务添加到开机自启服务中
systemctl enable minio.service
#系统服务刷新
systemctl daemon-reload
#启动服务
systemctl start minio.service
#查看服务状态
systemctl status minio
#停止服务
systemctl stop minio
#取消开机自启
systemctl disable minio
集群部署-Docker
看了好多人写的,都没成功,放着吧
Nginx 负载均衡
官网:https://nginx.org/en/download.html
Nginx 下载安装
# 下载 下载到当前目录
wget https://nginx.org/download/nginx-1.26.0.tar.gz
# 安装相关库
yum install gcc openssl openssl-devel pcre pcre-devel zlib zlib-devel -y
# 解压
tar -zxvf nginx-1.26.0.tar.gz
# 切换至解压后的nginx主目录
cd nginx-1.26.0/
# 在nginx主目录nginx-1.26.0下执行命令 --prefix是指定nginx安装路径
./configure --prefix=/usr/local/nginx
# 执行命令进行编译
make
# 执行命令进行安装
make install
# 安装完成建议删除 nginx-1.26.0 nginx 安装在了/usr/local
# 这个删除的是下载解压的文件
rm -rf nginx-1.26.0
Nginx 启动
# -c是指定配置文件
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
# 重启
/usr/local/nginx/sbin/nginx -s reload
Nginx 关闭
# 会将已经进来的请求处理完后再关闭
# 找出nginx的进程号
ps -ef | grep nginx
# QUIT 必须是大写
kill -QUIT 主pid
# 快速关闭会直接关闭,已经进来的请求也不会处理
ps -ef | grep nginx
# TERM 必须是大写
kill -TERM 主pid
Nginx配置检查
# 当修改Nginx配置文件后,可以使用Nginx命令进行配置文件语法检查,用于检查Nginx配置文件是否正确
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf -t
Nginx 修改配置文件
1、在http模块配置upstream
upstream api {
server 192.168.64.100:9000;
server 192.168.64.102:9000;
server 192.168.64.103:9000;
server 192.168.64.104:9000;
}
upstream webui {
server 192.168.64.100:9001;
server 192.168.64.102:9001;
server 192.168.64.103:9001;
server 192.168.64.104:9001;
}
2、在server模块里配置
location / {
#root html;
#index index.html index.htm;
proxy_pass http://api;
proxy_set_header Host $http_host;
proxy_set_header Server MinIO;
proxy_set_header Accept-Ranges bytes;
}
再写个server 指定 webui
server {
listen 50000;
server_name localhost;
location / {
proxy_pass http://webui;
}
}
测试访问
在地址栏输入:http://192.168.64.100:50000/ 可以正常访问 minio 后台
常见问题
服务器时间不同步
The difference between the request time and the server’s time is too large.
解决:
yum install ntpdate -y
ntpdate pool.ntp.org
上传的文件默认是不能访问的
http://ip:9000/存储桶/文件名
一、后台修改 bucke t 的访问策略
二、代码实现
@Test
public void createBucket() throws Exception {
String bucketName = "test1";
boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!bucketExists) {
// 创建bucket
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
//创建的时候设置访问策略 2012-10-17 不能改
String policyJsonString = "{\n" +
" \"Version\": \"2012-10-17\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Principal\": {\"AWS\": [\"*\"]},\n" +
" \"Action\": [\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\n" +
" \"Resource\": [\"arn:aws:s3:::"+bucketName+"\"]\n" +
" },\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Principal\": {\"AWS\": [ \"*\"]},\n" +
" \"Action\": [\"s3:DeleteObject\",\"s3:GetObject\", \"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\n" +
" \"Resource\": [\"arn:aws:s3:::"+bucketName+"/*\"]\n" +
" }\n" +
" ]\n" +
"}";
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
.bucket(bucketName)
.config(policyJsonString)
.build());
}