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

Commit ee8b0a5

Browse files
authored
Support SSL configuration for the driver application submission (#49)
* Support SSL when setting up the driver. The user can provide a keyStore to load onto the driver pod and the driver pod will use that keyStore to set up SSL on its server. * Clean up SSL secrets after finishing submission. We don't need to persist these after the pod has them mounted and is running already. * Fix compilation error * Revert image change * Address comments * Programmatically generate certificates for integration tests. * Address comments * Resolve merge conflicts
1 parent f7ca555 commit ee8b0a5

File tree

9 files changed

+445
-67
lines changed

9 files changed

+445
-67
lines changed

core/src/main/scala/org/apache/spark/deploy/rest/RestSubmissionServer.scala

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@ package org.apache.spark.deploy.rest
1919

2020
import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse}
2121

22-
import scala.io.Source
23-
2422
import com.fasterxml.jackson.core.JsonProcessingException
25-
import org.eclipse.jetty.server.{HttpConnectionFactory, Server, ServerConnector}
23+
import org.eclipse.jetty.http.HttpVersion
24+
import org.eclipse.jetty.server.{HttpConfiguration, HttpConnectionFactory, Server, ServerConnector, SslConnectionFactory}
2625
import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
2726
import org.eclipse.jetty.util.thread.{QueuedThreadPool, ScheduledExecutorScheduler}
2827
import org.json4s._
2928
import org.json4s.jackson.JsonMethods._
29+
import scala.io.Source
3030

31-
import org.apache.spark.{SPARK_VERSION => sparkVersion, SparkConf}
31+
import org.apache.spark.{SPARK_VERSION => sparkVersion, SparkConf, SSLOptions}
3232
import org.apache.spark.internal.Logging
3333
import org.apache.spark.util.Utils
3434

@@ -50,7 +50,8 @@ import org.apache.spark.util.Utils
5050
private[spark] abstract class RestSubmissionServer(
5151
val host: String,
5252
val requestedPort: Int,
53-
val masterConf: SparkConf) extends Logging {
53+
val masterConf: SparkConf,
54+
val sslOptions: SSLOptions = SSLOptions()) extends Logging {
5455
protected val submitRequestServlet: SubmitRequestServlet
5556
protected val killRequestServlet: KillRequestServlet
5657
protected val statusRequestServlet: StatusRequestServlet
@@ -79,19 +80,32 @@ private[spark] abstract class RestSubmissionServer(
7980
* Return a 2-tuple of the started server and the bound port.
8081
*/
8182
private def doStart(startPort: Int): (Server, Int) = {
83+
// TODO consider using JettyUtils#startServer to do this instead
8284
val threadPool = new QueuedThreadPool
8385
threadPool.setDaemon(true)
8486
val server = new Server(threadPool)
8587

88+
val resolvedConnectionFactories = sslOptions
89+
.createJettySslContextFactory()
90+
.map(sslFactory => {
91+
val sslConnectionFactory = new SslConnectionFactory(
92+
sslFactory, HttpVersion.HTTP_1_1.asString())
93+
val rawHttpConfiguration = new HttpConfiguration()
94+
rawHttpConfiguration.setSecureScheme("https")
95+
rawHttpConfiguration.setSecurePort(startPort)
96+
val rawHttpConnectionFactory = new HttpConnectionFactory(rawHttpConfiguration)
97+
Array(sslConnectionFactory, rawHttpConnectionFactory)
98+
}).getOrElse(Array(new HttpConnectionFactory()))
99+
86100
val connector = new ServerConnector(
87-
server,
88-
null,
89-
// Call this full constructor to set this, which forces daemon threads:
90-
new ScheduledExecutorScheduler("RestSubmissionServer-JettyScheduler", true),
91-
null,
92-
-1,
93-
-1,
94-
new HttpConnectionFactory())
101+
server,
102+
null,
103+
// Call this full constructor to set this, which forces daemon threads:
104+
new ScheduledExecutorScheduler("RestSubmissionServer-JettyScheduler", true),
105+
null,
106+
-1,
107+
-1,
108+
resolvedConnectionFactories: _*)
95109
connector.setHost(host)
96110
connector.setPort(startPort)
97111
server.addConnector(connector)

docs/running-on-kubernetes.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,24 @@ To specify a main application resource that is in the Docker image, and if it ha
132132
--conf spark.kubernetes.executor.docker.image=registry-host:5000/spark-executor:latest \
133133
container:///home/applications/examples/example.jar
134134

135+
### Setting Up SSL For Submitting the Driver
136+
137+
When submitting to Kubernetes, a pod is started for the driver, and the pod starts an HTTP server. This HTTP server
138+
receives the driver's configuration, including uploaded driver jars, from the client before starting the application.
139+
Spark supports using SSL to encrypt the traffic in this bootstrapping process. It is recommended to configure this
140+
whenever possible.
141+
142+
See the [security page](security.html) and [configuration](configuration.html) sections for more information on
143+
configuring SSL; use the prefix `spark.ssl.kubernetes.driverlaunch` in configuring the SSL-related fields in the context
144+
of submitting to Kubernetes. For example, to set the trustStore used when the local machine communicates with the driver
145+
pod in starting the application, set `spark.ssl.kubernetes.driverlaunch.trustStore`.
146+
147+
One note about the keyStore is that it can be specified as either a file on the client machine or a file in the
148+
container image's disk. Thus `spark.ssl.kubernetes.driverlaunch.keyStore` can be a URI with a scheme of either `file:`
149+
or `container:`. A scheme of `file:` corresponds to the keyStore being located on the client machine; it is mounted onto
150+
the driver container as a [secret volume](https://kubernetes.io/docs/user-guide/secrets/). When the URI has the scheme
151+
`container:`, the file is assumed to already be on the container's disk at the appropriate path.
152+
135153
### Spark Properties
136154

137155
Below are some other common properties that are specific to Kubernetes. Most of the other configurations are the same

pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@
137137
<parquet.version>1.8.1</parquet.version>
138138
<hive.parquet.version>1.6.0</hive.parquet.version>
139139
<feign.version>8.18.0</feign.version>
140+
<bouncycastle.version>1.52</bouncycastle.version>
140141
<jetty.version>9.2.16.v20160414</jetty.version>
141142
<javaxservlet.version>3.1.0</javaxservlet.version>
142143
<chill.version>0.8.0</chill.version>
@@ -337,7 +338,11 @@
337338
<artifactId>okhttp</artifactId>
338339
<version>3.4.1</version>
339340
</dependency>
340-
341+
<dependency>
342+
<groupId>org.bouncycastle</groupId>
343+
<artifactId>bcpkix-jdk15on</artifactId>
344+
<version>${bouncycastle.version}</version>
345+
</dependency>
341346
<!-- This artifact is a shaded version of ASM 5.0.4. The POM that was used to produce this
342347
is at https://github.com/apache/geronimo-xbean/tree/xbean-4.4/xbean-asm5-shaded
343348
For context on why we shade ASM, see SPARK-782 and SPARK-6152. -->

0 commit comments

Comments
 (0)