K8S部署Minio经验心得
概述
Minio是云原生友好的开源分布式对象存储解决方案。官网上有部署的教程,但是在实验室环境,我有如下要求:
- 只有一台服务器;
- 希望通过Ingress开放console和api,因此希望取消默认的TLS选项;
在部署过程中,对于Minio的部署有如下心得,与大家进行分享。
部署Minio Operator
参照官网即可。
部署Minio租户
准备PV
参照官网。其中NODE-NAME
应当改为node的名字,如下所示:
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-disk-0
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage
local:
path: /data/minio/0
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- vm-12-10-centos
创建租户时要求至少提供4个卷。因此参照上述PV定义创建4个。如果你打算创建一个40Gi的存储池,应当准备4个10Gi的PV。另外,需要注意storageClassName
名字的正确性。
【注意】如果重新创建租户,本地路径应当重新删除,再创建PV,否则会出现这样的错误:
Detected unexpected disk ordering refusing to use the disk
Unable to initialize backend: Storage resources are insufficient for the read operation .minio.sys/pool.bin
创建租户
参照官网,但是由于我们只有一台服务器,因此命令中的参数应该改成:
kubectl minio tenant create minio-tenant-1 \
--servers 1 \
--volumes 4 \
--capacity 40Gi \
--storage-class local-storage \
--namespace minio-tenant-1
【注意】创建租户后,请记住admin用户的密码。
通过Ingress访问Minio
Minio Operator Console可以对所有租户进行管理,在minio-operator
命名空间可以看到console服务已经开启了http/https访问,operator console的端口为9090:
$ kubectl get svc -n minio-operator
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
console ClusterIP 10.10.219.125 <none> 9090/TCP,9443/TCP 15d
operator ClusterIP 10.10.169.204 <none> 4222/TCP,4221/TCP 15d
租户Console(Tenant Console)可以对本租户的资源进行管理。在minio-tenant-1
命名空间可以看到服务的情况
$ kubectl get svc -n minio-tenant-1
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
minio ClusterIP 10.10.252.104 <none> 443/TCP 112m
minio-tenant-1-console ClusterIP 10.10.120.162 <none> 9443/TCP 112m
minio-tenant-1-hl ClusterIP None <none> 9000/TCP 112m
这里租户空间中的服务均为https服务,因此为了能被Ingress访问,应该去掉TLS加密。可以通过Minio Operator Console将TLS加密选项去掉。
我们先将如下三个Ingress路径配置上:
- minio-operator-console.yourdomain.com:operator console
- minio.yourdomain.com:租户api
- minio-console.yourdomain.com:租户console
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
generation: 1
name: sharework-minio
namespace: <your namespace>
spec:
ingressClassName: nginx
tls:
- hosts:
- minio-operator-console.yourdomain.com
- minio.yourdomain.com
- minio-console.yourdomain.com
secretName: sharework-secrets
rules:
- host: minio-operator-console.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: minio-operator-console
port:
number: 9090
- host: minio-console.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: minio-console
port:
number: 9090
- host: minio.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: minio
port:
number: 80
---
apiVersion: v1
kind: Service
metadata:
name: minio-operator-console
namespace: <your namespace>
spec:
type: ExternalName
externalName: console.minio-operator.svc.cluster.local
---
apiVersion: v1
kind: Service
metadata:
name: minio-console
namespace: <your namespace>
spec:
type: ExternalName
externalName: minio-tenant-1-console.minio-tenant-1.svc.cluster.local
---
apiVersion: v1
kind: Service
metadata:
name: minio
namespace: <your namespace>
spec:
type: ExternalName
externalName: minio.minio-tenant-1.svc.cluster.local
为Operator Console创建Ingress后,可以输入JWT通过minio-operator-console.yourdomain.com
访问Operator Console。JWT获得方式如下:
kubectl minio proxy
进入Operator Console后,选择Tenants->minio-tenant-1->Security->TLS,将选项关闭,在界面中选择重启Tenant。
可以看到服务改成了http方式了,如下所示:
$ kubectl get svc -n minio-tenant-1
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
minio ClusterIP 10.10.252.104 <none> 80/TCP 112m
minio-tenant-1-console ClusterIP 10.10.120.162 <none> 9090/TCP 112m
minio-tenant-1-hl ClusterIP None <none> 9000/TCP 112m
【注意】根据Tenant的spec,设置
requestAutoCert: false
应该也可以禁用TLS,但是在尝试时出现各种错误,没有成功通过事先定义的yaml来部署一个tenant,最后都是用的命令行方式创建的。
了解PVC绑定过程
首先,通过Storage Class的volumeBindingMode: WaitForFirstConsumer
的指定,可以保证PVC在绑定PV前,会根据Pod对Node的要求进行筛选:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
然后,我可以看到Pod中定义了podAntiAffinity
,其规则为,如果Node的v1.min.io/tenant
标签中包含租户名,则不能再被调度到该节点(即对每个Node而言,只会为每个租户创建一个Pod),如下所示:
apiVersion: minio.min.io/v2
kind: Tenant
metadata:
generation: 1
name: minio-tenant-1
namespace: minio-tenant-1
spec:
image: minio/minio:RELEASE.2022-05-23T18-45-11Z
pools:
- affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: v1.min.io/tenant
operator: In
values:
- minio-tenant-1
topologyKey: kubernetes.io/hostname
servers: 1
volumeClaimTemplate:
apiVersion: v1
kind: PersistentVolumeClaims
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: local-storage
volumesPerServer: 4
requestAutoCert: true
如果由于某些意外Node的标签没有清除,则Pod不能被调度到这个Node。
【注意】如果所创建的PV不满足所有PVC申请的要求,则会出现下列提示
$ kubectl describe pod <tenant-pod>
Warning FailedScheduling 30m (x920 over 15h) default-scheduler 0/1 nodes are available: 1 node(s) didn't find available persistent volumes to bind.
测试
参考s3fs-fuse的说明进行配置
- 创建一个名为
test
的存储桶(bucket) - 创建一个普通用户,配置read/write权限,添加Service Account,记录access key和secret
- 安装s3fs-fuse
sudo yum install epel-release
sudo yum install s3fs-fuse
- 创建凭据
echo ACCESS_KEY_ID:SECRET_ACCESS_KEY > ${HOME}/.passwd-s3fs
chmod 600 ${HOME}/.passwd-s3fs
- 创建挂载点目录
mkdir -p /path/to/mountpoint
- 挂载s3对象存储
s3fs test /path/to/mountpoint -o passwd_file=${HOME}/.passwd-s3fs -o url=https://<your api url>/ -o use_path_request_style
- 测试文件访问
echo "hello" > /path/to/mountpoint/a.txt
- 检查存储桶中存在该文件
a.txt
限制
您应当了解对象存储技术与普通文件系统相比存在以下局限性:
- 随机写、追加写会导致整个文件重写
- 结构操作(比如列出目录)会比较慢
- 仅能提供最终一致性,即读操作可能读到旧的内容
- 文件和目录重命名不是原子操作
- 多个客户端挂载同一个存储桶时,没有协调机制
- 不支持硬链接
- inotify仅能通知本机,不会通知其他客户端
更多推荐
所有评论(0)