MinIO是一个由CNCF孵化的云原生服务,旨在在多租户环境中以可持续的方式进行扩展。orchestration(编排)平台如kubernetes为MinIO的扩展提供了非常好的支撑。MinIO可以用于机器学习,分析和应用程序数据工作负载的高性能基础架构。
MinIO特征
建立在web规模的规则之上,MinIO利用Web缩放器为对象存储带来了简单的缩放模型。在MinIO上,扩展从单个群集开始,该群集可以与其他MinIO群集联合以创建全局名称空间,并在需要时跨越多个数据中心。
与Amazon S3云存储服务兼容。Amazon S3 API是对象存储中的事实上的标准,而MinIO是事实上的S3兼容性标准。
轻量强大。极简主义是MinIO的指导性设计原则。简单性减少了出错的机会,提高了正常运行时间,提供了可靠性,同时也为性能奠定了基础。
Minio使用纠删码erasure code和checksum校验来保护数据免受硬件故障和无声数据损坏。纠删码是一种恢复丢失和损坏数据的数学算法, Minio采用Reed-Solomon code将对象拆分成N/2数据和N/2 奇偶校验块。如12块盘,一个对象会被分成6个数据块、6个奇偶校验块,即便丢失一半数量(N/2)的硬盘,仍可以从剩下的盘中的数据进行恢复。
部署分布式MinIO集群
在大数据领域,通常的设计理念都是无中心和分布式。分布式Minio可以让你将多块硬盘(甚至在不同的机器上)组成一个对象存储服务。由于硬盘分布在不同的节点上,分布式Minio避免了单点故障。
可靠性: 分布式Minio采用 纠删码来防范多个节点宕机和位衰减bit rot,分布式Minio至少需要4个硬盘,使用分布式Minio自动引入了纠删码功能。
高可用: 单机Minio服务存在单点故障,相反,如果是一个有N块硬盘的分布式Minio,只要有N/2硬盘在线,你的数据就是安全的。不过你需要至少有N/2+1个硬盘来创建新的对象。例如,一个16节点的Minio集群,每个节点16块硬盘,就算8台服务器宕机,这个集群仍然是可读的,不过你需要9台服务器才能写数据。
一致性: Minio在分布式和单机模式下,所有读写操作都严格遵守read-after-write一致性模型。
使用helm template方式部署minio
helm repo add minio https://helm.min.io/
helm template demo minio/minio --namespace minio \
--set persistence.size=100Gi \
--set accessKey=myaccesskey,secretKey=mysecretkey \
--set persistence.storageClass=local-storage \
--set service.type=NodePort \
--set mountPath=/export \
--set resources.requests.memory=256Mi \
--set resources.requests.cpu=100m \
--set resources.limits.memory=2Gi \
--set resources.limits.cpu=1000m \
--set mode=distributed,numberOfNodes=4 > minio-distributed.yaml
[root@k8s-test09 minio]# kubectl create ns minio
[root@k8s-test09 minio]# kubectl create -f minio-distributed.yaml -n minio
[root@k8s-test09 minio]# kubectl get po,svc -n minio -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/demo-minio-0 1/1 Running 0 78s 192.168.215.102 k8s-test09 <none> <none>
pod/demo-minio-1 1/1 Running 0 78s 192.168.234.7 k8s-test10 <none> <none>
pod/demo-minio-2 1/1 Running 0 78s 192.168.215.101 k8s-test09 <none> <none>
pod/demo-minio-3 1/1 Running 0 78s 192.168.234.8 k8s-test10 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/demo-minio NodePort 10.254.127.220 <none> 9000:32000/TCP 78s app=minio,release=demo
service/demo-minio-svc ClusterIP None <none> 9000/TCP 78s app=minio,release=demo复制
使用NodePort访问minio,新建一个demo的bucket,并上传文件
模拟故障,让一个节点处于Pending状态,测试数据的一致性
[root@k8s-test09 ~]# kubectl get po -n minio
NAME READY STATUS RESTARTS AGE
demo-minio-0 0/1 Pending 0 12s
demo-minio-1 1/1 Running 0 17m
demo-minio-2 1/1 Running 0 17m
demo-minio-3 1/1 Running 0 17m复制
上传附件测试
恢复minio集群,进入po查看元数据
[root@k8s-test09 ~]# kubectl -n minio exec -it demo-minio-0 -- sh
~ $ cd /export/demo/
/export/demo $ ls -lrt
total 0
drwxrwsr-x 3 1000 1000 65 Oct 6 04:50 photo-1466854076813-4aa9ac0fc347.jpeg
/export/demo $
/export/demo $ exit
[root@k8s-test09 ~]#
[root@k8s-test09 ~]# kubectl -n minio exec -it demo-minio-1 -- sh
~ $ cd /export/demo/
/export/demo $ ls -lrt
total 0
drwxr-sr-x 3 1000 1000 65 Oct 6 04:50 photo-1466854076813-4aa9ac0fc347.jpeg
drwxr-sr-x 3 1000 1000 65 Oct 6 05:01 test.jpg
/export/demo $复制
minio-0节点不会自动同步数据,数据存在一致性问题,需手动处理。这意味着每次故障后,都需要手动去同步数据,感觉minio应该会自动同步,还待挖掘。
安装MinIO客户端命令行工具
MinIO Client (mc)为ls,cat,cp,mirror,diff,find等UNIX命令提供了一种替代方案。它支持文件系统和兼容Amazon S3的云存储服务(AWS Signature v2和v4),Google云存储等
[root@k8s-test09 minio]# wget http://dl.minio.org.cn/client/mc/release/linux-amd64/mc
[root@k8s-test09 minio]# chmod +x mc
[root@k8s-test09 minio]# mv mc /usr/local/bin/
#命令行参数
COMMANDS:
ls list buckets and objects
mb make a bucket
rb remove a bucket
cp copy objects
mirror synchronize object(s) to a remote site
cat display object contents
head display first 'n' lines of an object
pipe stream STDIN to an object
share generate URL for temporary access to an object
find search for objects
sql run sql queries on objects
stat show object metadata
mv move objects
tree list buckets and objects in a tree format
du summarize disk usage recursively
lock set and get object lock configuration
retention set retention for object(s)
legalhold set legal hold for object(s)
diff list differences in object name, size, and date between two buckets
rm remove objects
event configure object notifications
ilm configure bucket lifecycle
watch listen for object notification events
policy manage anonymous access to buckets and objects
tag manage tags for bucket(s) and object(s)
admin manage MinIO servers
config configure MinIO client
update update mc to latest release复制
添加一个云存储
mc config host add myminio http://10.254.127.220:9000 myaccesskey mysecretkey --api s3v4
复制
myminio是云存储服务id
http://10.254.127.220:9000 是S3 endpoint,这里是minio的service CLUSTER-IP
myaccesskey 云存储服务(minio)的access
mysecretkey 云存储服务(minio)的key
s3v4 API签名是可选参数,默认情况下为"S3v4"
列出myminio上的所有存储桶,可以加上 --json --debug 等参数
[root@k8s-test09 ~]# mc --json ls myminio
{
"status": "success",
"type": "folder",
"lastModified": "2020-10-06T12:48:20.292+08:00",
"size": 0,
"key": "demo/",
"etag": "",
"url": "http://10.254.127.220:9000/"
}复制
在myminio上创建一个名叫"mybucket"的存储桶
[root@k8s-test09 ~]# mc mb myminio/mybucket
Bucket created successfully `myminio/mybucket`.复制
拷贝一个文本文件到对象存储,并查看文件的内容
[root@k8s-test09 ~]# mc cp myobject.txt myminio/mybucket
myobject.txt: 13 B / 13 B ┃▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓┃ 436 B/s 0s
[root@k8s-test09 ~]# mc cat myminio/mybucket/myobject.txt
Hello MinIO!复制
MinIO Client(mc)提供了“ admin”子命令来对MinIO部署执行管理任务。
COMMANDS:
service restart and stop all MinIO servers
update update all MinIO servers
info display MinIO server information
user manage users
group manage groups
policy manage policies defined in the MinIO server
config manage MinIO server configuration
heal heal disks, buckets and objects on MinIO server
profile generate profile data for debugging purposes
top provide top like statistics for MinIO
trace show http trace for MinIO server
console show console logs for MinIO server
prometheus manages prometheus config
kms perform KMS management operations
obd run on-board diagnostics
bucket manage buckets defined in the MinIO server复制
查看minio服务状态
[root@k8s-test09 ~]# mc admin info myminio
● demo-minio-0.demo-minio-svc.minio.svc.cluster.local:9000
Uptime: 32 minutes
Version: 2020-09-26T03:44:56Z
Network: 4/4 OK
Drives: 0/0 OK
● demo-minio-1.demo-minio-svc.minio.svc.cluster.local:9000
Uptime: 52 minutes
Version: 2020-09-26T03:44:56Z
Network: 4/4 OK
Drives: 0/0 OK
● demo-minio-2.demo-minio-svc.minio.svc.cluster.local:9000
Uptime: 53 minutes
Version: 2020-09-26T03:44:56Z
Network: 4/4 OK
Drives: 0/0 OK
● demo-minio-3.demo-minio-svc.minio.svc.cluster.local:9000
Uptime: 52 minutes
Version: 2020-09-26T03:44:56Z
Network: 4/4 OK
Drives: 0/0 OK
1.6 MiB Used, 1 Bucket, 1 Object
0 drives online, 0 drives offline复制
在MinIO上添加并启用新用户'newuser'
[root@k8s-test09 ~]# mc admin user add myminio/ newuser newuser123
Added user `newuser` successfully.
[root@k8s-test09 ~]# mc admin user enable myminio/ newuser
Enabled user `newuser` successfully.复制
列出MinIO上的所有用户
[root@k8s-test09 ~]# mc admin user list --json myminio/
{
"status": "success",
"accessKey": "newuser",
"userStatus": "enabled"
}复制
将'newuser'添加到MinIO上的“somegroup”组中。如果组不存在,则会创建该组
[root@k8s-test09 ~]# mc admin group add myminio somegroup newuser
Added members {newuser} to group somegroup successfully.复制
使用heal命令修复MinIO服务器上的磁盘,丢失的存储桶和对象。注意:此命令仅适用于MinIO擦除编码设置(独立和分布式)
更换新磁盘后修复MinIO集群,递归修复所有存储桶和对象
[root@k8s-test09 ~]# mc admin heal -r myminio
◓ mybucket
1/1 objects; 219 KiB in 1s
┌────────┬───┬─────────────────────┐
│ Green │ 4 │ 100.0% ████████████ │
│ Yellow │ 0 │ 0.0% │
│ Red │ 0 │ 0.0% │
│ Grey │ 0 │ 0.0% │
└────────┴───┴─────────────────────┘复制
递归修复指定存储桶上的MinIO集群
[root@k8s-test09 ~]# mc admin heal -r myminio/demo
◓ demo
0/0 objects; 0 B in 1s
┌────────┬───┬─────────────────────┐
│ Green │ 2 │ 100.0% ████████████ │
│ Yellow │ 0 │ 0.0% │
│ Red │ 0 │ 0.0% │
│ Grey │ 0 │ 0.0% │
└────────┴───┴─────────────────────┘复制
进入minio-0 查看数据已经同步,与其它节点数据一致
[root@k8s-test09 ~]# kubectl -n minio exec -it demo-minio-0 -- sh
~ $ cd /export/demo/
/export/demo $ ls -lrt
total 0
drwxrwsr-x 3 1000 1000 65 Oct 6 04:50 photo-1466854076813-4aa9ac0fc347.jpeg
drwxr-sr-x 3 1000 1000 65 Oct 6 05:48 test.jpg
/export/demo $复制
显示MinIO集群中自我修复过程的状态
[root@k8s-test09 ~]# mc admin heal myminio/
Background healing status:
● 0 item(s) scanned in total
● Never executed复制
获取分布式MinIO群集上10个最旧锁的列表
[root@k8s-test09 ~]# mc admin top locks myminio
Time Type Resource
1 hours WRITE .minio.sys/runDataCrawler.lock复制
更多命令使用请查看官方文档
MinIO-Go SDK
MinIO Go客户端SDK提供了简单的API,可以访问任何与Amazon S3兼容的对象存储。
示例程序,上传一个文件,并列出所有bucket及某个bucket下的所有文件
package main
import (
"context"
"fmt"
"log"
"net/url"
"time"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
)
func main() {
// minio 服务端
endpoint := "47.242.25.45:32000"
accessKeyID := "myaccesskey"
secretAccessKey := "mysecretkey"
bucketName := "mybucket"
locationName := "test"
useSSL := false
// 上传的文件
objectName := locationName + "/" + "demo.tar.gz"
filePath := "/tmp/demo.tar.gz"
contentType := "application/zip"
// 初始化minio客户端对象
minioClient, err := minio.New(endpoint, &minio.Options{
Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
Secure: useSSL,
})
if err != nil {
log.Fatalln(err)
}
// bucket不存在则创建
err = minioClient.MakeBucket(context.TODO(), bucketName, minio.MakeBucketOptions{Region: locationName})
if err != nil {
exists, errBucketExists := minioClient.BucketExists(context.TODO(), bucketName)
if errBucketExists == nil && exists {
log.Printf("We already own %s\n", bucketName)
} else {
log.Fatalln(err)
}
} else {
log.Printf("Successfully created %s\n", bucketName)
}
// 上传文件
n, err := minioClient.FPutObject(context.TODO(), bucketName, objectName, filePath, minio.PutObjectOptions{ContentType: contentType})
if err != nil {
log.Fatalln(err)
}
log.Printf("Successfully uploaded %s of size %v\n", objectName, n)
// 列出所有bucket
buckets, err := minioClient.ListBuckets(context.Background())
if err != nil {
log.Fatalln(err)
}
for _, bucket := range buckets {
log.Println(bucket)
}
// 列出bucket中匹配前缀的所有对象,忽略文件夹
for object := range minioClient.ListObjects(context.TODO(), bucketName, minio.ListObjectsOptions{Recursive: true}) {
if object.Err != nil {
fmt.Println(object.Err)
}
// 桶,文件名称,url的有效时间,url
URL, err := minioClient.PresignedGetObject(context.TODO(), bucketName, object.Key,time.Second*24*60*60, make(url.Values))
if err != nil {
log.Fatalln(err)
}
fmt.Printf("name: %s , modifiedtime: %v Size: %d , URL: %s\n",object.Key,object.LastModified,object.Size,URL)
}
复制
运行结果
查看上传的文件
[root@k8s-test09 ~]# mc ls myminio/mybucket/test
[2020-10-06 17:04:39 CST] 822KiB demo.tar.gz
[root@k8s-test09 ~]#复制