Skip to content
This repository was archived by the owner on Jan 9, 2020. It is now read-only.

Commit fdd50f1

Browse files
mccheahash211
authored andcommitted
New API for custom labels and annotations. (#346)
* New API for custom labels and annotations. This APi allows for these labels and annotations to have = and , characters, which is hard to accomplish in the old scheme. * Compare correct values in requirements * Use helper method * Address comments. * Fix scalastyle * Use variable * Remove unused import
1 parent d6a3111 commit fdd50f1

File tree

6 files changed

+127
-26
lines changed

6 files changed

+127
-26
lines changed

docs/running-on-kubernetes.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,10 +524,52 @@ from the other deployment modes. See the [configuration page](configuration.html
524524
(typically 6-10%).
525525
</td>
526526
</tr>
527+
<tr>
528+
<td><code>spark.kubernetes.driver.label.[labelKey]</code></td>
529+
<td>(none)</td>
530+
<td>
531+
Adds a label to the driver pod, with key <code>labelKey</code> and the value as the configuration's value. For
532+
example, setting <code>spark.kubernetes.driver.label.identifier</code> to <code>myIdentifier</code> will result in
533+
the driver pod having a label with key <code>identifier</code> and value <code>myIdentifier</code>. Multiple labels
534+
can be added by setting multiple configurations with this prefix.
535+
</td>
536+
</tr>
537+
<tr>
538+
<td><code>spark.kubernetes.driver.annotation.[annotationKey]</code></td>
539+
<td>(none)</td>
540+
<td>
541+
Adds an annotation to the driver pod, with key <code>annotationKey</code> and the value as the configuration's
542+
value. For example, setting <code>spark.kubernetes.driver.annotation.identifier</code> to <code>myIdentifier</code>
543+
will result in the driver pod having an annotation with key <code>identifier</code> and value
544+
<code>myIdentifier</code>. Multiple annotations can be added by setting multiple configurations with this prefix.
545+
</td>
546+
</tr>
547+
<tr>
548+
<td><code>spark.kubernetes.executor.label.[labelKey]</code></td>
549+
<td>(none)</td>
550+
<td>
551+
Adds a label to all executor pods, with key <code>labelKey</code> and the value as the configuration's value. For
552+
example, setting <code>spark.kubernetes.executor.label.identifier</code> to <code>myIdentifier</code> will result in
553+
the executor pods having a label with key <code>identifier</code> and value <code>myIdentifier</code>. Multiple
554+
labels can be added by setting multiple configurations with this prefix.
555+
</td>
556+
</tr>
557+
<tr>
558+
<td><code>spark.kubernetes.executor.annotation.[annotationKey]</code></td>
559+
<td>(none)</td>
560+
<td>
561+
Adds an annotation to the executor pods, with key <code>annotationKey</code> and the value as the configuration's
562+
value. For example, setting <code>spark.kubernetes.executor.annotation.identifier</code> to <code>myIdentifier</code>
563+
will result in the executor pods having an annotation with key <code>identifier</code> and value
564+
<code>myIdentifier</code>. Multiple annotations can be added by setting multiple configurations with this prefix.
565+
</td>
566+
</tr>
527567
<tr>
528568
<td><code>spark.kubernetes.driver.labels</code></td>
529569
<td>(none)</td>
530570
<td>
571+
<i>Deprecated.</i> Use <code>spark.kubernetes.driver.label.<labelKey></code> instead which supports <code>=</code>
572+
and <code>,</code> characters in label values.
531573
Custom labels that will be added to the driver pod. This should be a comma-separated list of label key-value pairs,
532574
where each label is in the format <code>key=value</code>. Note that Spark also adds its own labels to the driver pod
533575
for bookkeeping purposes.
@@ -537,6 +579,8 @@ from the other deployment modes. See the [configuration page](configuration.html
537579
<td><code>spark.kubernetes.driver.annotations</code></td>
538580
<td>(none)</td>
539581
<td>
582+
<i>Deprecated.</i> Use <code>spark.kubernetes.driver.annotation.<annotationKey></code> instead which supports
583+
<code>=</code> and <code>,</code> characters in annotation values.
540584
Custom annotations that will be added to the driver pod. This should be a comma-separated list of label key-value
541585
pairs, where each annotation is in the format <code>key=value</code>.
542586
</td>
@@ -545,6 +589,8 @@ from the other deployment modes. See the [configuration page](configuration.html
545589
<td><code>spark.kubernetes.executor.labels</code></td>
546590
<td>(none)</td>
547591
<td>
592+
<i>Deprecated.</i> Use <code>spark.kubernetes.executor.label.<labelKey></code> instead which supports
593+
<code>=</code> and <code>,</code> characters in label values.
548594
Custom labels that will be added to the executor pods. This should be a comma-separated list of label key-value
549595
pairs, where each label is in the format <code>key=value</code>. Note that Spark also adds its own labels to the
550596
executor pods for bookkeeping purposes.
@@ -554,6 +600,8 @@ from the other deployment modes. See the [configuration page](configuration.html
554600
<td><code>spark.kubernetes.executor.annotations</code></td>
555601
<td>(none)</td>
556602
<td>
603+
<i>Deprecated.</i> Use <code>spark.kubernetes.executor.annotation.<annotationKey></code> instead which supports
604+
<code>=</code> and <code>,</code> characters in annotation values.
557605
Custom annotations that will be added to the executor pods. This should be a comma-separated list of annotation
558606
key-value pairs, where each annotation is in the format <code>key=value</code>.
559607
</td>

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

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717

1818
package org.apache.spark.deploy.kubernetes
1919

20-
import org.apache.spark.SparkException
20+
import org.apache.spark.{SparkConf, SparkException}
21+
import org.apache.spark.internal.Logging
22+
import org.apache.spark.internal.config.OptionalConfigEntry
2123

22-
object ConfigurationUtils {
24+
object ConfigurationUtils extends Logging {
2325
def parseKeyValuePairs(
2426
maybeKeyValues: Option[String],
2527
configKey: String,
@@ -38,4 +40,29 @@ object ConfigurationUtils {
3840
}).toMap
3941
}).getOrElse(Map.empty[String, String])
4042
}
43+
44+
def combinePrefixedKeyValuePairsWithDeprecatedConf(
45+
sparkConf: SparkConf,
46+
prefix: String,
47+
deprecatedConf: OptionalConfigEntry[String],
48+
configType: String): Map[String, String] = {
49+
val deprecatedKeyValuePairsString = sparkConf.get(deprecatedConf)
50+
deprecatedKeyValuePairsString.foreach { _ =>
51+
logWarning(s"Configuration with key ${deprecatedConf.key} is deprecated. Use" +
52+
s" configurations with prefix $prefix<key> instead.")
53+
}
54+
val fromDeprecated = parseKeyValuePairs(
55+
deprecatedKeyValuePairsString,
56+
deprecatedConf.key,
57+
configType)
58+
val fromPrefix = sparkConf.getAllWithPrefix(prefix)
59+
val combined = fromDeprecated.toSeq ++ fromPrefix
60+
combined.groupBy(_._1).foreach {
61+
case (key, values) =>
62+
require(values.size == 1,
63+
s"Cannot have multiple values for a given $configType key, got key $key with" +
64+
s" values $values")
65+
}
66+
combined.toMap
67+
}
4168
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ package object config extends Logging {
113113
.bytesConf(ByteUnit.MiB)
114114
.createOptional
115115

116+
private[spark] val KUBERNETES_DRIVER_LABEL_PREFIX = "spark.kubernetes.driver.label."
117+
private[spark] val KUBERNETES_DRIVER_ANNOTATION_PREFIX = "spark.kubernetes.driver.annotation."
118+
private[spark] val KUBERNETES_EXECUTOR_LABEL_PREFIX = "spark.kubernetes.executor.label."
119+
private[spark] val KUBERNETES_EXECUTOR_ANNOTATION_PREFIX = "spark.kubernetes.executor.annotation."
120+
116121
private[spark] val KUBERNETES_DRIVER_LABELS =
117122
ConfigBuilder("spark.kubernetes.driver.labels")
118123
.doc("Custom labels that will be added to the driver pod. This should be a comma-separated" +

resource-managers/kubernetes/core/src/main/scala/org/apache/spark/deploy/kubernetes/submit/Client.scala

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import org.apache.spark.deploy.kubernetes.config._
2929
import org.apache.spark.deploy.kubernetes.constants._
3030
import org.apache.spark.deploy.rest.kubernetes.ResourceStagingServerSslOptionsProviderImpl
3131
import org.apache.spark.internal.Logging
32+
import org.apache.spark.internal.config.ConfigEntry
3233
import org.apache.spark.launcher.SparkLauncher
3334
import org.apache.spark.util.Utils
3435

@@ -82,17 +83,25 @@ private[spark] class Client(
8283
def run(): Unit = {
8384
validateNoDuplicateFileNames(sparkJars)
8485
validateNoDuplicateFileNames(sparkFiles)
85-
val parsedCustomLabels = ConfigurationUtils.parseKeyValuePairs(
86-
customLabels, KUBERNETES_DRIVER_LABELS.key, "labels")
87-
require(!parsedCustomLabels.contains(SPARK_APP_ID_LABEL), s"Label with key " +
88-
s" $SPARK_APP_ID_LABEL is not allowed as it is reserved for Spark bookkeeping" +
89-
s" operations.")
90-
val parsedCustomAnnotations = ConfigurationUtils.parseKeyValuePairs(
91-
customAnnotations, KUBERNETES_DRIVER_ANNOTATIONS.key, "annotations")
92-
require(!parsedCustomAnnotations.contains(SPARK_APP_NAME_ANNOTATION), s"Annotation with key" +
93-
s" $SPARK_APP_NAME_ANNOTATION is not allowed as it is reserved for Spark bookkeeping" +
94-
s" operations.")
95-
val allLabels = parsedCustomLabels ++ Map(
86+
87+
val driverCustomLabels = ConfigurationUtils.combinePrefixedKeyValuePairsWithDeprecatedConf(
88+
sparkConf,
89+
KUBERNETES_DRIVER_LABEL_PREFIX,
90+
KUBERNETES_DRIVER_LABELS,
91+
"label")
92+
require(!driverCustomLabels.contains(SPARK_APP_ID_LABEL), s"Label with key " +
93+
s" $SPARK_APP_ID_LABEL is not allowed as it is reserved for Spark bookkeeping" +
94+
s" operations.")
95+
96+
val driverCustomAnnotations = ConfigurationUtils.combinePrefixedKeyValuePairsWithDeprecatedConf(
97+
sparkConf,
98+
KUBERNETES_DRIVER_ANNOTATION_PREFIX,
99+
KUBERNETES_DRIVER_ANNOTATIONS,
100+
"annotation")
101+
require(!driverCustomAnnotations.contains(SPARK_APP_NAME_ANNOTATION),
102+
s"Annotation with key $SPARK_APP_NAME_ANNOTATION is not allowed as it is reserved for" +
103+
s" Spark bookkeeping operations.")
104+
val allDriverLabels = driverCustomLabels ++ Map(
96105
SPARK_APP_ID_LABEL -> kubernetesAppId,
97106
SPARK_ROLE_LABEL -> SPARK_POD_DRIVER_ROLE)
98107

@@ -138,8 +147,8 @@ private[spark] class Client(
138147
val basePod = new PodBuilder()
139148
.withNewMetadata()
140149
.withName(kubernetesDriverPodName)
141-
.addToLabels(allLabels.asJava)
142-
.addToAnnotations(parsedCustomAnnotations.asJava)
150+
.addToLabels(allDriverLabels.asJava)
151+
.addToAnnotations(driverCustomAnnotations.toMap.asJava)
143152
.addToAnnotations(SPARK_APP_NAME_ANNOTATION, appName)
144153
.endMetadata()
145154
.withNewSpec()
@@ -148,7 +157,7 @@ private[spark] class Client(
148157
.endSpec()
149158

150159
val maybeSubmittedDependencyUploader = initContainerComponentsProvider
151-
.provideInitContainerSubmittedDependencyUploader(allLabels)
160+
.provideInitContainerSubmittedDependencyUploader(allDriverLabels)
152161
val maybeSubmittedResourceIdentifiers = maybeSubmittedDependencyUploader.map { uploader =>
153162
SubmittedResources(uploader.uploadJars(), uploader.uploadFiles())
154163
}

resource-managers/kubernetes/core/src/main/scala/org/apache/spark/scheduler/cluster/kubernetes/KubernetesClusterSchedulerBackend.scala

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,11 @@ private[spark] class KubernetesClusterSchedulerBackend(
6262
org.apache.spark.internal.config.EXECUTOR_CLASS_PATH)
6363
private val executorJarsDownloadDir = conf.get(INIT_CONTAINER_JARS_DOWNLOAD_LOCATION)
6464

65-
private val executorLabels = ConfigurationUtils.parseKeyValuePairs(
66-
conf.get(KUBERNETES_EXECUTOR_LABELS),
67-
KUBERNETES_EXECUTOR_LABELS.key,
68-
"executor labels")
65+
private val executorLabels = ConfigurationUtils.combinePrefixedKeyValuePairsWithDeprecatedConf(
66+
conf,
67+
KUBERNETES_EXECUTOR_LABEL_PREFIX,
68+
KUBERNETES_EXECUTOR_LABELS,
69+
"executor label")
6970
require(
7071
!executorLabels.contains(SPARK_APP_ID_LABEL),
7172
s"Custom executor labels cannot contain $SPARK_APP_ID_LABEL as it is" +
@@ -74,11 +75,13 @@ private[spark] class KubernetesClusterSchedulerBackend(
7475
!executorLabels.contains(SPARK_EXECUTOR_ID_LABEL),
7576
s"Custom executor labels cannot contain $SPARK_EXECUTOR_ID_LABEL as it is reserved for" +
7677
s" Spark.")
77-
private val executorAnnotations = ConfigurationUtils.parseKeyValuePairs(
78-
conf.get(KUBERNETES_EXECUTOR_ANNOTATIONS),
79-
KUBERNETES_EXECUTOR_ANNOTATIONS.key,
80-
"executor annotations")
8178

79+
private val executorAnnotations =
80+
ConfigurationUtils.combinePrefixedKeyValuePairsWithDeprecatedConf(
81+
conf,
82+
KUBERNETES_EXECUTOR_ANNOTATION_PREFIX,
83+
KUBERNETES_EXECUTOR_ANNOTATIONS,
84+
"executor annotation")
8285
private var shufflePodCache: Option[ShufflePodCache] = None
8386
private val executorDockerImage = conf.get(EXECUTOR_DOCKER_IMAGE)
8487
private val dockerImagePullPolicy = conf.get(DOCKER_IMAGE_PULL_POLICY)

resource-managers/kubernetes/core/src/test/scala/org/apache/spark/deploy/kubernetes/submit/ClientV2Suite.scala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,17 @@ class ClientV2Suite extends SparkFunSuite with BeforeAndAfter {
4949
private val APP_ID = "spark-id"
5050
private val CUSTOM_LABEL_KEY = "customLabel"
5151
private val CUSTOM_LABEL_VALUE = "customLabelValue"
52+
private val DEPRECATED_CUSTOM_LABEL_KEY = "deprecatedCustomLabel"
53+
private val DEPRECATED_CUSTOM_LABEL_VALUE = "deprecatedCustomLabelValue"
5254
private val ALL_EXPECTED_LABELS = Map(
5355
CUSTOM_LABEL_KEY -> CUSTOM_LABEL_VALUE,
56+
DEPRECATED_CUSTOM_LABEL_KEY -> DEPRECATED_CUSTOM_LABEL_VALUE,
5457
SPARK_APP_ID_LABEL -> APP_ID,
5558
SPARK_ROLE_LABEL -> SPARK_POD_DRIVER_ROLE)
5659
private val CUSTOM_ANNOTATION_KEY = "customAnnotation"
5760
private val CUSTOM_ANNOTATION_VALUE = "customAnnotationValue"
61+
private val DEPRECATED_CUSTOM_ANNOTATION_KEY = "deprecatedCustomAnnotation"
62+
private val DEPRECATED_CUSTOM_ANNOTATION_VALUE = "deprecatedCustomAnnotationValue"
5863
private val INIT_CONTAINER_SECRET_NAME = "init-container-secret"
5964
private val INIT_CONTAINER_SECRET_DATA = Map("secret-key" -> "secret-data")
6065
private val MAIN_CLASS = "org.apache.spark.examples.SparkPi"
@@ -94,8 +99,11 @@ class ClientV2Suite extends SparkFunSuite with BeforeAndAfter {
9499
.set(DRIVER_DOCKER_IMAGE, CUSTOM_DRIVER_IMAGE)
95100
.set(org.apache.spark.internal.config.DRIVER_MEMORY, DRIVER_MEMORY_MB.toLong)
96101
.set(KUBERNETES_DRIVER_MEMORY_OVERHEAD, DRIVER_MEMORY_OVERHEAD_MB.toLong)
97-
.set(KUBERNETES_DRIVER_LABELS, s"$CUSTOM_LABEL_KEY=$CUSTOM_LABEL_VALUE")
98-
.set(KUBERNETES_DRIVER_ANNOTATIONS, s"$CUSTOM_ANNOTATION_KEY=$CUSTOM_ANNOTATION_VALUE")
102+
.set(KUBERNETES_DRIVER_LABELS, s"$DEPRECATED_CUSTOM_LABEL_KEY=$DEPRECATED_CUSTOM_LABEL_VALUE")
103+
.set(KUBERNETES_DRIVER_ANNOTATIONS,
104+
s"$DEPRECATED_CUSTOM_ANNOTATION_KEY=$DEPRECATED_CUSTOM_ANNOTATION_VALUE")
105+
.set(s"$KUBERNETES_DRIVER_LABEL_PREFIX$CUSTOM_LABEL_KEY", CUSTOM_LABEL_VALUE)
106+
.set(s"$KUBERNETES_DRIVER_ANNOTATION_PREFIX$CUSTOM_ANNOTATION_KEY", CUSTOM_ANNOTATION_VALUE)
99107
.set(org.apache.spark.internal.config.DRIVER_CLASS_PATH, DRIVER_EXTRA_CLASSPATH)
100108
.set(org.apache.spark.internal.config.DRIVER_JAVA_OPTIONS, DRIVER_JAVA_OPTIONS)
101109
private val EXECUTOR_INIT_CONF_KEY = "executor-init-conf"
@@ -444,6 +452,7 @@ class ClientV2Suite extends SparkFunSuite with BeforeAndAfter {
444452

445453
private def podHasCorrectAnnotations(pod: Pod): Boolean = {
446454
val expectedAnnotations = Map(
455+
DEPRECATED_CUSTOM_ANNOTATION_KEY -> DEPRECATED_CUSTOM_ANNOTATION_VALUE,
447456
CUSTOM_ANNOTATION_KEY -> CUSTOM_ANNOTATION_VALUE,
448457
SPARK_APP_NAME_ANNOTATION -> APP_NAME,
449458
BOOTSTRAPPED_POD_ANNOTATION -> TRUE)

0 commit comments

Comments
 (0)