本文详解MinIO对象存储的部署配置、S3兼容API使用、分布式集群搭建等实践。
前言
对象存储越来越重要:
- 海量非结构化数据存储
- 图片、视频、备份文件
- 云原生应用标配
MinIO是最流行的开源对象存储:
- S3 API 100%兼容
- 高性能(单节点可达100Gbps)
- 部署简单,轻量级
- 支持分布式、纠删码
用MinIO搭建私有云存储,成本低、速度快。
一、单节点部署
1.1 Docker部署
bash
docker run -d \
--name minio \
-p 9000:9000 \
-p 9001:9001 \
-e MINIO_ROOT_USER=admin \
-e MINIO_ROOT_PASSWORD=admin123456 \
-v /data/minio:/data \
minio/minio server /data --console-address ":9001"
1.2 Docker Compose部署
yaml
# docker-compose.yml
version: '3.8'
services:
minio:
image: minio/minio:latest
container_name: minio
ports:
- "9000:9000" # API端口
- "9001:9001" # 控制台端口
environment:
MINIO_ROOT_USER: admin
MINIO_ROOT_PASSWORD: admin123456
volumes:
- ./data:/data
command: server /data --console-address ":9001"
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
bash
docker compose up -d
1.3 访问MinIO
控制台:http://服务器IP:9001
API地址:http://服务器IP:9000
用户名:admin
密码:admin123456
二、基本操作
2.1 创建Bucket
控制台 → Buckets → Create Bucket
- Bucket Name: my-bucket
- Versioning: 按需开启
- Object Locking: 按需开启
2.2 mc客户端
bash
# 安装mc客户端
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
mv mc /usr/local/bin/
# 配置别名
mc alias set myminio http://192.168.1.100:9000 admin admin123456
# 查看bucket
mc ls myminio
# 创建bucket
mc mb myminio/my-bucket
# 上传文件
mc cp myfile.txt myminio/my-bucket/
# 下载文件
mc cp myminio/my-bucket/myfile.txt ./
# 查看bucket内容
mc ls myminio/my-bucket/
# 删除文件
mc rm myminio/my-bucket/myfile.txt
# 同步目录
mc mirror ./local-folder myminio/my-bucket/
2.3 S3 API使用
Python示例:
python
import boto3
from botocore.client import Config
# 创建S3客户端
s3 = boto3.client(
's3',
endpoint_url='http://192.168.1.100:9000',
aws_access_key_id='admin',
aws_secret_access_key='admin123456',
config=Config(signature_version='s3v4')
)
# 创建bucket
s3.create_bucket(Bucket='my-bucket')
# 上传文件
s3.upload_file('local_file.txt', 'my-bucket', 'remote_file.txt')
# 下载文件
s3.download_file('my-bucket', 'remote_file.txt', 'downloaded_file.txt')
# 列出对象
response = s3.list_objects_v2(Bucket='my-bucket')
for obj in response.get('Contents', []):
print(obj['Key'])
# 生成预签名URL(临时访问链接)
url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': 'my-bucket', 'Key': 'remote_file.txt'},
ExpiresIn=3600 # 1小时有效
)
print(url)
Java示例:
java
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;
import java.net.URI;
public class MinioExample {
public static void main(String[] args) {
S3Client s3 = S3Client.builder()
.endpointOverride(URI.create("http://192.168.1.100:9000"))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create("admin", "admin123456")
))
.region(Region.US_EAST_1)
.build();
// 列出bucket
ListBucketsResponse response = s3.listBuckets();
response.buckets().forEach(bucket ->
System.out.println(bucket.name())
);
}
}
三、权限管理
3.1 创建用户
控制台 → Identity → Users → Create User
- Access Key: readonly-user
- Secret Key: readonly123456
- Policies: readonly(只读)
3.2 内置策略
| 策略 | 权限 |
|---|---|
| readonly | 只读所有bucket |
| readwrite | 读写所有bucket |
| diagnostics | 诊断权限 |
| writeonly | 只写权限 |
3.3 自定义策略
json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::my-bucket/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-bucket"
]
}
]
}
3.4 Bucket策略(公开访问)
json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::public-bucket/*"]
}
]
}
四、分布式集群
4.1 集群架构
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Node1 │ │ Node2 │ │ Node3 │ │ Node4 │
│ /data1 │ │ /data1 │ │ /data1 │ │ /data1 │
│ /data2 │ │ /data2 │ │ /data2 │ │ /data2 │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
│ │ │ │
└───────────┼───────────┼───────────┘
│
纠删码分布存储
(最多允许N/2节点故障)
4.2 Docker Compose集群
yaml
# docker-compose.yml
version: '3.8'
services:
minio1:
image: minio/minio:latest
hostname: minio1
volumes:
- ./data1-1:/data1
- ./data1-2:/data2
environment:
MINIO_ROOT_USER: admin
MINIO_ROOT_PASSWORD: admin123456
command: server --console-address ":9001" http://minio{1...4}/data{1...2}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
minio2:
image: minio/minio:latest
hostname: minio2
volumes:
- ./data2-1:/data1
- ./data2-2:/data2
environment:
MINIO_ROOT_USER: admin
MINIO_ROOT_PASSWORD: admin123456
command: server --console-address ":9001" http://minio{1...4}/data{1...2}
minio3:
image: minio/minio:latest
hostname: minio3
volumes:
- ./data3-1:/data1
- ./data3-2:/data2
environment:
MINIO_ROOT_USER: admin
MINIO_ROOT_PASSWORD: admin123456
command: server --console-address ":9001" http://minio{1...4}/data{1...2}
minio4:
image: minio/minio:latest
hostname: minio4
volumes:
- ./data4-1:/data1
- ./data4-2:/data2
environment:
MINIO_ROOT_USER: admin
MINIO_ROOT_PASSWORD: admin123456
command: server --console-address ":9001" http://minio{1...4}/data{1...2}
nginx:
image: nginx:latest
ports:
- "9000:9000"
- "9001:9001"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- minio1
- minio2
- minio3
- minio4
4.3 Nginx负载均衡配置
nginx
# nginx.conf
events {
worker_connections 1024;
}
http {
upstream minio_api {
server minio1:9000;
server minio2:9000;
server minio3:9000;
server minio4:9000;
}
upstream minio_console {
server minio1:9001;
server minio2:9001;
server minio3:9001;
server minio4:9001;
}
server {
listen 9000;
location / {
proxy_pass http://minio_api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 9001;
location / {
proxy_pass http://minio_console;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
五、跨站点同步
5.1 场景
需求:
- 总部MinIO存储主数据
- 分部MinIO作为副本或缓存
- 两地网络不通
5.2 组网方案
使用组网软件(如星空组网)打通网络:
┌─────────────────────────────────────────────────────────┐
│ 组网虚拟局域网 │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ 总部MinIO │ │ 分部MinIO │ │
│ │ 10.10.0.1 │←────→│ 10.10.0.2 │ │
│ │ :9000 │ 同步 │ :9000 │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
5.3 配置站点复制
bash
# 在总部MinIO配置
mc admin replicate add myminio http://10.10.0.2:9000 \
--access-key admin --secret-key admin123456
# 或使用mc mirror同步
mc mirror --watch myminio/my-bucket remote-minio/my-bucket
5.4 客户端访问就近节点
python
# 应用根据网络环境选择MinIO节点
MINIO_ENDPOINTS = {
'headquarters': 'http://10.10.0.1:9000',
'branch': 'http://10.10.0.2:9000'
}
# 使用就近节点
endpoint = MINIO_ENDPOINTS.get(current_location, MINIO_ENDPOINTS['headquarters'])
六、与应用集成
6.1 Spring Boot集成
xml
<!-- pom.xml -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.7</version>
</dependency>
java
@Configuration
public class MinioConfig {
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint("http://192.168.1.100:9000")
.credentials("admin", "admin123456")
.build();
}
}
@Service
public class FileService {
@Autowired
private MinioClient minioClient;
public String uploadFile(MultipartFile file, String bucket) {
String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucket)
.object(fileName)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build());
return fileName;
}
public InputStream downloadFile(String bucket, String fileName) {
return minioClient.getObject(GetObjectArgs.builder()
.bucket(bucket)
.object(fileName)
.build());
}
}
6.2 文件直传(前端直传)
javascript
// 1. 后端生成预签名URL
// 2. 前端直接上传到MinIO
async function uploadFile(file) {
// 获取预签名URL
const response = await fetch('/api/presigned-url', {
method: 'POST',
body: JSON.stringify({ filename: file.name })
});
const { url } = await response.json();
// 直接上传到MinIO
await fetch(url, {
method: 'PUT',
body: file,
headers: {
'Content-Type': file.type
}
});
}
七、监控与告警
7.1 Prometheus指标
bash
# 启用Prometheus指标
mc admin prometheus generate myminio
# 配置Prometheus
scrape_configs:
- job_name: minio
metrics_path: /minio/v2/metrics/cluster
static_configs:
- targets: ['192.168.1.100:9000']
7.2 关键指标
| 指标 | 说明 |
|---|---|
| minio_bucket_usage_total_bytes | Bucket使用量 |
| minio_node_disk_free_bytes | 磁盘剩余空间 |
| minio_s3_requests_total | 请求总数 |
| minio_s3_requests_errors_total | 错误请求数 |
八、总结
MinIO对象存储要点:
- 部署简单:Docker一行命令
- S3兼容:无缝替换AWS S3
- 分布式:纠删码保证数据安全
- 权限管理:IAM策略控制
- 跨站点:组网后同步复制
使用场景:
☑ 图片/视频存储
☑ 日志归档
☑ 数据备份
☑ AI训练数据集
☑ 云原生应用存储后端
参考资料
- MinIO官方文档:https://min.io/docs/minio/linux/index.html
- MinIO GitHub:https://github.com/minio/minio
- MinIO SDK文档:https://min.io/docs/minio/linux/developers/minio-drivers.html
💡 建议:生产环境至少4节点集群,启用纠删码。单节点仅用于开发测试。