Skip to content

Commit 3c76993

Browse files
mccheahash211
authored andcommitted
Support using PEM files to configure SSL for driver submission (apache-spark-on-k8s#173)
* Support configuring SSL using PEM files. * Address some missed comments * Fix import ordering * Slight rewording of comments * Fix scalastyle (cherry picked from commit 078697f)
1 parent 896b59b commit 3c76993

File tree

13 files changed

+680
-278
lines changed

13 files changed

+680
-278
lines changed

docs/running-on-kubernetes.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,24 @@ Spark supports using TLS to encrypt the traffic in this bootstrapping process. I
127127
whenever possible.
128128

129129
See the [security page](security.html) and [configuration](configuration.html) sections for more information on
130-
configuring TLS; use the prefix `spark.ssl.kubernetes.submission` in configuring the TLS-related fields in the context
130+
configuring TLS; use the prefix `spark.ssl.kubernetes.driversubmitserver` in configuring the TLS-related fields in the context
131131
of submitting to Kubernetes. For example, to set the trustStore used when the local machine communicates with the driver
132-
pod in starting the application, set `spark.ssl.kubernetes.submission.trustStore`.
132+
pod in starting the application, set `spark.ssl.kubernetes.driversubmitserver.trustStore`.
133133

134134
One note about the keyStore is that it can be specified as either a file on the client machine or a file in the
135-
container image's disk. Thus `spark.ssl.kubernetes.submission.keyStore` can be a URI with a scheme of either `file:`
135+
container image's disk. Thus `spark.ssl.kubernetes.driversubmitserver.keyStore` can be a URI with a scheme of either `file:`
136136
or `local:`. A scheme of `file:` corresponds to the keyStore being located on the client machine; it is mounted onto
137137
the driver container as a [secret volume](https://kubernetes.io/docs/user-guide/secrets/). When the URI has the scheme
138138
`local:`, the file is assumed to already be on the container's disk at the appropriate path.
139139

140+
Finally, the submission server and client can be configured to use PEM files instead of Java keyStores. When using
141+
this mode, set `spark.ssl.kubernetes.driversubmitserver.keyPem` and
142+
`spark.ssl.kubernetes.driversubmitserver.serverCertPem` to configure the key and certificate files on the driver
143+
submission server. These files can be uploaded from the submitter's machine if they have no scheme or a scheme of
144+
`file:`, or they can be located on the container's disk if they have the scheme `local:`. The client's certificate
145+
file should be provided via setting `spark.ssl.kubernetes.driversubmitserver.clientCertPem`, and this file must be
146+
located on the submitting machine's local disk.
147+
140148
### Submission of Local Files through Ingress/External controller
141149

142150
Kubernetes pods run with their own IP address space. If Spark is run in cluster mode, the driver pod may not be

resource-managers/kubernetes/core/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@
8787
<groupId>com.google.guava</groupId>
8888
<artifactId>guava</artifactId>
8989
</dependency>
90+
<dependency>
91+
<groupId>org.bouncycastle</groupId>
92+
<artifactId>bcpkix-jdk15on</artifactId>
93+
</dependency>
9094
<!-- End of shaded deps. -->
9195

9296
</dependencies>

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

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ private[spark] class Client(
161161
driverServiceManager.handleSubmissionError(
162162
new SparkException("Submission shutting down early...")))
163163
try {
164-
val sslConfigurationProvider = new SslConfigurationProvider(
164+
val sslConfigurationProvider = new DriverSubmitSslConfigurationProvider(
165165
sparkConf, kubernetesAppId, kubernetesClient, kubernetesResourceCleaner)
166166
val submitServerSecret = kubernetesClient.secrets().createNew()
167167
.withNewMetadata()
@@ -182,7 +182,7 @@ private[spark] class Client(
182182
configureOwnerReferences(
183183
kubernetesClient,
184184
submitServerSecret,
185-
sslConfiguration.sslSecrets,
185+
sslConfiguration.sslSecret,
186186
driverPod,
187187
driverService)
188188
submitApplicationToDriverServer(
@@ -209,7 +209,6 @@ private[spark] class Client(
209209
Utils.tryLogNonFatalError {
210210
driverServiceManager.stop()
211211
}
212-
213212
// Remove the shutdown hooks that would be redundant
214213
Utils.tryLogNonFatalError {
215214
ShutdownHookManager.removeShutdownHook(resourceCleanShutdownHook)
@@ -236,7 +235,7 @@ private[spark] class Client(
236235
private def submitApplicationToDriverServer(
237236
kubernetesClient: KubernetesClient,
238237
driverServiceManager: DriverServiceManager,
239-
sslConfiguration: SslConfiguration,
238+
sslConfiguration: DriverSubmitSslConfiguration,
240239
driverService: Service,
241240
submitterLocalFiles: Iterable[String],
242241
submitterLocalJars: Iterable[String],
@@ -298,7 +297,7 @@ private[spark] class Client(
298297
customLabels: Map[String, String],
299298
customAnnotations: Map[String, String],
300299
submitServerSecret: Secret,
301-
sslConfiguration: SslConfiguration): (Pod, Service) = {
300+
sslConfiguration: DriverSubmitSslConfiguration): (Pod, Service) = {
302301
val driverKubernetesSelectors = (Map(
303302
SPARK_DRIVER_LABEL -> kubernetesAppId,
304303
SPARK_APP_ID_LABEL -> kubernetesAppId,
@@ -349,7 +348,7 @@ private[spark] class Client(
349348
private def configureOwnerReferences(
350349
kubernetesClient: KubernetesClient,
351350
submitServerSecret: Secret,
352-
sslSecrets: Array[Secret],
351+
sslSecret: Option[Secret],
353352
driverPod: Pod,
354353
driverService: Service): Service = {
355354
val driverPodOwnerRef = new OwnerReferenceBuilder()
@@ -359,7 +358,7 @@ private[spark] class Client(
359358
.withKind(driverPod.getKind)
360359
.withController(true)
361360
.build()
362-
sslSecrets.foreach(secret => {
361+
sslSecret.foreach(secret => {
363362
val updatedSecret = kubernetesClient.secrets().withName(secret.getMetadata.getName).edit()
364363
.editMetadata()
365364
.addToOwnerReferences(driverPodOwnerRef)
@@ -425,10 +424,10 @@ private[spark] class Client(
425424
driverKubernetesSelectors: Map[String, String],
426425
customAnnotations: Map[String, String],
427426
submitServerSecret: Secret,
428-
sslConfiguration: SslConfiguration): Pod = {
427+
sslConfiguration: DriverSubmitSslConfiguration): Pod = {
429428
val containerPorts = buildContainerPorts()
430429
val probePingHttpGet = new HTTPGetActionBuilder()
431-
.withScheme(if (sslConfiguration.sslOptions.enabled) "HTTPS" else "HTTP")
430+
.withScheme(if (sslConfiguration.enabled) "HTTPS" else "HTTP")
432431
.withPath("/v1/submissions/ping")
433432
.withNewPort(SUBMISSION_SERVER_PORT_NAME)
434433
.build()
@@ -452,7 +451,7 @@ private[spark] class Client(
452451
.withSecretName(submitServerSecret.getMetadata.getName)
453452
.endSecret()
454453
.endVolume()
455-
.addToVolumes(sslConfiguration.sslPodVolumes: _*)
454+
.addToVolumes(sslConfiguration.sslPodVolume.toSeq: _*)
456455
.withServiceAccount(serviceAccount.getOrElse("default"))
457456
.addNewContainer()
458457
.withName(DRIVER_CONTAINER_NAME)
@@ -463,7 +462,7 @@ private[spark] class Client(
463462
.withMountPath(secretDirectory)
464463
.withReadOnly(true)
465464
.endVolumeMount()
466-
.addToVolumeMounts(sslConfiguration.sslPodVolumeMounts: _*)
465+
.addToVolumeMounts(sslConfiguration.sslPodVolumeMount.toSeq: _*)
467466
.addNewEnv()
468467
.withName(ENV_SUBMISSION_SECRET_LOCATION)
469468
.withValue(s"$secretDirectory/$SUBMISSION_APP_SECRET_NAME")
@@ -661,7 +660,7 @@ private[spark] class Client(
661660
kubernetesClient: KubernetesClient,
662661
driverServiceManager: DriverServiceManager,
663662
service: Service,
664-
sslConfiguration: SslConfiguration): KubernetesSparkRestApi = {
663+
sslConfiguration: DriverSubmitSslConfiguration): KubernetesSparkRestApi = {
665664
val serviceUris = driverServiceManager.getDriverServiceSubmissionServerUris(service)
666665
require(serviceUris.nonEmpty, "No uris found to contact the driver!")
667666
HttpClientUtil.createClient[KubernetesSparkRestApi](

0 commit comments

Comments
 (0)