Skip to content

Commit f714b8e

Browse files
author
Andrew Korzhuev
committed
Make mount.readOnly and emptyDir params optional
1 parent 9e4be63 commit f714b8e

6 files changed

Lines changed: 58 additions & 14 deletions

File tree

docs/running-on-kubernetes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ specific to Spark on Kubernetes.
664664
</tr>
665665
<tr>
666666
<td><code>spark.kubernetes.executor.volumes.[VolumeType].[VolumeName].mount.readOnly</code></td>
667-
<td>(none)</td>
667+
<td>false</td>
668668
<td>
669669
Specify if the mounted volume is read only or not. For example,
670670
<code>spark.kubernetes.executor.volumes.persistentVolumeClaim.checkpointpvc.mount.readOnly=false</code>.

resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/KubernetesVolumeSpec.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717
package org.apache.spark.deploy.k8s
1818

1919
private[spark] sealed trait KubernetesVolumeSpecificConf
20+
2021
private[spark] case class KubernetesHostPathVolumeConf(
21-
hostPath: String) extends KubernetesVolumeSpecificConf
22+
hostPath: String) extends KubernetesVolumeSpecificConf
23+
2224
private[spark] case class KubernetesPVCVolumeConf(
23-
claimName: String) extends KubernetesVolumeSpecificConf
25+
claimName: String) extends KubernetesVolumeSpecificConf
26+
2427
private[spark] case class KubernetesEmptyDirVolumeConf(
25-
medium: String,
26-
sizeLimit: String) extends KubernetesVolumeSpecificConf
28+
medium: Option[String],
29+
sizeLimit: Option[String]) extends KubernetesVolumeSpecificConf
2730

