Skip to content
This repository was archived by the owner on Jan 9, 2020. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions docs/running-on-kubernetes.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,22 @@ from the other deployment modes. See the [configuration page](configuration.html
a scheme).
</td>
</tr>
<tr>
<td><code>spark.kubernetes.authenticate.submission.trustStore</code></td>
<td>(none)</td>
<td>
Path to the trustStore file for connecting to the Kubernetes API server over TLS when starting the driver. This file
must be located on the submitting machine's disk. Specify this as a path as opposed to a URI (i.e. do not provide
a scheme).
</td>
</tr>
<tr>
<td><code>spark.kubernetes.authenticate.submission.trustStorePassword</code></td>
<td>(none)</td>
<td>
Password for the trustStore specified in <code>spark.kubernetes.authenticate.submission.trustStore</code>.
</td>
</tr>
<tr>
<td><code>spark.kubernetes.authenticate.submission.clientKeyFile</code></td>
<td>(none)</td>
Expand Down Expand Up @@ -412,6 +428,22 @@ from the other deployment modes. See the [configuration page](configuration.html
Specify this as a path as opposed to a URI (i.e. do not provide a scheme).
</td>
</tr>
<tr>
<td><code>spark.kubernetes.authenticate.driver.trustStore</code></td>
<td>(none)</td>
<td>
Path to the trustStore file for connecting to the Kubernetes API server over TLS from the driver pod when requesting
executors. This file must be located on the submitting machine's disk, and will be uploaded to the driver pod.
Specify this as a path as opposed to a URI (i.e. do not provide a scheme).
</td>
</tr>
<tr>
<td><code>spark.kubernetes.authenticate.driver.trustStorePassword</code></td>
<td>(none)</td>
<td>
Password for the trustStore specified in <code>spark.kubernetes.authenticate.driver.trustStore</code>.
</td>
</tr>
<tr>
<td><code>spark.kubernetes.authenticate.driver.clientKeyFile</code></td>
<td>(none)</td>
Expand Down
2 changes: 1 addition & 1 deletion resource-managers/kubernetes/core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<name>Spark Project Kubernetes</name>
<properties>
<sbt.project.name>kubernetes</sbt.project.name>
<kubernetes.client.version>2.2.13</kubernetes.client.version>
<kubernetes.client.version>2.3.1</kubernetes.client.version>
</properties>

<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ case class KubernetesCredentials(
oauthTokenBase64: Option[String],
caCertDataBase64: Option[String],
clientKeyDataBase64: Option[String],
clientCertDataBase64: Option[String])
clientCertDataBase64: Option[String],
trustStoreDataBase64: Option[String],
trustStorePasswordBase64: Option[String])
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ private[spark] object SparkKubernetesClientFactory {
s"Cannot specify OAuth token through both a file $oauthTokenFileConf and a" +
s" value $oauthTokenConf.")

