rustfs介绍
RustFS 是用 Rust 从零写成的分布式对象存储,完全兼容 S3 协议。处理小对象时,吞吐量达到 MinIO 的 2.3 倍;许可证选用宽松的 Apache 2.0(MinIO 为 AGPLv3)。WORM 合规、加密、多站点复制——企业级功能一应俱全。
项目目前仍处于 Beta 阶段,但对于被 MinIO 协议卡住的团队,它已经是最值得关注的替代选项。

本课程就从rustfs的安装、界面基本操作、基于s3协议的go语言操作以及rustfs的分布式部署进行课程学习
rustfs中文官方文档:https://docs.rustfs.com.cn/installation/
rustfs的安装
还是首推使用docker进行rustfs的安装,主要是为了方便做版本管理
直接两条命令快速搞定
mkdir -p rustfs/data && chown -R 10001:10001 rustfs
docker run -d --name rustfs -p 9000:9000 -p 9001:9001 -v $(pwd)/rustfs/data:/data rustfs/rustfs:1.0.0-alpha.80 /data
默认用户名密码都是 rustfsadmin
如果需要修改,配置RUSTFS_ACCESS_KEY,RUSTFS_SECRET_KEY环境变量
docker run -d --name rustfs -p 9000:9000 -e RUSTFS_ACCESS_KEY="fengfeng" -e RUSTFS_SECRET_KEY="12345678" -p 9001:9001 -v $(pwd)/rustfs/data:/data rustfs/rustfs:1.0.0-alpha.80 /data
或者使用docker-compose
version: "3.9"
services:
rustfs:
image: rustfs/rustfs:1.0.0-alpha.80
container_name: rustfs
ports:
- "9000:9000"
- "9001:9001"
environment:
- RUSTFS_VOLUMES=/data
volumes:
- ./data:/data
restart: unless-stopped
9001端口就是rustfs的web管理界面,默认用户名密码都是 rustfsadmin

9000端口就是s3 api接口的端口
rustfs web界面的基本操作
存储桶操作
创建和minio的区别不大,都有版本控制、对象锁、存储桶大小限制
区别就是版本控制目前没有前缀过滤

修改存储桶权限
存储桶右边有一个编辑,点开就可以更改它的访问策略

文件的访问路径是 http://host/<桶名>/<对象名>
用户操作
创建一个只能查看文件列表的用户
在用户菜单创建一个只有readonly策略的用户,然后可以打开存储桶的访问策略

然后登录新创建的用户,它能看到的页面是这样的

默认的readonly是直接存储桶列表、对象下载策略的,没有对象列表策略的
所以点进存储桶会报错