2831
private[spark] case class KubernetesVolumeSpec[T <: KubernetesVolumeSpecificConf](
2932
volumeName: String,

resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/KubernetesVolumeUtils.scala

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,11 @@ private[spark] object KubernetesVolumeUtils {
4242

4343
for {
4444
path <- properties.getTry(pathKey)
45-
readOnly <- properties.getTry(readOnlyKey)
4645
volumeConf <- parseVolumeSpecificConf(properties, volumeType, volumeName)
4746
} yield KubernetesVolumeSpec(
4847
volumeName = volumeName,
4948
mountPath = path,
50-
mountReadOnly = readOnly.toBoolean,
49+
mountReadOnly = properties.get(readOnlyKey).exists(_.toBoolean),
5150
volumeConf = volumeConf
5251
)
5352
}
@@ -91,10 +90,7 @@ private[spark] object KubernetesVolumeUtils {
9190
case KUBERNETES_VOLUMES_EMPTYDIR_TYPE =>
9291
val mediumKey = s"$volumeType.$volumeName.$KUBERNETES_VOLUMES_OPTIONS_MEDIUM_KEY"
9392
val sizeLimitKey = s"$volumeType.$volumeName.$KUBERNETES_VOLUMES_OPTIONS_SIZE_LIMIT_KEY"
94-
for {
95-
medium <- options.getTry(mediumKey)
96-
sizeLimit <- options.getTry(sizeLimitKey)
97-
} yield KubernetesEmptyDirVolumeConf(medium, sizeLimit)
93+
Success(KubernetesEmptyDirVolumeConf(options.get(mediumKey), options.get(sizeLimitKey)))
9894

9995
case _ =>
10096
Failure(new RuntimeException(s"Kubernetes Volume type `$volumeType` is not supported"))

resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/k8s/features/MountVolumesFeatureStep.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ private[spark] class MountVolumesFeatureStep(
6666

6767
case KubernetesEmptyDirVolumeConf(medium, sizeLimit) =>
6868
new VolumeBuilder()
69-
.withEmptyDir(new EmptyDirVolumeSource(medium, new Quantity(sizeLimit)))
69+
.withEmptyDir(
70+
new EmptyDirVolumeSource(medium.getOrElse(""),
71+
new Quantity(sizeLimit.orNull)))
7072
}
7173

7274
val volume = volumeBuilder.withName(spec.volumeName).build()

resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/KubernetesVolumeUtilsSuite.scala

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,29 @@ class KubernetesVolumeUtilsSuite extends SparkFunSuite {
5959
assert(volumeSpec.mountPath === "/path")
6060
assert(volumeSpec.mountReadOnly === true)
6161
assert(volumeSpec.volumeConf.asInstanceOf[KubernetesEmptyDirVolumeConf] ===
62-
KubernetesEmptyDirVolumeConf("medium", "5G"))
62+
KubernetesEmptyDirVolumeConf(Some("medium"), Some("5G")))
63+
}
64+
65+
test("Parses emptyDir volume options can be optional") {
66+
val sparkConf = new SparkConf(false)
67+
sparkConf.set("test.emptyDir.volumeName.mount.path", "/path")
68+
sparkConf.set("test.emptyDir.volumeName.mount.readOnly", "true")
69+
70+
val volumeSpec = KubernetesVolumeUtils.parseVolumesWithPrefix(sparkConf, "test.").head.get
71+
assert(volumeSpec.volumeName === "volumeName")
72+
assert(volumeSpec.mountPath === "/path")
73+
assert(volumeSpec.mountReadOnly === true)
74+
assert(volumeSpec.volumeConf.asInstanceOf[KubernetesEmptyDirVolumeConf] ===
75+
KubernetesEmptyDirVolumeConf(None, None))
76+
}
77+
78+
test("Defaults optional readOnly to false") {
79+
val sparkConf = new SparkConf(false)
80+
sparkConf.set("test.hostPath.volumeName.mount.path", "/path")
81+
sparkConf.set("test.hostPath.volumeName.options.path", "/hostPath")
82+
83+
val volumeSpec = KubernetesVolumeUtils.parseVolumesWithPrefix(sparkConf, "test.").head.get
84+
assert(volumeSpec.mountReadOnly === false)
6385
}
6486

6587
test("Gracefully fails on missing mount key") {

resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/k8s/features/MountVolumesFeatureStepSuite.scala

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class MountVolumesFeatureStepSuite extends SparkFunSuite {
8383
"testVolume",
8484
"/tmp",
8585
false,
86-
KubernetesEmptyDirVolumeConf("Memory", "6G")
86+
KubernetesEmptyDirVolumeConf(Some("Memory"), Some("6G"))
8787
)
8888
val kubernetesConf = emptyKubernetesConf.copy(roleVolumes = volumeConf :: Nil)
8989
val step = new MountVolumesFeatureStep(kubernetesConf)
@@ -99,6 +99,27 @@ class MountVolumesFeatureStepSuite extends SparkFunSuite {
9999
assert(configuredPod.container.getVolumeMounts.get(0).getReadOnly === false)
100100
}
101101

102+
test("Mounts emptyDir with no options") {
103+
val volumeConf = KubernetesVolumeSpec(
104+
"testVolume",
105+
"/tmp",
106+
false,
107+
KubernetesEmptyDirVolumeConf(None, None)
108+
)
109+
val kubernetesConf = emptyKubernetesConf.copy(roleVolumes = volumeConf :: Nil)
110+
val step = new MountVolumesFeatureStep(kubernetesConf)
111+
val configuredPod = step.configurePod(SparkPod.initialPod())
112+
113+
assert(configuredPod.pod.getSpec.getVolumes.size() === 1)
114+
val emptyDir = configuredPod.pod.getSpec.getVolumes.get(0).getEmptyDir
115+
assert(emptyDir.getMedium === "")
116+
assert(emptyDir.getSizeLimit.getAmount === null)
117+
assert(configuredPod.container.getVolumeMounts.size() === 1)
118+
assert(configuredPod.container.getVolumeMounts.get(0).getMountPath === "/tmp")
119+
assert(configuredPod.container.getVolumeMounts.get(0).getName === "testVolume")
120+
assert(configuredPod.container.getVolumeMounts.get(0).getReadOnly === false)
121+
}
122+
102123
test("Mounts multiple volumes") {
103124
val hpVolumeConf = KubernetesVolumeSpec(
104125
"hpVolume",

0 commit comments

Comments
 (0)