val trustStorePasswordConf = s"$kubernetesAuthConfPrefix.$TRUSTSTORE_PASSWORD_CONF_SUFFIX"
val trustStorePasswordFileConf =
s"$kubernetesAuthConfPrefix.$TRUSTSTORE_PASSWORD_FILE_CONF_SUFFIX"
val trustStore = sparkConf
.getOption(s"$kubernetesAuthConfPrefix.$TRUSTSTORE_CONF_SUFFIX")
val trustStorePassword = sparkConf.getOption(trustStorePasswordConf)
val trustStorePasswordFile = sparkConf.getOption(trustStorePasswordFileConf)
OptionRequirements.requireNandDefined(
trustStorePassword,
trustStorePasswordFile,
s"Cannot specify trustStore Password through both a value $trustStorePasswordConf and a" +
s" file $trustStorePasswordFileConf")
val resolvedTrustStorePassword = trustStorePassword.orElse(
trustStorePasswordFile.map(f => Files.toString(new File(f), Charsets.UTF_8)))
val caCertFile = sparkConf
.getOption(s"$kubernetesAuthConfPrefix.$CA_CERT_FILE_CONF_SUFFIX")
.orElse(maybeServiceAccountCaCert.map(_.getAbsolutePath))
Expand All @@ -80,6 +94,10 @@ private[spark] object SparkKubernetesClientFactory {
(file, configBuilder) => configBuilder.withClientCertFile(file)
}.withOption(namespace) {
(ns, configBuilder) => configBuilder.withNamespace(ns)
}.withOption(trustStore) {
(trustStore, configBuilder) => configBuilder.withTrustStoreFile(trustStore)
}.withOption(resolvedTrustStorePassword) {
(pw, configBuilder) => configBuilder.withTrustStorePassphrase(pw)
}.build()
val baseHttpClient = HttpClientUtils.createHttpClient(config)
val httpClientWithCustomDispatcher = baseHttpClient.newBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ package object config extends Logging {
private[spark] val CLIENT_KEY_FILE_CONF_SUFFIX = "clientKeyFile"
private[spark] val CLIENT_CERT_FILE_CONF_SUFFIX = "clientCertFile"
private[spark] val CA_CERT_FILE_CONF_SUFFIX = "caCertFile"
private[spark] val TRUSTSTORE_CONF_SUFFIX = "trustStore"
private[spark] val TRUSTSTORE_PASSWORD_CONF_SUFFIX = "trustStorePassword"
private[spark] val TRUSTSTORE_PASSWORD_FILE_CONF_SUFFIX = "trustStorePasswordFile"

private[spark] val RESOURCE_STAGING_SERVER_USE_SERVICE_ACCOUNT_CREDENTIALS =
ConfigBuilder(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ package object constants {
private[spark] val DRIVER_CREDENTIALS_OAUTH_TOKEN_SECRET_NAME = "oauth-token"
private[spark] val DRIVER_CREDENTIALS_OAUTH_TOKEN_PATH =
s"$DRIVER_CREDENTIALS_SECRETS_BASE_DIR/$DRIVER_CREDENTIALS_OAUTH_TOKEN_SECRET_NAME"
private[spark] val DRIVER_CREDENTIALS_TRUSTSTORE_SECRET_NAME = "trustStore"
private[spark] val DRIVER_CREDENTIALS_TRUSTSTORE_PATH =
s"$DRIVER_CREDENTIALS_SECRETS_BASE_DIR/$DRIVER_CREDENTIALS_TRUSTSTORE_SECRET_NAME"
private[spark] val DRIVER_CREDENTIALS_TRUSTSTORE_PASSWORD_SECRET_NAME = "trustStore"
private[spark] val DRIVER_CREDENTIALS_TRUSTSTORE_PASSWORD_PATH =
s"$DRIVER_CREDENTIALS_SECRETS_BASE_DIR/$DRIVER_CREDENTIALS_TRUSTSTORE_PASSWORD_SECRET_NAME"
private[spark] val DRIVER_CREDENTIALS_SECRET_VOLUME_NAME = "kubernetes-credentials"

// Default and fixed ports
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ private[spark] class DriverPodKubernetesCredentialsMounterImpl(
maybeUserSpecifiedMountedClientKeyFile: Option[String],
maybeUserSpecifiedMountedClientCertFile: Option[String],
maybeUserSpecifiedMountedOAuthTokenFile: Option[String],
maybeUserSpecifiedMountedCaCertFile: Option[String])
maybeUserSpecifiedMountedCaCertFile: Option[String],
maybeUserSpecifiedMountedTrustStoreFile: Option[String],
maybeUserSpecifiedMountedTrustStorePasswordFile: Option[String])
extends DriverPodKubernetesCredentialsMounter {

override def setDriverPodKubernetesCredentialLocations(sparkConf: SparkConf): SparkConf = {
Expand All @@ -78,6 +80,14 @@ private[spark] class DriverPodKubernetesCredentialsMounterImpl(
maybeUserSpecifiedMountedOAuthTokenFile,
submitterLocalDriverPodKubernetesCredentials.oauthTokenBase64,
DRIVER_CREDENTIALS_OAUTH_TOKEN_PATH)
val resolvedMountedTrustStoreFile = resolveSecretLocation(
maybeUserSpecifiedMountedTrustStoreFile,
submitterLocalDriverPodKubernetesCredentials.trustStoreDataBase64,
DRIVER_CREDENTIALS_TRUSTSTORE_PATH)
val resolvedMountedTrustStorePasswordFile = resolveSecretLocation(
maybeUserSpecifiedMountedTrustStorePasswordFile,
submitterLocalDriverPodKubernetesCredentials.trustStorePasswordBase64,
DRIVER_CREDENTIALS_TRUSTSTORE_PASSWORD_PATH)
val sparkConfWithCredentialLocations = sparkConf.clone()
.setOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$CA_CERT_FILE_CONF_SUFFIX",
Expand All @@ -91,6 +101,13 @@ private[spark] class DriverPodKubernetesCredentialsMounterImpl(
.setOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$OAUTH_TOKEN_FILE_CONF_SUFFIX",
resolvedMountedOAuthTokenFile)
.setOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$TRUSTSTORE_CONF_SUFFIX",
resolvedMountedTrustStoreFile)
.setOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$TRUSTSTORE_PASSWORD_CONF_SUFFIX",
resolvedMountedTrustStorePasswordFile)

// Redact all OAuth token values
sparkConfWithCredentialLocations
.getAll
Expand Down Expand Up @@ -118,7 +135,15 @@ private[spark] class DriverPodKubernetesCredentialsMounterImpl(
resolveSecretData(
maybeUserSpecifiedMountedOAuthTokenFile,
submitterLocalDriverPodKubernetesCredentials.oauthTokenBase64,
DRIVER_CREDENTIALS_OAUTH_TOKEN_SECRET_NAME)
DRIVER_CREDENTIALS_OAUTH_TOKEN_SECRET_NAME) ++
resolveSecretData(
maybeUserSpecifiedMountedTrustStoreFile,
submitterLocalDriverPodKubernetesCredentials.trustStoreDataBase64,
DRIVER_CREDENTIALS_TRUSTSTORE_SECRET_NAME) ++
resolveSecretData(
maybeUserSpecifiedMountedTrustStorePasswordFile,
submitterLocalDriverPodKubernetesCredentials.trustStorePasswordBase64,
DRIVER_CREDENTIALS_TRUSTSTORE_PASSWORD_SECRET_NAME)
if (allSecretData.isEmpty) {
None
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ private[spark] class DriverPodKubernetesCredentialsMounterProviderImpl(
sparkConf.getOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$OAUTH_TOKEN_FILE_CONF_SUFFIX"),
sparkConf.getOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$CA_CERT_FILE_CONF_SUFFIX"))
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$CA_CERT_FILE_CONF_SUFFIX"),
sparkConf.getOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$TRUSTSTORE_CONF_SUFFIX"),
sparkConf.getOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$TRUSTSTORE_PASSWORD_FILE_CONF_SUFFIX"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ private[spark] class DriverPodKubernetesCredentialsProvider(sparkConf: SparkConf
.map { token =>
BaseEncoding.base64().encode(token.getBytes(Charsets.UTF_8))
}
val trustStorePasswordBase64 = sparkConf
.getOption(s"$APISERVER_AUTH_DRIVER_CONF_PREFIX.$TRUSTSTORE_PASSWORD_CONF_SUFFIX")
.map { token =>
BaseEncoding.base64().encode(token.getBytes(Charsets.UTF_8))
}
val caCertDataBase64 = safeFileConfToBase64(
s"$APISERVER_AUTH_DRIVER_CONF_PREFIX.$CA_CERT_FILE_CONF_SUFFIX",
s"Driver CA cert file provided at %s does not exist or is not a file.")
Expand All @@ -43,11 +48,16 @@ private[spark] class DriverPodKubernetesCredentialsProvider(sparkConf: SparkConf
val clientCertDataBase64 = safeFileConfToBase64(
s"$APISERVER_AUTH_DRIVER_CONF_PREFIX.$CLIENT_CERT_FILE_CONF_SUFFIX",
s"Driver client cert file provided at %s does not exist or is not a file.")
val trustStoreDataBase64 = safeFileConfToBase64(
s"$APISERVER_AUTH_DRIVER_CONF_PREFIX.$TRUSTSTORE_CONF_SUFFIX",
s"Driver trustStore file provided at %s does not exist or is not a file.")
KubernetesCredentials(
oauthTokenBase64 = oauthTokenBase64,
caCertDataBase64 = caCertDataBase64,
clientKeyDataBase64 = clientKeyDataBase64,
clientCertDataBase64 = clientCertDataBase64)
clientCertDataBase64 = clientCertDataBase64,
trustStoreDataBase64 = trustStoreDataBase64,
trustStorePasswordBase64 = trustStorePasswordBase64)
}

private def safeFileConfToBase64(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,22 @@ class DriverPodKubernetesCredentialsMounterSuite
private val CLIENT_CERT_DATA = "client-cert-data"
private val OAUTH_TOKEN_DATA = "oauth-token"
private val CA_CERT_DATA = "ca-cert-data"
private val TRUSTSTORE_DATA = "trustStore"
private val TRUSTSTORE_PASSWORD_DATA = "trustStorePassword"
private val SUBMITTER_LOCAL_DRIVER_KUBERNETES_CREDENTIALS = KubernetesCredentials(
caCertDataBase64 = Some(CA_CERT_DATA),
clientKeyDataBase64 = Some(CLIENT_KEY_DATA),
clientCertDataBase64 = Some(CLIENT_CERT_DATA),
oauthTokenBase64 = Some(OAUTH_TOKEN_DATA))
oauthTokenBase64 = Some(OAUTH_TOKEN_DATA),
trustStoreDataBase64 = Some(TRUSTSTORE_DATA),
trustStorePasswordBase64 = Some(TRUSTSTORE_PASSWORD_DATA))
private val APP_ID = "app-id"
private val USER_SPECIFIED_CLIENT_KEY_FILE = Some("/var/data/client-key.pem")
private val USER_SPECIFIED_CLIENT_CERT_FILE = Some("/var/data/client-cert.pem")
private val USER_SPECIFIED_OAUTH_TOKEN_FILE = Some("/var/data/token.txt")
private val USER_SPECIFIED_CA_CERT_FILE = Some("/var/data/ca.pem")
private val USER_SPECIFIED_TRUSTSTORE_FILE = Some("/var/data/trustStore.jks")
private val USER_SPECIFIED_TRUSTSTORE_PASSWORD_FILE = Some("/var/data/trustStorePassword.txt")

// Different configurations of credentials mounters
private val credentialsMounterWithPreMountedFiles =
Expand All @@ -51,27 +57,42 @@ class DriverPodKubernetesCredentialsMounterSuite
maybeUserSpecifiedMountedClientKeyFile = USER_SPECIFIED_CLIENT_KEY_FILE,
maybeUserSpecifiedMountedClientCertFile = USER_SPECIFIED_CLIENT_CERT_FILE,
maybeUserSpecifiedMountedOAuthTokenFile = USER_SPECIFIED_OAUTH_TOKEN_FILE,
maybeUserSpecifiedMountedCaCertFile = USER_SPECIFIED_CA_CERT_FILE)
maybeUserSpecifiedMountedCaCertFile = USER_SPECIFIED_CA_CERT_FILE,
maybeUserSpecifiedMountedTrustStoreFile = USER_SPECIFIED_TRUSTSTORE_FILE,
maybeUserSpecifiedMountedTrustStorePasswordFile = USER_SPECIFIED_TRUSTSTORE_PASSWORD_FILE)
private val credentialsMounterWithoutPreMountedFiles =
new DriverPodKubernetesCredentialsMounterImpl(
kubernetesAppId = APP_ID,
submitterLocalDriverPodKubernetesCredentials = SUBMITTER_LOCAL_DRIVER_KUBERNETES_CREDENTIALS,
maybeUserSpecifiedMountedClientKeyFile = None,
maybeUserSpecifiedMountedClientCertFile = None,
maybeUserSpecifiedMountedOAuthTokenFile = None,
maybeUserSpecifiedMountedCaCertFile = None)
maybeUserSpecifiedMountedCaCertFile = None,
maybeUserSpecifiedMountedTrustStoreFile = None,
maybeUserSpecifiedMountedTrustStorePasswordFile = None)
private val credentialsMounterWithoutAnyDriverCredentials =
new DriverPodKubernetesCredentialsMounterImpl(
APP_ID, KubernetesCredentials(None, None, None, None), None, None, None, None)
APP_ID,
KubernetesCredentials(None, None, None, None, None, None),
None,
None,
None,
None,
None,
None)

