004.MinIO-DirectPV分散式儲存部署

木二發表於2024-08-24

MinIO部署介紹

部署概述

Kubernetes hostpath、local和本地靜態配置都存在需要事先在node節點準備好可用的塊儲存或檔案系統,例如對插入的硬碟,或者磁碟陣列做分割槽格式化,檔案系統則需提前建立好Kubernetes即將利用的掛載目錄,並且兩種方法都會有親和性限制,無法做到讓Kubernetes自身的去排程讓資料卷分佈在不同的node節點上。

若利用傳統的SAN或者NAS的CSI儲存驅動(網路PV)來為minio叢集提供儲存,minio叢集本身就分散式儲存和保障高可用的特點,不僅會在資料路徑中增加另一層複製/擦除編碼和額外的網路躍點。這種額外的分解層還會導致複雜性增加和效能下降的問題。

而DirectPV可以解決如上問題,DirectPV做到了跨服器發現可用儲存資源、跨服器格式化儲存、建立供Kubernetes PV使用的儲存池,由Kubernetes API透過DirectPV CSI排程儲存資源為POD分配直連式儲存PV,分散式地在node節點建立符合PVC申請要求的PV。DirectPV建立的儲存資源統一由部署DirectPV的節點監視和維護。

通俗點講,相當於在master節點部署DirectPV後,只需在node節點插入硬碟或者組建磁碟陣列,後續的格式化只需在安裝了DirectPV的master節點上操作,node節點無需後續操作,PV由Kubernetes自行排程和建立,並由PV卷將資料持久化。

DirectPV更多介紹參考:002.DirectPV介紹及安裝

基於如上考慮,本實驗Kubernetes部署Minio叢集儲存,選擇使用DirectPV CSI作為分散式儲存的最佳實踐。
同時minio官方支援透過簡單的快速部署,以便於進行基礎測試:

curl https://raw.githubusercontent.com/minio/docs/master/source/extra/examples/minio-dev.yaml -O
kubectl apply -f minio-dev.yaml

參考官方: 快速部署MinIO

minio叢集特性

每個minio叢集節點上由Kubernetes排程,而每個叢集節點的驅動器使用的PV由DirectPV排程,也就是說驅動器實際使用的儲存資源是由DirectPV隨機的從屬於Kubernetes的DirectPV儲存池中分配出來的,那實際的資料會隨機的分佈在node節點上的硬碟上,只要node節點硬碟數量較多,很大程度上可以規避硬碟單點故障的問題。

  • 分散式
    minio叢集將資料分佈在每個minio叢集節點上,每個叢集節點至少擁有4個驅動器,資料被均勻分佈在每個叢集節點的驅動器上,一半的驅動器空間用於資料備份利用,一半的空間用於儲存。

  • 高可用
    minio叢集的高可用特性,即驅動器只要有總數的N/2線上,即可完整的同步和還原資料,解決了硬碟單點故障導致資料丟失的問題。只要minio的叢集節點數量夠多,也能規避minio叢集節點故障大面積的驅動器掉線導致儲存資料丟失的問題。

MinIO部署

部署規劃

  • Kubernetes 安裝
    本實驗不涉及 Kubernetes 部署, Kubernetes 部署參考 Kubernetes_v1.30.3高可用部署架構二

  • 節點規劃
    已完成部署的Kubernetes叢集的規劃及磁碟相關資訊如下:

主機 IP 磁碟 備註
master01 172.24.10.11 —— master節點
master02 172.24.10.12 —— master節點
master03 172.24.10.13 —— master節點
worker01 172.24.10.14 /dev/nvme0n2 worker節點+ MinIO 節點 + DirectPV節點
worker02 172.24.10.15 /dev/nvme0n2 worker節點+ MinIO 節點 + DirectPV節點
worker03 172.24.10.16 /dev/nvme0n2 worker節點+ MinIO 節點 + DirectPV節點

叢集VIP: 172.24.10.100
相關域名均能正常解析,可透過hosts解析相關域名至 VPI 。

DirectPV部署

DirectPV部署安裝參考:002.DirectPV介紹及安裝

通常安裝完DirectPV後會自動生成預設的 directpv-min-io StorageClass 。

[root@master01 directpv]# kubectl get sc -o wide
NAME                 PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
directpv-min-io      directpv-min-io      Delete          WaitForFirstConsumer   true                   11h

配置MinIO

根據當前規劃,參考 DirectPV部署MinIO儲存官方yaml 進行修改。

也可參考 MinIO官方yaml 修改。

當前版本的minio把API埠和WebUI埠進行了區分,本實驗API保留9000,webui配置為9090。
部署在獨立的namespace minio-dev中。

[root@master01 minio]# curl https://raw.githubusercontent.com/minio/docs/master/source/extra/examples/minio-dev.yaml -O

[root@master01 minio]# vim minio-dev.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: minio-dev
  labels:
    name: minio-dev

---
kind: Service
apiVersion: v1
metadata:
  name: minio
  namespace: minio-dev
  labels:
    app: minio
