卷调度

概述

DirectPV 为提供 PersistentVolumeClaim 用于 DirectPV 存储类的 Pod 提供驱动器。

DirectPV 包含一个名为 directpv-min-io 的存储类,其 卷绑定模式WaitForFirstConsumer。此模式将延迟卷绑定和 PersistentVolume 的供应,直到使用 PersistentVolumeClaim 创建 Pod。然后,DirectPV 选择或供应与 Pod 调度约束中指定的拓扑匹配的 PersistentVolumes。

卷约束

Pod 可能包含持久卷声明的附加约束。DirectPV 选择和供应符合 Pod 调度约束指定的拓扑的 Persistent Volumes。

调度约束的一些示例包括

  • 资源要求,例如容量
  • 节点选择器
  • Pod 亲和性和反亲和性
  • 污点和容忍度

驱动器选择

以下序列和流程图显示了 DirectPV CSI 控制器如何为 CreateVolume 请求选择合适的驱动器。

  1. 验证请求中的文件系统类型是否为 xfs。DirectPV 仅支持 xfs 文件系统。

  2. 验证请求中的任何访问层。

  3. 检查 DirectPVDrive CRD 对象中是否存在请求的卷。如果存在,DirectPV 将调度包含该卷的第一个驱动器。

  4. 如果没有 DirectPVDrive CRD 对象具有请求的卷,DirectPV 将通过以下方式审查每个驱动器:

    • 请求的容量
    • 访问层(如果请求)
    • 拓扑约束(如果请求)
  5. 如果此过程选择了多个驱动器,DirectPV 将选择具有最大可用容量的驱动器。

  6. 如果多个驱动器具有相同的最大可用容量,DirectPV 将随机调度选定的驱动器之一。

  7. 使用请求的卷信息更新已调度驱动器。

注意以下行为:

  • 如果没有驱动器匹配,DirectPV 将返回错误。
  • 如果出现错误,Kubernetes 将重试请求。
  • 如果两个或多个并行请求调度同一个驱动器,该驱动器将成功调度一个请求。所有其他请求将失败并重试。

Flowchart of the decision tree to schedule a drive

自定义驱动器选择

DirectPV 有几种方法可以控制驱动器选择。这些包括

  • 节点选择器
  • Pod 亲和性和反亲和性
  • 污点和容忍度

除了这些方法之外,DirectPV 可以使用 _驱动器标签_ 来选择具有自定义存储类的特定驱动器进行卷调度。

  • 通过 label drives 命令标记选定的驱动器。

    # Label the 'nvme1n1' drive in all nodes as 'fast' with the 'tier' key.
    kubectl directpv label drives --drives=nvme1n1 tier=fast
    
  • 使用 create-storage-class.sh 脚本 创建一个带有驱动器标签的新存储类。

    # Create new storage class 'fast-tier-storage' with drive labels 'directpv.min.io/tier: fast'
    create-storage-class.sh fast-tier-storage 'directpv.min.io/tier: fast'
    
  • 卷供应 中使用新创建的存储类。

    $ kubectl apply -f - <<EOF
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: sleep-pvc
    spec:
      volumeMode: Filesystem
      storageClassName: fast-tier-storage
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 8Mi
    EOF
    

唯一驱动器选择

基于默认可用容量的驱动器选择会导致在单个驱动器中为 StatefulSet 部署分配多个卷。这种选择缺乏像 MinIO 对象存储这样的应用程序的性能和高可用性。

为了克服这种行为,DirectPV 提供了一种方法来为每个驱动器分配一个卷。要使用此功能,请创建一个 自定义存储类,其中包含一个标签,格式类似于 directpv.min.io/volume-claim-id

以下是如何使用 create-storage-class.sh 脚本 创建自定义存储类的示例

create-storage-class.sh tenant-1-storage 'directpv.min.io/volume-claim-id: 555e99eb-e255-4407-83e3-fc443bf20f86'

此自定义存储类必须在你的 StatefulSet 部署中使用。以下是如何部署 MinIO 对象存储的示例

kind: Service
apiVersion: v1
metadata:
  name: minio
  labels:
    app: minio
spec:
  selector:
    app: minio
  ports:
    - name: minio
      port: 9000

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: minio
  labels:
    app: minio
spec:
  serviceName: "minio"
  replicas: 2
  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
        args:
        - "server"
        - "http://minio-{0...1}.minio.default.svc.cluster.local:9000/data{1...2}"
  volumeClaimTemplates:
  - metadata:
      name: minio-data-1
    spec:
      storageClassName: tenant-1-storage
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 16Mi
  - metadata:
      name: minio-data-2
    spec:
      storageClassName: tenant-1-storage
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 16Mi