概述

Minio是云原生友好的开源分布式对象存储解决方案。官网上有部署的教程,但是在实验室环境,我有如下要求:

  1. 只有一台服务器;
  2. 希望通过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 ClassvolumeBindingMode: 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的说明进行配置

  1. 创建一个名为test的存储桶(bucket)
  2. 创建一个普通用户,配置read/write权限,添加Service Account,记录access keysecret
  3. 安装s3fs-fuse
sudo yum install epel-release
sudo yum install s3fs-fuse
  1. 创建凭据
echo ACCESS_KEY_ID:SECRET_ACCESS_KEY > ${HOME}/.passwd-s3fs
chmod 600 ${HOME}/.passwd-s3fs
  1. 创建挂载点目录
mkdir -p /path/to/mountpoint
  1. 挂载s3对象存储
s3fs test /path/to/mountpoint -o passwd_file=${HOME}/.passwd-s3fs -o url=https://<your api url>/ -o use_path_request_style
  1. 测试文件访问
echo "hello" > /path/to/mountpoint/a.txt
  1. 检查存储桶中存在该文件a.txt

限制

您应当了解对象存储技术与普通文件系统相比存在以下局限性:

  • 随机写、追加写会导致整个文件重写
  • 结构操作(比如列出目录)会比较慢
  • 仅能提供最终一致性,即读操作可能读到旧的内容
  • 文件和目录重命名不是原子操作
  • 多个客户端挂载同一个存储桶时,没有协调机制
  • 不支持硬链接
  • inotify仅能通知本机,不会通知其他客户端
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