MinIO对象存储搭建与S3兼容实战

本文详解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对象存储要点:

  1. 部署简单:Docker一行命令
  2. S3兼容:无缝替换AWS S3
  3. 分布式:纠删码保证数据安全
  4. 权限管理:IAM策略控制
  5. 跨站点:组网后同步复制

使用场景:

复制代码
☑ 图片/视频存储
☑ 日志归档
☑ 数据备份
☑ AI训练数据集
☑ 云原生应用存储后端

参考资料

  1. MinIO官方文档:https://min.io/docs/minio/linux/index.html
  2. MinIO GitHub:https://github.com/minio/minio
  3. MinIO SDK文档:https://min.io/docs/minio/linux/developers/minio-drivers.html

💡 建议:生产环境至少4节点集群,启用纠删码。单节点仅用于开发测试。

复制代码
相关推荐
济南java开发,求内推2 天前
MINIO升级版本至:RELEASE.2024-04-06T05-26-02Z
minio
分布式存储与RustFS2 天前
MinIO替代方案精选:RustFS深度评测与选型指南
人工智能·rust·开源项目·对象存储·minio·企业存储·rustfs
空中楼阁,梦幻泡影5 天前
Docker安装MinIO
运维·docker·容器·minio·存储
分布式存储与RustFS5 天前
MinIO替代方案与团队适配性分析:RustFS如何匹配不同规模团队?
人工智能·rust·开源项目·对象存储·minio·企业存储·rustfs
分布式存储与RustFS5 天前
MinIO替代方案生态集成指南:RustFS如何无缝融入现代技术栈
rust·github·开源项目·对象存储·minio·企业存储·rustfs
分布式存储与RustFS8 天前
开源存储新变局:MinIO步入维护期后的五大替代方案深度解析
开源·对象存储·minio·高可用·企业存储·rustfs
分布式存储与RustFS8 天前
RustFS:基于Rust的高性能分布式对象存储,重新定义数据存储新标准!
人工智能·wpf·对象存储·minio·高可用·企业存储·rustfs
ejinxian11 天前
MinIO 国产化替代品Ceph、Garage 、RustFS
ceph·minio·rustfs·garage