@@ -18,7 +18,6 @@ package org.apache.spark.deploy.kubernetes
18
18
19
19
import java .io .File
20
20
import java .security .SecureRandom
21
- import java .util
22
21
import java .util .concurrent .{CountDownLatch , TimeUnit }
23
22
24
23
import com .google .common .io .Files
@@ -73,6 +72,7 @@ private[spark] class Client(
73
72
74
73
private val serviceAccount = sparkConf.get(KUBERNETES_SERVICE_ACCOUNT_NAME )
75
74
private val customLabels = sparkConf.get(KUBERNETES_DRIVER_LABELS )
75
+ private val customAnnotations = sparkConf.get(KUBERNETES_DRIVER_ANNOTATIONS )
76
76
77
77
private val kubernetesResourceCleaner = new KubernetesResourceCleaner
78
78
@@ -90,7 +90,18 @@ private[spark] class Client(
90
90
throw new SparkException (s " Main app resource file $mainAppResource is not a file or " +
91
91
s " is a directory. " )
92
92
}
93
- val parsedCustomLabels = parseCustomLabels(customLabels)
93
+ val parsedCustomLabels = parseKeyValuePairs(customLabels, KUBERNETES_DRIVER_LABELS .key,
94
+ " labels" )
95
+ parsedCustomLabels.keys.foreach { key =>
96
+ require(key != SPARK_APP_ID_LABEL , " Label with key" +
97
+ s " $SPARK_APP_ID_LABEL cannot be used in " +
98
+ " spark.kubernetes.driver.labels, as it is reserved for Spark's" +
99
+ " internal configuration." )
100
+ }
101
+ val parsedCustomAnnotations = parseKeyValuePairs(
102
+ customAnnotations,
103
+ KUBERNETES_DRIVER_ANNOTATIONS .key,
104
+ " annotations" )
94
105
var k8ConfBuilder = new K8SConfigBuilder ()
95
106
.withApiVersion(" v1" )
96
107
.withMasterUrl(master)
@@ -134,6 +145,7 @@ private[spark] class Client(
134
145
val (driverPod, driverService) = launchDriverKubernetesComponents(
135
146
kubernetesClient,
136
147
parsedCustomLabels,
148
+ parsedCustomAnnotations,
137
149
submitServerSecret,
138
150
sslConfiguration)
139
151
configureOwnerReferences(
@@ -215,14 +227,15 @@ private[spark] class Client(
215
227
216
228
private def launchDriverKubernetesComponents (
217
229
kubernetesClient : KubernetesClient ,
218
- parsedCustomLabels : Map [String , String ],
230
+ customLabels : Map [String , String ],
231
+ customAnnotations : Map [String , String ],
219
232
submitServerSecret : Secret ,
220
233
sslConfiguration : SslConfiguration ): (Pod , Service ) = {
221
234
val driverKubernetesSelectors = (Map (
222
235
SPARK_DRIVER_LABEL -> kubernetesAppId,
223
236
SPARK_APP_ID_LABEL -> kubernetesAppId,
224
237
SPARK_APP_NAME_LABEL -> appName)
225
- ++ parsedCustomLabels).asJava
238
+ ++ customLabels)
226
239
val endpointsReadyFuture = SettableFuture .create[Endpoints ]
227
240
val endpointsReadyWatcher = new DriverEndpointsReadyWatcher (endpointsReadyFuture)
228
241
val serviceReadyFuture = SettableFuture .create[Service ]
@@ -249,6 +262,7 @@ private[spark] class Client(
249
262
val driverPod = createDriverPod(
250
263
kubernetesClient,
251
264
driverKubernetesSelectors,
265
+ customAnnotations,
252
266
submitServerSecret,
253
267
sslConfiguration)
254
268
kubernetesResourceCleaner.registerOrUpdateResource(driverPod)
@@ -342,7 +356,7 @@ private[spark] class Client(
342
356
343
357
private def createDriverService (
344
358
kubernetesClient : KubernetesClient ,
345
- driverKubernetesSelectors : java.util. Map [String , String ],
359
+ driverKubernetesSelectors : Map [String , String ],
346
360
submitServerSecret : Secret ): Service = {
347
361
val driverSubmissionServicePort = new ServicePortBuilder ()
348
362
.withName(SUBMISSION_SERVER_PORT_NAME )
@@ -352,19 +366,20 @@ private[spark] class Client(
352
366
kubernetesClient.services().createNew()
353
367
.withNewMetadata()
354
368
.withName(kubernetesAppId)
355
- .withLabels(driverKubernetesSelectors)
369
+ .withLabels(driverKubernetesSelectors.asJava )
356
370
.endMetadata()
357
371
.withNewSpec()
358
372
.withType(" NodePort" )
359
- .withSelector(driverKubernetesSelectors)
373
+ .withSelector(driverKubernetesSelectors.asJava )
360
374
.withPorts(driverSubmissionServicePort)
361
375
.endSpec()
362
376
.done()
363
377
}
364
378
365
379
private def createDriverPod (
366
380
kubernetesClient : KubernetesClient ,
367
- driverKubernetesSelectors : util.Map [String , String ],
381
+ driverKubernetesSelectors : Map [String , String ],
382
+ customAnnotations : Map [String , String ],
368
383
submitServerSecret : Secret ,
369
384
sslConfiguration : SslConfiguration ): Pod = {
370
385
val containerPorts = buildContainerPorts()
@@ -376,7 +391,8 @@ private[spark] class Client(
376
391
kubernetesClient.pods().createNew()
377
392
.withNewMetadata()
378
393
.withName(kubernetesAppId)
379
- .withLabels(driverKubernetesSelectors)
394
+ .withLabels(driverKubernetesSelectors.asJava)
395
+ .withAnnotations(customAnnotations.asJava)
380
396
.endMetadata()
381
397
.withNewSpec()
382
398
.withRestartPolicy(" Never" )
@@ -601,20 +617,19 @@ private[spark] class Client(
601
617
connectTimeoutMillis = 5000 )
602
618
}
603
619
604
- private def parseCustomLabels (maybeLabels : Option [String ]): Map [String , String ] = {
605
- maybeLabels.map(labels => {
606
- labels.split(" ," ).map(_.trim).filterNot(_.isEmpty).map(label => {
607
- label.split(" =" , 2 ).toSeq match {
620
+ private def parseKeyValuePairs (
621
+ maybeKeyValues : Option [String ],
622
+ configKey : String ,
623
+ keyValueType : String ): Map [String , String ] = {
624
+ maybeKeyValues.map(keyValues => {
625
+ keyValues.split(" ," ).map(_.trim).filterNot(_.isEmpty).map(keyValue => {
626
+ keyValue.split(" =" , 2 ).toSeq match {
608
627
case Seq (k, v) =>
609
- require(k != SPARK_APP_ID_LABEL , " Label with key" +
610
- s " $SPARK_APP_ID_LABEL cannot be used in " +
611
- " spark.kubernetes.driver.labels, as it is reserved for Spark's" +
612
- " internal configuration." )
613
628
(k, v)
614
629
case _ =>
615
- throw new SparkException (" Custom labels set by spark.kubernetes.driver.labels " +
616
- " must be a comma-separated list of key-value pairs, with format <key>=<value>." +
617
- s " Got label : $label . All labels : $labels " )
630
+ throw new SparkException (s " Custom $keyValueType set by $configKey must be a " +
631
+ s " comma-separated list of key-value pairs, with format <key>=<value>. " +
632
+ s " Got value : $keyValue . All values : $keyValues " )
618
633
}
619
634
}).toMap
620
635
}).getOrElse(Map .empty[String , String ])
0 commit comments