卷调度
概述
DirectPV 为提供 PersistentVolumeClaim
用于 DirectPV 存储类的 Pod 提供驱动器。
DirectPV
包含一个名为 directpv-min-io
的存储类,其 卷绑定模式 为 WaitForFirstConsumer
。此模式将延迟卷绑定和 PersistentVolume
的供应,直到使用 PersistentVolumeClaim
创建 Pod
。然后,DirectPV 选择或供应与 Pod 调度约束中指定的拓扑匹配的 PersistentVolumes。
卷约束
Pod 可能包含持久卷声明的附加约束。DirectPV 选择和供应符合 Pod 调度约束指定的拓扑的 Persistent Volumes。
调度约束的一些示例包括
- 资源要求,例如容量
- 节点选择器
- Pod 亲和性和反亲和性
- 污点和容忍度
驱动器选择
以下序列和流程图显示了 DirectPV CSI 控制器如何为 CreateVolume
请求选择合适的驱动器。
-
验证请求中的文件系统类型是否为
xfs
。DirectPV 仅支持xfs
文件系统。 -
验证请求中的任何访问层。
-
检查
DirectPVDrive
CRD 对象中是否存在请求的卷。如果存在,DirectPV 将调度包含该卷的第一个驱动器。 -
如果没有
DirectPVDrive
CRD 对象具有请求的卷,DirectPV 将通过以下方式审查每个驱动器:- 请求的容量
- 访问层(如果请求)
- 拓扑约束(如果请求)
-
如果此过程选择了多个驱动器,DirectPV 将选择具有最大可用容量的驱动器。
-
如果多个驱动器具有相同的最大可用容量,DirectPV 将随机调度选定的驱动器之一。
-
使用请求的卷信息更新已调度驱动器。
注意以下行为:
- 如果没有驱动器匹配,DirectPV 将返回错误。
- 如果出现错误,Kubernetes 将重试请求。
- 如果两个或多个并行请求调度同一个驱动器,该驱动器将成功调度一个请求。所有其他请求将失败并重试。
自定义驱动器选择
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