From e31eb9f34f9070efcf39ea40b4b80f37273b4e88 Mon Sep 17 00:00:00 2001 From: jp39 Date: Sun, 18 Aug 2024 15:58:43 +0200 Subject: [PATCH] Auto: unconditionally set affinity when RWO or RWOP is requested. Force HostPath to be used preemptively instead of letting the scheduler choose where to place the first pod. Also add support for ReadWriteOncePod. --- README.md | 16 ++++++++++------ .../templates/storageclass.yaml | 3 --- pkg/provisioner/provision.go | 10 +++++----- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 79b58d1..d15e418 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,13 @@ but the `PersistentVolume` objects will have a [NodeAffinity][node affinity] con ![architecture with Hostpath](architecture.hostpath.drawio.svg "Architecture with Hostpath provisioning") As a third option, if the ZFS host is part of the cluster, you can let the provisioner choose -whether [NFS][nfs] or [HostPath][hostpath] is used with the `Auto` mode. If the scheduler -decides to place a Pod onto the ZFS host, *and* the requested access mode in the Persistent Volume -Claim is `ReadWriteOnce` (the volume can only be accessed by pods running on the same node) -[HostPath][hostpath] will automatically be used, otherwise [NFS][nfs] will be used. +whether [NFS][nfs] or [HostPath][hostpath] is used with the `Auto` mode. If the requested +[AccessModes][access modes] in the Persistent Volume Claim contains `ReadWriteOnce` (the volume +can only be accessed by pods running on the same node), or `ReadWriteOncePod` (the volume can only +be accessed by one single Pod at any time), then [HostPath][hostpath] will be used and +the [NodeAffinity][node affinity] will be configured on the `PersistentVolume` objects so the +scheduler will automatically place the corresponding Pods onto the ZFS host. Otherwise +[NFS][nfs] will be used and [NodeAffinity][node affinity] will not be set. Currently all ZFS attributes are inherited from the parent dataset. @@ -92,8 +95,8 @@ parameters: For NFS, you can also specify other options, as described in [exports(5)][man exports]. The following example configures a storage class using the `Auto` type. The provisioner -will decide whether [HostPath][hostpath] or [NFS][nfs] will be used based on where the -pods are being scheduled. +will decide whether [HostPath][hostpath] or [NFS][nfs] will be used based on the +[AccessModess][access modes] requested by the persistent volume claim. ```yaml kind: StorageClass @@ -215,3 +218,4 @@ I (@ccremer) have been allowed to take over maintenance for this repository. [helm chart]: https://github.com/ccremer/kubernetes-zfs-provisioner/blob/master/charts/kubernetes-zfs-provisioner/README.md [gentics]: https://www.gentics.com/genticscms/index.en.html [gentics repo]: https://github.com/gentics/kubernetes-zfs-provisioner +[access modes]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes diff --git a/charts/kubernetes-zfs-provisioner/templates/storageclass.yaml b/charts/kubernetes-zfs-provisioner/templates/storageclass.yaml index ae531f2..a4fb411 100644 --- a/charts/kubernetes-zfs-provisioner/templates/storageclass.yaml +++ b/charts/kubernetes-zfs-provisioner/templates/storageclass.yaml @@ -12,9 +12,6 @@ metadata: {{ toYaml . | nindent 4 }} {{- end }} provisioner: {{ $.Values.provisioner.instance }} -{{- if eq .type "auto" }} -volumeBindingMode: WaitForFirstConsumer -{{- end }} reclaimPolicy: {{ .policy | default "Delete" }} parameters: parentDataset: {{ .parentDataset }} diff --git a/pkg/provisioner/provision.go b/pkg/provisioner/provision.go index 7b72cdf..eb12088 100644 --- a/pkg/provisioner/provision.go +++ b/pkg/provisioner/provision.go @@ -73,7 +73,7 @@ func (p *ZFSProvisioner) Provision(ctx context.Context, options controller.Provi }, Spec: v1.PersistentVolumeSpec{ PersistentVolumeReclaimPolicy: reclaimPolicy, - AccessModes: createAccessModes(useHostPath), + AccessModes: createAccessModes(options, useHostPath), Capacity: v1.ResourceList{ v1.ResourceStorage: options.PVC.Spec.Resources.Requests[v1.ResourceStorage], }, @@ -91,9 +91,6 @@ func canUseHostPath(parameters *ZFSStorageClassParameters, options controller.Pr case HostPath: return true case Auto: - if options.SelectedNode == nil || parameters.HostPathNodeName != options.SelectedNode.Name { - return false - } if slices.Contains(options.PVC.Spec.AccessModes, v1.ReadOnlyMany) || slices.Contains(options.PVC.Spec.AccessModes, v1.ReadWriteMany) { return false } @@ -101,7 +98,10 @@ func canUseHostPath(parameters *ZFSStorageClassParameters, options controller.Pr return true } -func createAccessModes(useHostPath bool) []v1.PersistentVolumeAccessMode { +func createAccessModes(options controller.ProvisionOptions, useHostPath bool) []v1.PersistentVolumeAccessMode { + if slices.Contains(options.PVC.Spec.AccessModes, v1.ReadWriteOncePod) { + return []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod} + } accessModes := []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce} if !useHostPath { accessModes = append(accessModes, v1.ReadOnlyMany, v1.ReadWriteMany)