如何搭建 OSS 对象存储服务? - MinIO

3,346 阅读7分钟

背景

本文档主要描述如何使用 MinIO 搭建 OSS 对象存储服务

目标

  1. 搭建 OSS 服务,支持 https 访问
  2. 多站点部署副本集,实现高可用(容灾)

什么是 OSS

OSS 「Object Storage Service」,即对象存储服务。它是一种面向云计算的分布式存储服务,可以将海量的非结构化数据以对象的形式进行存储和管理。与传统的文件存储和块存储不同,对象存储将数据作为对象进行存储,每个对象都有唯一的标识符和元数据,可以通过 HTTP 或 HTTPS 等协议进行访问。

什么是 MinIO

MinIO 是一个对象存储解决方案,一款开源云存储软件,提供高性能分布式对象存储,提供了与 Amazon Web Services S3 兼容的API,并支持所有核心S3功能,专为大规模数据基础设施而设计。并且它在 GitHub 上拥有超过 26,000 颗星,有超过 680 名贡献者在为它工作。

MinIO 服务器存储所有类型的非结构化数据,例如照片、视频、日志文件等。它也可在开源 Apache V2 许可下使用,许多最强大的大数据和机器学习应用程序都使用 MinIO S3 对象存储。可以在 MinIO 网站上查看许多其他功能。

官网: min.io/

gihub: github.com/minio/minio

✅ Docker 部署 MinIO

参考文档:deploy-minio-single-node

配置文件

创建 /etc/default/minio 文件,并将以下内容保存到文件作为 MinIO 的环境变量

# /etc/default/minio,用于挂载到 MinIO 容器,设置 MinIO 的环境变量

# 设置 MinIO 服务的 root 帐号。
MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=admin123

# MINIO_VOLUMES sets the storage volume or path to use for the MinIO server.

MINIO_VOLUMES="/mnt/data"

# MINIO_SERVER_URL sets the hostname of the local machine for use with the MinIO Server
# MinIO assumes your network control plane can correctly resolve this hostname to the local machine

# Uncomment the following line and replace the value with the correct hostname for the local machine.

# 设置 Minio 的 API 域名 & 文件分享的地址,注意是 https,因为运行容器时已配置证书开启了 https 访问
MINIO_SERVER_URL="https://xxx.domain.com:9000"

配置证书

将主机域名的 ssl 证书拷贝并重命名到单独的文件夹下 /minio/certs

image.png

docker 运行 MinIO 容器

docker run -dt                                  \
  -p 9000:9000 -p 9090:9090                     \
  -v ~/minio/data:/mnt/data                             \
  -v /etc/default/minio:/etc/config.env         \
  -v /minio/certs:/tmp/certs \
  -e "MINIO_CONFIG_ENV_FILE=/etc/config.env"    \
  -e "MINIO_PUBLIC_ADDRESS=gzoffice.mojidict.com:9090" \
  --name "minio_local"                          \
  minio/minio server --console-address ":9090"  --address ":9000" --certs-dir /tmp/certs
命令解析
docker run -dt创建一个后台运行的 Docker 容器
-p 9000:9000 -p 9090:9090将容器内的端口 9000 和 9090 映射到主机的 9000 和 9090 端口
-v ~/minio/data:/mnt/data将主机上 ~/minio/data 目录挂载到容器内的 /mnt/data 目录,用于持久化存储数据
-v /etc/default/minio:/etc/config.env将主机上 /etc/default/minio 文件挂载到容器内的 /etc/config.env 文件,用于设置 Minio 的配置环境变量
-v /minio/certs:/tmp/certs将主机上 /minio/certs 目录挂载到容器内的 /tmp/certs 目录,用于存储 TLS 证书
-e "MINIO_CONFIG_ENV_FILE=/etc/config.env"设置 Minio 的配置环境变量文件路径为 /etc/config.env
-e "MINIO_PUBLIC_ADDRESS=``gzoffice.mojidict.com:9090``"设置 Minio 的公共访问地址为 gzoffice.mojidict.com:9090,该地址用于生成访问 Minio 对象存储的 URL
--name "minio_local"指定容器名称为 minio_local
minio/minio使用 Minio 的官方 Docker 镜像
server --console-address ":9090" --address ":9000" --certs-dir /tmp/certs启动 Minio 服务器,并设置控制台地址为 :9090,服务地址为 :9000,TLS 证书存储路径为 /tmp/certs

Docker 启动成功,访问 MinIO 管理后台:xxx.domain.com:9090

image.png

✅ MinIO 站点复制(Site Replication)

官方文档:Site Replication Overview

概述

Site Replication,即 站点复制,将多个独立的 MinIO 部署配置为称为对等站点的副本集群,支持将数据自动地从一个 MinIO 服务复制到另一个 MinIO 服务,在多个地理位置创建冗余备份,从而提高可用性、灵活性、备份以及灾难恢复。 image.png

站点复制 特点