所以可以自定义一个策略,分配给用户
{
"ID": "",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"NotAction": [],
"Resource": [
"arn:aws:s3:::*"
],
"NotResource": [],
"Condition": {}
}
]
}
rustfs预览图片的方式是直接将认证信息带到查询参数上的,所以存储桶私有的情况下,访问这个预览地址也是可以访问到的
s3 api操作
不想改之前的代码,可以直接用minio的那个客户端
或者可以用go s3这个客户端
本课程的minio-go版本
github.com/minio/minio-go/v7 v7.0.97 // indirect
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"io"
"os"
)
var client *minio.Client
var endPoint = "192.168.80.188:9000"
func init() {
accessKey := "rustfsadmin"
accessSecret := "rustfsadmin"
// 初始化minio客户端
_client, err := minio.New(endPoint, &minio.Options{
Creds: credentials.NewStaticV4(accessKey, accessSecret, ""),
Secure: false,
})
if err != nil {
fmt.Println(err)
os.Exit(0)
}
client = _client
}
func bucketList() {
list, err := client.ListBuckets(context.Background())
if err != nil {
fmt.Println(err)
return
}
for _, info := range list {
fmt.Println(info.Name)
}
}
func bucketCreate() {
err := client.MakeBucket(context.Background(), "demo2", minio.MakeBucketOptions{})
fmt.Println(err)
}
func uploadFile1() {
info, err := client.FPutObject(context.Background(), "demo2", "0114/ssh隧道命令.jpg", "ssh隧道命令.jpg", minio.PutObjectOptions{
UserMetadata: map[string]string{
"userId": "1",
"userIp": "2.5.21.22",
},
})
if err != nil {
fmt.Println(err)
return
}
byteData, _ := json.Marshal(info)
fmt.Println(string(byteData))
}
func fileList() {
ch := client.ListObjects(context.Background(), "demo2", minio.ListObjectsOptions{
Recursive: true,
Prefix: "uploads",
WithMetadata: true,
MaxKeys: 1,
})
for info := range ch {
fmt.Println(info.Key, info.LastModified, info.UserMetadata)
}
}
func main() {
//bucketCreate()
//bucketList()
uploadFile1()
fileList()
}
rustfs配置SSL
参考文档:https://docs.rustfs.com.cn/integration/tls-configured.html
证书对的名称必须为
rustfs_cert.pem和rustfs_key.pem
先生成证书
#!/bin/bash
# 证书有效期(天)
VALID_DAYS=3650
# 证书输出目录(和 docker-compose.yml 同目录)
CERT_DIR="./certs"
# 1. 创建证书目录
mkdir -p ${CERT_DIR}
cat > ${CERT_DIR}/cert_ssl.conf <<EOF
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
prompt = no
[req_distinguished_name]
C = CN
ST = Beijing
L = Beijing
O = MyOrg
OU = MyDept
CN = 192.168.80.174
[v3_req]
basicConstraints = CA:TRUE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
IP.1 = 192.168.80.174
IP.2 = 192.168.80.176
IP.3 = 127.0.0.1
EOF
openssl req -x509 -nodes -days ${VALID_DAYS} -newkey rsa:2048 -keyout ${CERT_DIR}/rustfs_key.pem -out ${CERT_DIR}/rustfs_cert.pem -config ${CERT_DIR}/cert_ssl.conf
# 4. 清理临时配置文件(可选)
rm -f ${CERT_DIR}/cert_ssl.conf
# 5. 验证证书(输出关键信息)
echo -e "\n证书生成完成!路径:${CERT_DIR}"
echo "证书包含的 SAN 扩展:"
openssl x509 -in ${CERT_DIR}/rustfs_cert.pem -text -noout | grep -A 1 "Subject Alternative Name"
docker的方式
docker run -d --name rustfs1 -e RUSTFS_TLS_PATH=/opt/tls/ -v /opt/rustfs_study/rustfs/certs:/opt/tls -p 9000:9000 -p 9001:9001 -v /opt/rustfs/data/:/data rustfs/rustfs:1.0.0-alpha.80
docker compose的方式
version: "3.9"
services:
rustfs:
image: rustfs/rustfs:1.0.0-alpha.80
container_name: rustfs
ports:
- "9000:9000"
- "9001:9001"
environment:
- RUSTFS_VOLUMES=/data
- RUSTFS_TLS_PATH=/opt/tls/
volumes:
- /opt/rustfs/data/:/data
- /opt/rustfs_study/rustfs/certs/:/opt/tls/
restart: unless-stopped
分布式部署
用docker compose的方式
目前我测试下来,只能用docker的host模式可以部署成功,其他发方式好像不太行
有几个注意点需要注意:
- RUSTFS_VOLUMES必须是连续的主机名,一般通过修改hosts来完成
先修改hosts的ip映射,这样就可以设置连续的域名节点了
192.168.80.188 node0
192.168.80.189 node1
先批量创建目录
rm -rf /opt/rustfs
mkdir -p /opt/rustfs/data{0..3} && chown -R 10001:10001 /opt/rustfs
version: "3.9"
services:
rustfs:
image: rustfs/rustfs:1.0.0-alpha.80
container_name: rustfs
environment:
- RUSTFS_VOLUMES=http://node{0...1}:9000/data{0...3}
- RUSTFS_ACCESS_KEY=rustfsadmin
- RUSTFS_SECRET_KEY=rustfsadmin
volumes:
- /opt/rustfs/data0/:/data0
- /opt/rustfs/data1/:/data1
- /opt/rustfs/data2/:/data2
- /opt/rustfs/data3/:/data3
network_mode: host
restart: unless-stopped