// Test matrices
private val TEST_MATRIX_EXPECTED_SPARK_CONFS = Table(
("Credentials Mounter Implementation",
"Expected client key file",
"Expected client cert file",
"Expected CA Cert file",
"Expected OAuth Token File"),
"Expected OAuth Token File",
"Expected TrustStore File",
"Expected TrustStore Password File"),
(credentialsMounterWithoutAnyDriverCredentials,
None,
None,
None,
None,
None,
Expand All @@ -80,12 +101,16 @@ class DriverPodKubernetesCredentialsMounterSuite
Some(DRIVER_CREDENTIALS_CLIENT_KEY_PATH),
Some(DRIVER_CREDENTIALS_CLIENT_CERT_PATH),
Some(DRIVER_CREDENTIALS_CA_CERT_PATH),
Some(DRIVER_CREDENTIALS_OAUTH_TOKEN_PATH)),
Some(DRIVER_CREDENTIALS_OAUTH_TOKEN_PATH),
Some(DRIVER_CREDENTIALS_TRUSTSTORE_PATH),
Some(DRIVER_CREDENTIALS_TRUSTSTORE_PASSWORD_PATH)),
(credentialsMounterWithPreMountedFiles,
USER_SPECIFIED_CLIENT_KEY_FILE,
USER_SPECIFIED_CLIENT_CERT_FILE,
USER_SPECIFIED_CA_CERT_FILE,
USER_SPECIFIED_OAUTH_TOKEN_FILE))
USER_SPECIFIED_OAUTH_TOKEN_FILE,
USER_SPECIFIED_TRUSTSTORE_FILE,
USER_SPECIFIED_TRUSTSTORE_PASSWORD_FILE))