spec:
  selector:
    app: minio
  type: NodePort
  ports:
    - name: api
      port: 9000
      protocol: TCP
      targetPort: 9000
      nodePort: 9000
    - name: webui
      port: 9090
      protocol: TCP
      targetPort: 9090
      nodePort: 9090
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: minio
  namespace: minio-dev
  labels:
    app: minio
spec:
  serviceName: "minio"
  replicas: 4
  selector:
    matchLabels:
      app: minio
  template:
    metadata:
      labels:
        app: minio
        directpv.min.io/organization: minio
        directpv.min.io/app: minio-example
        directpv.min.io/tenant: tenant-1
    spec:
      containers:
      - name: minio
        image: minio/minio
        env:
        - name: MINIO_ACCESS_KEY
          value: minio
        - name: MINIO_SECRET_KEY
          value: minio123
        volumeMounts:
        - name: minio-data-1
          mountPath: /data1
        - name: minio-data-2
          mountPath: /data2
        - name: minio-data-3
          mountPath: /data3
        - name: minio-data-4
          mountPath: /data4
        args:
        - "server"
        - "http://minio-{0...3}.minio.minio-dev.svc.cluster.local/data{1...4}"
        - "--console-address"
        - ":9090"
  volumeClaimTemplates:                 #配置StorageClass
  - metadata:
      name: minio-data-1
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
      storageClassName: directpv-min-io #配置已存在的storageClass
  - metadata:
      name: minio-data-2
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
      storageClassName: directpv-min-io #配置已存在的storageClass
  - metadata:
      name: minio-data-3
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
      storageClassName: directpv-min-io #配置已存在的storageClass
  - metadata:
      name: minio-data-4
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
      storageClassName: directpv-min-io #配置已存在的storageClass

正式部署

[root@master01 minio]# kubectl apply -f minio-dev.yaml

[root@master01 minio]# kubectl -n minio-dev get all -o wide
NAME          READY   STATUS    RESTARTS   AGE     IP             NODE       NOMINATED NODE   READINESS GATES
pod/minio-0   1/1     Running   0          2m42s   10.10.30.123   worker02   <none>           <none>
pod/minio-1   1/1     Running   0          2m33s   10.10.196.75   worker04   <none>           <none>
pod/minio-2   1/1     Running   0          2m25s   10.10.5.11     worker01   <none>           <none>
pod/minio-3   1/1     Running   0          2m16s   10.10.19.65    worker03   <none>           <none>

NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                       AGE     SELECTOR
service/minio   NodePort   10.20.113.61   <none>        9000:9000/TCP,9090:9090/TCP   2m42s   app=minio

NAME                     READY   AGE     CONTAINERS   IMAGES
statefulset.apps/minio   4/4     2m42s   minio        minio/minio
[root@master01 minio]# kubectl directpv list drives
┌──────────┬─────────┬──────────────────────────┬────────┬────────┬─────────┬────────┐
│ NODE     │ NAME    │ MAKE                     │ SIZE   │ FREE   │ VOLUMES │ STATUS │
├──────────┼─────────┼──────────────────────────┼────────┼────────┼─────────┼────────┤
│ worker01 │ nvme0n2 │ VMware Virtual NVMe Disk │ 20 GiB │ 16 GiB │ 4       │ Ready  │
│ worker02 │ nvme0n2 │ VMware Virtual NVMe Disk │ 20 GiB │ 16 GiB │ 4       │ Ready  │
│ worker03 │ nvme0n2 │ VMware Virtual NVMe Disk │ 20 GiB │ 16 GiB │ 4       │ Ready  │
│ worker04 │ nvme0n2 │ VMware Virtual NVMe Disk │ 20 GiB │ 16 GiB │ 4       │ Ready  │
└──────────┴─────────┴──────────────────────────┴────────┴────────┴─────────┴────────┘

[root@master01 minio]# kubectl -n minio-dev get pvc

015

ingress訪問webui

使用ingress將Webui開放出來。
建立證書。

[root@master01 minio]# ll *com*
-rw-r--r-- 1 root root 3.9K Aug 24 06:19 api.linuxsb.com.crt
-rw-r--r-- 1 root root 1.7K Aug 24 06:19 api.linuxsb.com.key
-rw-r--r-- 1 root root 3.9K Aug 24 05:36 minio.linuxsb.com.crt
-rw-r--r-- 1 root root 1.7K Aug 24 05:36 minio.linuxsb.com.key

[root@master01 minio]# kubectl -n minio-dev create secret tls minio-webui-tls --cert=minio.linuxsb.com.crt --key=minio.linuxsb.com.key
[root@master01 minio]# kubectl -n minio-dev create secret tls minio-api-tls --cert=api.linuxsb.com.crt --key=api.linuxsb.com.key

[root@master01 minio]# kubectl -n minio-dev describe secrets minio-webui-tls
[root@master01 minio]# kubectl -n minio-dev describe secrets minio-api-tls

