dongjoon-hyun commented on code in PR #58730:
URL: https://github.com/apache/spark/pull/58730#discussion_r3990442898


##########
resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/Config.scala:
##########
@@ -961,6 +961,7 @@ private[spark] object Config extends Logging {
   val KUBERNETES_VOLUMES_PVC_TYPE = "persistentVolumeClaim"
   val KUBERNETES_VOLUMES_EMPTYDIR_TYPE = "emptyDir"
   val KUBERNETES_VOLUMES_NFS_TYPE = "nfs"
+  val KUBERNETES_VOLUMES_CSI_TYPE = "csiVolumeClaim"

Review Comment:
   All existing `VolumeType` tokens are the exact pod-spec `volumes[]` field 
names (`hostPath`, `emptyDir`, `nfs`, `persistentVolumeClaim`). The K8s field 
for this source is `csi`, and an inline CSI ephemeral volume does not create 
any claim, so `csiVolumeClaim` is both off-convention and a bit misleading. 
Since this becomes a public config key that we cannot rename later without a 
deprecation path, shall we use `csi` here?



##########
resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/Config.scala:
##########
@@ -974,6 +975,7 @@ private[spark] object Config extends Logging {
   val KUBERNETES_VOLUMES_OPTIONS_SERVER_KEY = "options.server"
   val KUBERNETES_VOLUMES_LABEL_KEY = "label."
   val KUBERNETES_VOLUMES_ANNOTATION_KEY = "annotation."
+  val KUBERNETES_VOLUMES_OPTIONS_CSI_DRIVER_NAME_KEY = "csiDriverName"

Review Comment:
   This is the only `KUBERNETES_VOLUMES_OPTIONS_*` constant whose value is not 
under `options.`, and the user-facing key `<type>.<name>.csiDriverName` breaks 
the `[VolumeType].[VolumeName].options.[OptionName]` form documented in 
`running-on-kubernetes.md`. I guess it was placed outside `options.` so that 
the generic sweep in `KubernetesVolumeUtils` does not push the driver into 
`volumeAttributes`.
   
   How about `options.driver` (matching the K8s field name) and excluding the 
known keys from the sweep, or nesting attributes under 
`options.volumeAttributes.<k>`? The latter also leaves room for `fsType` / 
`readOnly` / `nodePublishSecretRef` later without colliding with attribute 
names. Either way, please place the constant next to the other 
`KUBERNETES_VOLUMES_OPTIONS_*` keys.



##########
resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/KubernetesVolumeUtils.scala:
##########
@@ -133,6 +133,16 @@ object KubernetesVolumeUtils {
           options(pathKey),
           options(serverKey))
 
+      case KUBERNETES_VOLUMES_CSI_TYPE =>
+        val driverNameKey =
+          
s"$volumeType.$volumeName.$KUBERNETES_VOLUMES_OPTIONS_CSI_DRIVER_NAME_KEY"
+        val volumeConfPrefix = s"$volumeType.$volumeName.options."
+        val attributes = options.filter { case (k, v) => 
k.startsWith(volumeConfPrefix) }

Review Comment:
   nit: `v` is unused here. The sibling sweeps for `label.` / `annotation.` 
above use `.filter(_._1.startsWith(...))`.



##########
resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/KubernetesVolumeUtils.scala:
##########
@@ -133,6 +133,16 @@ object KubernetesVolumeUtils {
           options(pathKey),
           options(serverKey))
 
+      case KUBERNETES_VOLUMES_CSI_TYPE =>
+        val driverNameKey =
+          
s"$volumeType.$volumeName.$KUBERNETES_VOLUMES_OPTIONS_CSI_DRIVER_NAME_KEY"
+        val volumeConfPrefix = s"$volumeType.$volumeName.options."
+        val attributes = options.filter { case (k, v) => 
k.startsWith(volumeConfPrefix) }
+          .map { case (k, v) => (k.substring(volumeConfPrefix.length), v) }

Review Comment:
   Since every `options.*` key becomes a volume attribute, a user who sets 
`options.fsType=ext4` (following the documented options form) silently gets 
`volumeAttributes["fsType"]` instead of `csi.fsType`, and there is no way to 
pass `nodePublishSecretRef` at all, which many drivers require. Together with 
the `readOnly` comment in `MountVolumesFeatureStep`, it would be good to decide 
which `CSIVolumeSource` fields (`fsType`, `readOnly`, `nodePublishSecretRef`) 
are first-class options vs. attributes before the key layout is frozen.



##########
resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/MountVolumesFeatureStep.scala:
##########
@@ -134,6 +134,13 @@ private[spark] class MountVolumesFeatureStep(conf: 
KubernetesConf)
               .withPath(path)
               .withServer(server)
             .endNfs()
+
+        case KubernetesCSIVolumeConf(driverName, attributes) =>
+          new VolumeBuilder()
+            .withNewCsi()
+              .withDriver(driverName)

Review Comment:
   `spec.mountReadOnly` is applied only to the `VolumeMount` here. For CSI, 
kubelet takes the `readonly` flag of `NodePublishVolumeRequest` from 
`volume.csi.readOnly`, not from the mount, and some drivers (e.g. 
`secrets-store.csi.k8s.io`) reject the publish unless it is `true`, which 
leaves the pod in `ContainerCreating`. Could you add 
`.withReadOnly(spec.mountReadOnly)` like the `persistentVolumeClaim` branch 
does?



##########
resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/KubernetesVolumeUtils.scala:
##########
@@ -133,6 +133,16 @@ object KubernetesVolumeUtils {
           options(pathKey),
           options(serverKey))
 
+      case KUBERNETES_VOLUMES_CSI_TYPE =>
+        val driverNameKey =
+          
s"$volumeType.$volumeName.$KUBERNETES_VOLUMES_OPTIONS_CSI_DRIVER_NAME_KEY"
+        val volumeConfPrefix = s"$volumeType.$volumeName.options."
+        val attributes = options.filter { case (k, v) => 
k.startsWith(volumeConfPrefix) }
+          .map { case (k, v) => (k.substring(volumeConfPrefix.length), v) }
+        KubernetesCSIVolumeConf(
+          options(driverNameKey),

Review Comment:
   +1 to @uros-b's comment on `verifyOptionKey`. Please also add 
`csiVolumeClaim` parse tests to `KubernetesVolumeUtilsSuite` (happy path and 
missing driver name), like the `nfs` ones, since this branch is currently 
exercised only indirectly through `KubernetesTestConf`.



##########
resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/features/MountVolumesFeatureStepSuite.scala:
##########
@@ -573,4 +573,39 @@ class MountVolumesFeatureStepSuite extends SparkFunSuite {
     assert(configuredPod.pod.getSpec.getVolumes.size() === 2)
     assert(configuredPod.container.getVolumeMounts.size() === 2)
   }
+
+  test("Mounts csiVolumeClaim") {
+    val volumeConf = KubernetesVolumeSpec(
+      "spark-local-dir-0",

Review Comment:
   nit: `spark-local-dir-` is the prefix that `LocalDirsFeatureStep` treats 
specially, so this name suggests the test is about local dirs. The other tests 
in this suite use `testVolume`. Similarly, `csi.example.com` rather than a 
vendor domain, and the `mountOptions` value does not need the embedded double 
quotes. Binding `val csi = configuredPod.pod.getSpec.getVolumes.get(0).getCsi` 
would also keep each assertion on one line.



##########
resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/KubernetesTestConf.scala:
##########
@@ -143,6 +143,11 @@ object KubernetesTestConf {
           (KUBERNETES_VOLUMES_NFS_TYPE, Map(
             KUBERNETES_VOLUMES_OPTIONS_PATH_KEY -> path,
             KUBERNETES_VOLUMES_OPTIONS_SERVER_KEY -> server))
+
+        case KubernetesCSIVolumeConf(driverName, attributes) =>
+          (KUBERNETES_VOLUMES_CSI_TYPE, Map(
+            KUBERNETES_VOLUMES_OPTIONS_CSI_DRIVER_NAME_KEY -> driverName
+          ) ++ attributes)

Review Comment:
   After parsing, `KubernetesCSIVolumeConf.attributes` holds keys with 
`options.` stripped, but this helper writes them back verbatim. That is why the 
new test has to construct the conf with `"options.parentIndex"`-style keys, a 
shape production never produces; a production-shaped `Map("parentIndex" -> 
"0")` would silently end up as an empty `volumeAttributes`. How about 
`attributes.map { case (k, v) => s"options.$k" -> v }`, like the `label.` / 
`annotation.` handling in the PVC case above?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to