private val TEST_MATRIX_EXPECTED_CREDENTIALS_SECRET = Table(
("Credentials Mounter Implementation", "Expected Credentials Secret Data"),
Expand All @@ -96,18 +121,21 @@ class DriverPodKubernetesCredentialsMounterSuite
DRIVER_CREDENTIALS_CLIENT_KEY_SECRET_NAME -> CLIENT_KEY_DATA,
DRIVER_CREDENTIALS_CLIENT_CERT_SECRET_NAME -> CLIENT_CERT_DATA,
DRIVER_CREDENTIALS_CA_CERT_SECRET_NAME -> CA_CERT_DATA,
DRIVER_CREDENTIALS_OAUTH_TOKEN_SECRET_NAME -> OAUTH_TOKEN_DATA
),
DRIVER_CREDENTIALS_OAUTH_TOKEN_SECRET_NAME -> OAUTH_TOKEN_DATA,
DRIVER_CREDENTIALS_TRUSTSTORE_SECRET_NAME -> TRUSTSTORE_DATA,
DRIVER_CREDENTIALS_TRUSTSTORE_PASSWORD_SECRET_NAME -> TRUSTSTORE_PASSWORD_DATA),
name = s"$APP_ID-kubernetes-credentials"))),
(credentialsMounterWithPreMountedFiles, None))