参考文档:replicated-minio-deployments

  • MinIO 服务器端存储桶复制是一种自动存储桶级配置
  • MinIO 副本集的每个实例都可以承担读取和写入数据的角色,
  • MinIO 复制性能主要取决于每个对等站点之间的网络延迟。
  • MinIO 复制可以自动修复由于短暂或持续停机而导致部分或全部数据丢失的站点。
  • 复制配置完全在服务器端处理,采用 设置即忘(set-it-and-forget-it)的方式,即不需要以任何方式修改使用MinIO 的应用程序,一切都在服务器端处理

站点复制原理

参考文档:replication-processactive-active-replication

  • 站点复制建立在 双向主动-主动 框架的基础上,每个站点都能写入数据并触发数据复制的队列任务;

  • 默认双向复制规则,不存在从节点的说法;(也可配置为 主动-被动 的单向复制规则,相当于主从)

  • 配置站点复制规则的 MinIO 实例充当 “源站点”,而配置的远程 MinIO 实例充当 “目标站点”;采用双向、增量复制规则,自动同步新对象和对象变更,例如对象写入操作( PUT)、新对象版本、更改对象元数据

  • MinIO 使用一个复制队列系统,其中有多个并发复制工作进程在该队列上操作。MinIO 不断地从队列中复制和删除对象,同时扫描新的未复制对象以添加到队列中。

  • MinIO 将失败的复制操作重新排入队列,并重试这些操作,直到复制成功,以确保数据的完整性和可用性,而无需依赖 MinIO 扫描程序来注意未复制的对象版本。

  • 复制过程通常具有以下流程之一:

    • PENDING -> COMPLETED
    • PENDING -> FAILED -> COMPLETED

同步复制 & 异步复制

参考文档:synchronous-vs-asynchronous-replication

MinIO 支持为给定的远程目标实例,采用异步(默认)或同步复制。

  • 对于异步复制,MinIO 会在将对象放入复制队列之前完成原始的 PUT 操作。因此,在复制对象之前,发起客户端可以看到成功的 PUT 操作。虽然这可能会导致远程设备上的对象过时或丢失,但它减轻了由于复制负载而导致写入操作缓慢的风险。
  • 使用同步复制时,MinIO会在完成原始 PUT 操作之前尝试复制对象。无论复制尝试是否成功,MinIO都会返回成功的 PUT 操作。这降低了写操作缓慢的风险,但可能以远程位置上的对象陈旧或丢失为代价。

MinIO 强烈建议使用默认的异步站点复制

目前,MinIO 只建议跨两个数据中心进行复制。跨多个数据中心进行复制是可能的,但是,所涉及的复杂性和所需的性能权衡使得这实现起来相对困难(带宽、延迟)。具体参考:Basic Architectural Considerations

副本集搭建

具体参考官方部署文档:site-replication-tutorials

先决条件

  • 所有站点必须使用相同的 MinIO server 版本(部署方式参考 #Docker 部署 MinIO

  • 目标站点不能包含任何数据

    • 在设置时只有一个站点(源站点)可以有数据。其他站点不能存在任何 bucket、object;
    • 配置站点复制后,源站点上的任何数据都会复制到其他站点。
  • 站点已完全部署并可通过主机名或 IP 访问

  • 与配置中的所有其他站点共享 IDP (identity provider) 配置

  • 使用与其他已配置站点相同的根用户凭据

源站点配置 Site Replication:

image.png

image.png

源站点数据:

image.png

目标站点数据:

image.png

通过命令行工具 MinIO Clinet 查看 Replication 状态、待复制 Object 列表

MinIO Clinet API 文档:mc-replicate.html

暂时关闭 minio2,在 minio1 上传文件,复制失败,可通过 diff 查看未成功复制的数据列表:(重启 minio2 即可自动重新复制成功)

✅ Node.js 连接 & 管理 Minio

SDK API Referencemin.io/docs/minio/…

const Minio = require('minio')

// 创建Minio客户端对象
const minioClient = new Minio.Client({
  endPoint: 'your-minio-endpoint',
  port: 9000,
  useSSL: false,
  accessKey: 'access-key',  // 管理员创建
  secretKey: 'secret-key'   // 管理员创建
})

const bucketName = 'moji-test'  // 存储空间 bucket 名称
const objectName = 'test.png'   // 保存到 bucket 的文件对象名称
const filePath = 'files/test.png'

// 上传文件到 Minio
minioClient.fPutObject(bucketName, objectName, filePath, function(err, etag) {
  if (err) {
    return console.log(err)
  }
  console.log('File uploaded successfully')
  
  // 获取文件的签名链接,默认 7 天有效期
  const url = minioClient.presignedGetObject(bucketName, objectName)
  console.log('Signed URL:', url)
})

>>>
Signed URL: Promise {
  'https://xxx.domain.com:9001/moji-test/test22.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=sn92pbGHndL8T3YJ%2F20230417%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230417T062436Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=8865e435d049181ac0552fcf244df3f0c9dcff1b525b0ca0d67159a641b980b3'
}

参考资料