建立ingress規則。

[root@master01 minio]# vim minio-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minio-webui-ingress
  namespace: minio-dev
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: "nginx"
  tls:
    - hosts:
        - 'minio.linuxsb.com'
      secretName: minio-webui-tls
  rules:
    - host: minio.linuxsb.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: minio
                port:
                  number: 9090
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minio-api-ingress
  namespace: minio-dev
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: "nginx"
  tls:
    - hosts:
        - 'api.linuxsb.com'
      secretName: minio-api-tls
  rules:
    - host: api.linuxsb.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: minio
                port:
                  number: 9000
                  
[root@master01 minio]# kubectl apply -f minio-ingress.yaml 

[root@master01 minio]# kubectl -n minio-dev get ingress -o wide
NAME                  CLASS   HOSTS               ADDRESS        PORTS     AGE
minio-api-ingress     nginx   api.linuxsb.com     172.24.10.11   80, 443   64s
minio-webui-ingress   nginx   minio.linuxsb.com   172.24.10.11   80, 443   64s

確認驗證

  • 瀏覽器驗證
    使用瀏覽器訪問 https://172.24.10.100:9090 ,預設minio賬號密碼: minioadmin / minioadmin ,本實驗已設定賬號密碼: minio / minio123 。

010

011

也可使用ingress所暴露的域名訪問: https://minio.linuxsb.com

012

013

  • MC驗證
    MinIO Client mc命令列工具提供了ls、cat、cp、mirror和diff等命令,支援檔案系統和Amazon s3相容的雲端儲存服務。

mc命令列工具是為與AWS S3 API相容而構建的,並在MinIO和AWS S3上測試了預期的功能和行為。

安裝mc:

[root@master01 minio]# curl https://dl.min.io/client/mc/release/linux-amd64/mc \
  --create-dirs \
  -o /usr/local/bin/mc

[root@master01 minio]# chmod +x /usr/local/bin/mc
[root@master01 minio]# mc --help

連線minio:
使用mc alias set命令將Amazon s3相容的服務新增到mc配置中,將alias替換為要關聯到S3服務的名稱。
mc命令通常需要alias作為引數來標識要對哪個S3服務執行,如果省略ACCESS_KEY和SECRET_KEY,執行命令時會提示在CLI中輸入這些值。

[root@master01 minio]# mc alias set myminio https://api.linuxsb.com minio minio123
Added `myminio` successfully.
[root@master01 minio]# mc admin info myminio

014

提示:更多mc命令使用參考: MinIO Client

MinIO擴容

線上擴容

MinIO結合DirectPV部署的分散式儲存叢集,可透過DirectPV的特性完成線上卷擴容,不需要重新啟動使用這些卷的pod,調整擴容後的大小,然後Persistent Volume Claim自動完成相應動作。

[root@master01 minio]# kubectl -n minio-dev get pvc minio-data-1-minio-0 -o yaml > minio-data-1-minio-0.yaml        #將需要擴容的卷的yaml匯出

[root@master01 minio]# vim minio-data-1-minio-0.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    pv.kubernetes.io/bind-completed: "yes"
    pv.kubernetes.io/bound-by-controller: "yes"
    volume.beta.kubernetes.io/storage-provisioner: directpv-min-io
    volume.kubernetes.io/selected-node: worker02
    volume.kubernetes.io/storage-provisioner: directpv-min-io
  creationTimestamp: "2024-08-23T16:27:13Z"
  finalizers:
  - kubernetes.io/pvc-protection
  labels:
    app: minio
  name: minio-data-1-minio-0
  namespace: minio-dev
  resourceVersion: "1536089"
  uid: 4f6e5be4-4ed7-47e8-8cc1-5b0f3c65167e
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi                          #直接修改大小
  storageClassName: directpv-min-io
  volumeMode: Filesystem
  volumeName: pvc-4f6e5be4-4ed7-47e8-8cc1-5b0f3c65167e
status:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 1Gi
  phase: Bound

[root@master01 minio]# kubectl apply -f minio-data-1-minio-0.yaml
……

確認驗證

驗證擴容後的相應的卷是否為2G。

[root@master01 minio]# kubectl -n minio-dev get pvc minio-data-1-minio-0 -o yaml
apiVersion: v1
kind: PersistentVolumeClaim
#……
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi                          #擴容後的當前容量
  storageClassName: directpv-min-io
  volumeMode: Filesystem
  volumeName: pvc-4f6e5be4-4ed7-47e8-8cc1-5b0f3c65167e
status:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 2Gi

[root@master01 minio]# kubectl -n minio-dev get pvc minio-data-1-minio-0
NAME                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      VOLUMEATTRIBUTESCLASS   AGE
minio-data-1-minio-0   Bound    pvc-4f6e5be4-4ed7-47e8-8cc1-5b0f3c65167e   2Gi        RWO            directpv-min-io   <unset>                 6h20m

更多DirectPV卷管理參考: Volume management003.DirectPV儲存管理

相關文章