test("Credentials mounter should set the driver's Kubernetes credentials locations") {
forAll(TEST_MATRIX_EXPECTED_SPARK_CONFS) {
case (credentialsMounter,
expectedClientKeyFile,
expectedClientCertFile,
expectedCaCertFile,
expectedOAuthTokenFile) =>
expectedClientKeyFile,
expectedClientCertFile,
expectedCaCertFile,
expectedOAuthTokenFile,
expectedTrustStoreFile,
expectedTrustStorePasswordFile) =>
val baseSparkConf = new SparkConf()
val resolvedSparkConf =
credentialsMounter.setDriverPodKubernetesCredentialLocations(baseSparkConf)
Expand All @@ -123,6 +151,12 @@ class DriverPodKubernetesCredentialsMounterSuite
assert(resolvedSparkConf.getOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$OAUTH_TOKEN_FILE_CONF_SUFFIX") ===
expectedOAuthTokenFile)
assert(resolvedSparkConf.getOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$TRUSTSTORE_CONF_SUFFIX") ===
expectedTrustStoreFile)
assert(resolvedSparkConf.getOption(
s"$APISERVER_AUTH_DRIVER_MOUNTED_CONF_PREFIX.$TRUSTSTORE_PASSWORD_CONF_SUFFIX") ===
expectedTrustStorePasswordFile)
}
}

Expand Down