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

Commit 4a01baf

Browse files
mccheahfoxish
authored andcommitted
Generate the application ID label irrespective of app name. (#331)
* Generate the application ID label irrespective of app name. * Add an integration test. * Fix scalastyle
1 parent 069bd04 commit 4a01baf

File tree

10 files changed

+144
-114
lines changed

10 files changed

+144
-114
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private[spark] class KubernetesShuffleBlockHandler (
9191
try {
9292
Some(kubernetesClient
9393
.pods()
94-
.withLabels(Map(SPARK_ROLE_LABEL -> "driver").asJava)
94+
.withLabels(Map(SPARK_ROLE_LABEL -> SPARK_POD_DRIVER_ROLE).asJava)
9595
.watch(new Watcher[Pod] {
9696
override def eventReceived(action: Watcher.Action, p: Pod): Unit = {
9797
action match {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ package object config extends Logging {
151151
.stringConf
152152
.createOptional
153153

154+
private[spark] val KUBERNETES_EXECUTOR_POD_NAME_PREFIX =
155+
ConfigBuilder("spark.kubernetes.executor.podNamePrefix")
156+
.doc("Prefix to use in front of the executor pod names.")
157+
.internal()
158+
.stringConf
159+
.createWithDefault("spark")
160+
154161
private[spark] val KUBERNETES_SHUFFLE_NAMESPACE =
155162
ConfigBuilder("spark.kubernetes.shuffle.namespace")
156163
.doc("Namespace of the shuffle service")

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ package org.apache.spark.deploy.kubernetes
1919
package object constants {
2020
// Labels
2121
private[spark] val SPARK_DRIVER_LABEL = "spark-driver"
22-
private[spark] val SPARK_APP_ID_LABEL = "spark-app-id"
23-
private[spark] val SPARK_APP_NAME_LABEL = "spark-app-name"
22+
private[spark] val SPARK_APP_ID_LABEL = "spark-app-selector"
2423
private[spark] val SPARK_EXECUTOR_ID_LABEL = "spark-exec-id"
2524
private[spark] val SPARK_ROLE_LABEL = "spark-role"
25+
private[spark] val SPARK_POD_DRIVER_ROLE = "driver"
26+
private[spark] val SPARK_POD_EXECUTOR_ROLE = "executor"
27+
private[spark] val SPARK_APP_NAME_ANNOTATION = "spark-app-name"
2628

2729
// Credentials secrets
2830
private[spark] val DRIVER_CREDENTIALS_SECRETS_BASE_DIR =

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

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
package org.apache.spark.deploy.kubernetes.submit
1818

1919
import java.io.File
20-
import java.util.Collections
20+
import java.util.{Collections, UUID}
2121

2222
import io.fabric8.kubernetes.api.model.{ContainerBuilder, EnvVarBuilder, OwnerReferenceBuilder, PodBuilder, QuantityBuilder}
2323
import io.fabric8.kubernetes.client.KubernetesClient
2424
import scala.collection.JavaConverters._
2525

26-
import org.apache.spark.{SparkConf, SparkException}
26+
import org.apache.spark.SparkConf
2727
import org.apache.spark.deploy.kubernetes.{ConfigurationUtils, SparkKubernetesClientFactory}
2828
import org.apache.spark.deploy.kubernetes.config._
2929
import org.apache.spark.deploy.kubernetes.constants._
@@ -43,22 +43,21 @@ import org.apache.spark.util.Utils
4343
* where different steps of submission should be factored out into separate classes.
4444
*/
4545
private[spark] class Client(
46-
appName: String,
47-
kubernetesAppId: String,
48-
mainClass: String,
49-
sparkConf: SparkConf,
50-
appArgs: Array[String],
51-
sparkJars: Seq[String],
52-
sparkFiles: Seq[String],
53-
waitForAppCompletion: Boolean,
54-
kubernetesClient: KubernetesClient,
55-
initContainerComponentsProvider: DriverInitContainerComponentsProvider,
56-
kubernetesCredentialsMounterProvider: DriverPodKubernetesCredentialsMounterProvider,
57-
loggingPodStatusWatcher: LoggingPodStatusWatcher)
58-
extends Logging {
59-
46+
appName: String,
47+
kubernetesResourceNamePrefix: String,
48+
kubernetesAppId: String,
49+
mainClass: String,
50+
sparkConf: SparkConf,
51+
appArgs: Array[String],
52+
sparkJars: Seq[String],
53+
sparkFiles: Seq[String],
54+
waitForAppCompletion: Boolean,
55+
kubernetesClient: KubernetesClient,
56+
initContainerComponentsProvider: DriverInitContainerComponentsProvider,
57+
kubernetesCredentialsMounterProvider: DriverPodKubernetesCredentialsMounterProvider,
58+
loggingPodStatusWatcher: LoggingPodStatusWatcher) extends Logging {
6059
private val kubernetesDriverPodName = sparkConf.get(KUBERNETES_DRIVER_POD_NAME)
61-
.getOrElse(kubernetesAppId)
60+
.getOrElse(s"$kubernetesResourceNamePrefix-driver")
6261
private val driverDockerImage = sparkConf.get(DRIVER_DOCKER_IMAGE)
6362
private val dockerImagePullPolicy = sparkConf.get(DOCKER_IMAGE_PULL_POLICY)
6463

@@ -86,15 +85,16 @@ private[spark] class Client(
8685
val parsedCustomLabels = ConfigurationUtils.parseKeyValuePairs(
8786
customLabels, KUBERNETES_DRIVER_LABELS.key, "labels")
8887
require(!parsedCustomLabels.contains(SPARK_APP_ID_LABEL), s"Label with key " +
89-
s" $SPARK_APP_ID_LABEL is not allowed as it is reserved for Spark bookkeeping operations.")
90-
require(!parsedCustomLabels.contains(SPARK_APP_NAME_LABEL), s"Label with key" +
91-
s" $SPARK_APP_NAME_LABEL is not allowed as it is reserved for Spark bookkeeping operations.")
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.")
9295
val allLabels = parsedCustomLabels ++ Map(
9396
SPARK_APP_ID_LABEL -> kubernetesAppId,
94-
SPARK_APP_NAME_LABEL -> appName,
95-
SPARK_ROLE_LABEL -> "driver")
96-
val parsedCustomAnnotations = ConfigurationUtils.parseKeyValuePairs(
97-
customAnnotations, KUBERNETES_DRIVER_ANNOTATIONS.key, "annotations")
97+
SPARK_ROLE_LABEL -> SPARK_POD_DRIVER_ROLE)
9898

9999
val driverExtraClasspathEnv = driverExtraClasspath.map { classPath =>
100100
new EnvVarBuilder()
@@ -140,6 +140,7 @@ private[spark] class Client(
140140
.withName(kubernetesDriverPodName)
141141
.addToLabels(allLabels.asJava)
142142
.addToAnnotations(parsedCustomAnnotations.asJava)
143+
.addToAnnotations(SPARK_APP_NAME_ANNOTATION, appName)
143144
.endMetadata()
144145
.withNewSpec()
145146
.withRestartPolicy("Never")
@@ -186,6 +187,7 @@ private[spark] class Client(
186187
}
187188
resolvedSparkConf.setIfMissing(KUBERNETES_DRIVER_POD_NAME, kubernetesDriverPodName)
188189
resolvedSparkConf.set("spark.app.id", kubernetesAppId)
190+
resolvedSparkConf.set(KUBERNETES_EXECUTOR_POD_NAME_PREFIX, kubernetesResourceNamePrefix)
189191
// We don't need this anymore since we just set the JVM options on the environment
190192
resolvedSparkConf.remove(org.apache.spark.internal.config.DRIVER_JAVA_OPTIONS)
191193
val resolvedLocalClasspath = containerLocalizedFilesResolver
@@ -234,11 +236,11 @@ private[spark] class Client(
234236
throw e
235237
}
236238
if (waitForAppCompletion) {
237-
logInfo(s"Waiting for application $kubernetesAppId to finish...")
239+
logInfo(s"Waiting for application $appName to finish...")
238240
loggingPodStatusWatcher.awaitCompletion()
239-
logInfo(s"Application $kubernetesAppId finished.")
241+
logInfo(s"Application $appName finished.")
240242
} else {
241-
logInfo(s"Deployed Spark application $kubernetesAppId into Kubernetes.")
243+
logInfo(s"Deployed Spark application $appName into Kubernetes.")
242244
}
243245
}
244246
}
@@ -279,15 +281,21 @@ private[spark] object Client {
279281
val sparkFiles = sparkConf.getOption("spark.files")
280282
.map(_.split(","))
281283
.getOrElse(Array.empty[String])
282-
val appName = sparkConf.getOption("spark.app.name")
283-
.getOrElse("spark")
284-
val kubernetesAppId = s"$appName-$launchTime".toLowerCase.replaceAll("\\.", "-")
284+
val appName = sparkConf.getOption("spark.app.name").getOrElse("spark")
285+
// The resource name prefix is derived from the application name, making it easy to connect the
286+
// names of the Kubernetes resources from e.g. Kubectl or the Kubernetes dashboard to the
287+
// application the user submitted. However, we can't use the application name in the label, as
288+
// label values are considerably restrictive, e.g. must be no longer than 63 characters in
289+
// length. So we generate a separate identifier for the app ID itself, and bookkeeping that
290+
// requires finding "all pods for this application" should use the kubernetesAppId.
291+
val kubernetesResourceNamePrefix = s"$appName-$launchTime".toLowerCase.replaceAll("\\.", "-")
292+
val kubernetesAppId = s"spark-${UUID.randomUUID().toString.replaceAll("-", "")}"
285293
val namespace = sparkConf.get(KUBERNETES_NAMESPACE)
286294
val master = resolveK8sMaster(sparkConf.get("spark.master"))
287295
val sslOptionsProvider = new ResourceStagingServerSslOptionsProviderImpl(sparkConf)
288296
val initContainerComponentsProvider = new DriverInitContainerComponentsProviderImpl(
289297
sparkConf,
290-
kubernetesAppId,
298+
kubernetesResourceNamePrefix,
291299
namespace,
292300
sparkJars,
293301
sparkFiles,
@@ -300,14 +308,16 @@ private[spark] object Client {
300308
None,
301309
None)) { kubernetesClient =>
302310
val kubernetesCredentialsMounterProvider =
303-
new DriverPodKubernetesCredentialsMounterProviderImpl(sparkConf, kubernetesAppId)
311+
new DriverPodKubernetesCredentialsMounterProviderImpl(
312+
sparkConf, kubernetesResourceNamePrefix)
304313
val waitForAppCompletion = sparkConf.get(WAIT_FOR_APP_COMPLETION)
305314
val loggingInterval = Option(sparkConf.get(REPORT_INTERVAL))
306315
.filter( _ => waitForAppCompletion)
307316
val loggingPodStatusWatcher = new LoggingPodStatusWatcherImpl(
308-
kubernetesAppId, loggingInterval)
317+
kubernetesResourceNamePrefix, loggingInterval)
309318
new Client(
310319
appName,
320+
kubernetesResourceNamePrefix,
311321
kubernetesAppId,
312322
mainClass,
313323
sparkConf,

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

Lines changed: 54 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
*/
1717
package org.apache.spark.deploy.kubernetes.submit
1818

19-
import java.io.File
20-
2119
import org.apache.spark.{SparkConf, SSLOptions}
2220
import org.apache.spark.deploy.kubernetes.{InitContainerResourceStagingServerSecretPluginImpl, OptionRequirements, SparkPodInitContainerBootstrap, SparkPodInitContainerBootstrapImpl}
2321
import org.apache.spark.deploy.kubernetes.config._
@@ -46,12 +44,12 @@ private[spark] trait DriverInitContainerComponentsProvider {
4644
}
4745

4846
private[spark] class DriverInitContainerComponentsProviderImpl(
49-
sparkConf: SparkConf,
50-
kubernetesAppId: String,
51-
namespace: String,
52-
sparkJars: Seq[String],
53-
sparkFiles: Seq[String],
54-
resourceStagingServerExternalSslOptions: SSLOptions)
47+
sparkConf: SparkConf,
48+
kubernetesResourceNamePrefix: String,
49+
namespace: String,
50+
sparkJars: Seq[String],
51+
sparkFiles: Seq[String],
52+
resourceStagingServerExternalSslOptions: SSLOptions)
5553
extends DriverInitContainerComponentsProvider {
5654

5755
private val maybeResourceStagingServerUri = sparkConf.get(RESOURCE_STAGING_SERVER_URI)
@@ -99,10 +97,10 @@ private[spark] class DriverInitContainerComponentsProviderImpl(
9997
private val jarsDownloadPath = sparkConf.get(INIT_CONTAINER_JARS_DOWNLOAD_LOCATION)
10098
private val filesDownloadPath = sparkConf.get(INIT_CONTAINER_FILES_DOWNLOAD_LOCATION)
10199
private val maybeSecretName = maybeResourceStagingServerUri.map { _ =>
102-
s"$kubernetesAppId-init-secret"
100+
s"$kubernetesResourceNamePrefix-init-secret"
103101
}
104-
private val configMapName = s"$kubernetesAppId-init-config"
105-
private val configMapKey = s"$kubernetesAppId-init-config-key"
102+
private val configMapName = s"$kubernetesResourceNamePrefix-init-config"
103+
private val configMapKey = s"$kubernetesResourceNamePrefix-init-config-key"
106104
private val initContainerImage = sparkConf.get(INIT_CONTAINER_DOCKER_IMAGE)
107105
private val dockerImagePullPolicy = sparkConf.get(DOCKER_IMAGE_PULL_POLICY)
108106
private val downloadTimeoutMinutes = sparkConf.get(INIT_CONTAINER_MOUNT_TIMEOUT)
@@ -116,29 +114,29 @@ private[spark] class DriverInitContainerComponentsProviderImpl(
116114
filesResourceId <- maybeSubmittedResourceIds.map(_.filesResourceId)
117115
} yield {
118116
new SubmittedDependencyInitContainerConfigPluginImpl(
119-
// Configure the init-container with the internal URI over the external URI.
120-
maybeResourceStagingServerInternalUri.getOrElse(stagingServerUri),
121-
jarsResourceId,
122-
filesResourceId,
123-
INIT_CONTAINER_SUBMITTED_JARS_SECRET_KEY,
124-
INIT_CONTAINER_SUBMITTED_FILES_SECRET_KEY,
125-
INIT_CONTAINER_STAGING_SERVER_TRUSTSTORE_SECRET_KEY,
126-
INIT_CONTAINER_STAGING_SERVER_CLIENT_CERT_SECRET_KEY,
127-
resourceStagingServerInternalSslEnabled,
128-
maybeResourceStagingServerInternalTrustStore,
129-
maybeResourceStagingServerInternalClientCert,
130-
maybeResourceStagingServerInternalTrustStorePassword,
131-
maybeResourceStagingServerInternalTrustStoreType,
132-
INIT_CONTAINER_SECRET_VOLUME_MOUNT_PATH)
117+
// Configure the init-container with the internal URI over the external URI.
118+
maybeResourceStagingServerInternalUri.getOrElse(stagingServerUri),
119+
jarsResourceId,
120+
filesResourceId,
121+
INIT_CONTAINER_SUBMITTED_JARS_SECRET_KEY,
122+
INIT_CONTAINER_SUBMITTED_FILES_SECRET_KEY,
123+
INIT_CONTAINER_STAGING_SERVER_TRUSTSTORE_SECRET_KEY,
124+
INIT_CONTAINER_STAGING_SERVER_CLIENT_CERT_SECRET_KEY,
125+
resourceStagingServerInternalSslEnabled,
126+
maybeResourceStagingServerInternalTrustStore,
127+
maybeResourceStagingServerInternalClientCert,
128+
maybeResourceStagingServerInternalTrustStorePassword,
129+
maybeResourceStagingServerInternalTrustStoreType,
130+
INIT_CONTAINER_SECRET_VOLUME_MOUNT_PATH)
133131
}
134132
new SparkInitContainerConfigMapBuilderImpl(
135-
sparkJars,
136-
sparkFiles,
137-
jarsDownloadPath,
138-
filesDownloadPath,
139-
configMapName,
140-
configMapKey,
141-
submittedDependencyConfigPlugin)
133+
sparkJars,
134+
sparkFiles,
135+
jarsDownloadPath,
136+
filesDownloadPath,
137+
configMapName,
138+
configMapKey,
139+
submittedDependencyConfigPlugin)
142140
}
143141

144142
override def provideContainerLocalizedFilesResolver(): ContainerLocalizedFilesResolver = {
@@ -158,14 +156,13 @@ private[spark] class DriverInitContainerComponentsProviderImpl(
158156
driverPodLabels: Map[String, String]): Option[SubmittedDependencyUploader] = {
159157
maybeResourceStagingServerUri.map { stagingServerUri =>
160158
new SubmittedDependencyUploaderImpl(
161-
kubernetesAppId,
162-
driverPodLabels,
163-
namespace,
164-
stagingServerUri,
165-
sparkJars,
166-
sparkFiles,
167-
resourceStagingServerExternalSslOptions,
168-
RetrofitClientFactoryImpl)
159+
driverPodLabels,
160+
namespace,
161+
stagingServerUri,
162+
sparkJars,
163+
sparkFiles,
164+
resourceStagingServerExternalSslOptions,
165+
RetrofitClientFactoryImpl)
169166
}
170167
}
171168

@@ -178,15 +175,15 @@ private[spark] class DriverInitContainerComponentsProviderImpl(
178175
filesResourceSecret <- maybeSubmittedResourceSecrets.map(_.filesResourceSecret)
179176
} yield {
180177
new SubmittedDependencySecretBuilderImpl(
181-
secretName,
182-
jarsResourceSecret,
183-
filesResourceSecret,
184-
INIT_CONTAINER_SUBMITTED_JARS_SECRET_KEY,
185-
INIT_CONTAINER_SUBMITTED_FILES_SECRET_KEY,
186-
INIT_CONTAINER_STAGING_SERVER_TRUSTSTORE_SECRET_KEY,
187-
INIT_CONTAINER_STAGING_SERVER_CLIENT_CERT_SECRET_KEY,
188-
maybeResourceStagingServerInternalTrustStore,
189-
maybeResourceStagingServerInternalClientCert)
178+
secretName,
179+
jarsResourceSecret,
180+
filesResourceSecret,
181+
INIT_CONTAINER_SUBMITTED_JARS_SECRET_KEY,
182+
INIT_CONTAINER_SUBMITTED_FILES_SECRET_KEY,
183+
INIT_CONTAINER_STAGING_SERVER_TRUSTSTORE_SECRET_KEY,
184+
INIT_CONTAINER_STAGING_SERVER_CLIENT_CERT_SECRET_KEY,
185+
maybeResourceStagingServerInternalTrustStore,
186+
maybeResourceStagingServerInternalClientCert)
190187
}
191188
}
192189

@@ -196,13 +193,13 @@ private[spark] class DriverInitContainerComponentsProviderImpl(
196193
secret, INIT_CONTAINER_SECRET_VOLUME_MOUNT_PATH)
197194
}
198195
new SparkPodInitContainerBootstrapImpl(
199-
initContainerImage,
200-
dockerImagePullPolicy,
201-
jarsDownloadPath,
202-
filesDownloadPath,
203-
downloadTimeoutMinutes,
204-
configMapName,
205-
configMapKey,
206-
resourceStagingServerSecretPlugin)
196+
initContainerImage,
197+
dockerImagePullPolicy,
198+
jarsDownloadPath,
199+
filesDownloadPath,
200+
downloadTimeoutMinutes,
201+
configMapName,
202+
configMapKey,
203+
resourceStagingServerSecretPlugin)
207204
}
208205
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ private[spark] trait SubmittedDependencyUploader {
5050
* Resource Staging Service.
5151
*/
5252
private[spark] class SubmittedDependencyUploaderImpl(
53-
kubernetesAppId: String,
5453
podLabels: Map[String, String],
5554
podNamespace: String,
5655
stagingServerUri: String,

0 commit comments

Comments
 (0)