Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SPARK-22131][MESOS] Mesos driver secrets #19437

Closed
wants to merge 8 commits into from

Conversation

susanxhuynh
Copy link
Contributor

Background

In #18837 , @ArtRand added Mesos secrets support to the dispatcher. This PR is to add the same secrets support to the drivers. This means if the secret configs are set, the driver will launch executors that have access to either env or file-based secrets.

One use case for this is to support TLS in the driver <=> executor communication.

What changes were proposed in this pull request?

Most of the changes are a refactor of the dispatcher secrets support (#18837) - moving it to a common place that can be used by both the dispatcher and drivers. The same goes for the unit tests.

How was this patch tested?

There are four config combinations: [env or file-based] x [value or reference secret]. For each combination:

  • Added a unit test.
  • Tested in DC/OS.

@SparkQA
Copy link

SparkQA commented Oct 5, 2017

Test build #82475 has finished for PR 19437 at commit 6f062c0.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@susanxhuynh
Copy link
Contributor Author

@ArtRand @skonto Please review. Tests passed.

.getVariablesList
.asScala
assert(envVars
.filter(!_.getName.startsWith("SPARK_")).length == 2) // user-defined secret env vars
Copy link
Contributor

@skonto skonto Oct 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert(envVars.count(!_.getName.startsWith("SPARK_")) == 2)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

.getVariablesList
.asScala
assert(envVars
.filter(!_.getName.startsWith("SPARK_")).length == 2) // user-defined secret env vars
Copy link
Contributor

@skonto skonto Oct 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert(envVars.count(!_.getName.startsWith("SPARK_")) == 2)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll fix it.

@@ -122,7 +126,7 @@ private[mesos] object MesosSchedulerBackendUtil extends Logging {
.toList
}

def containerInfo(conf: SparkConf): ContainerInfo.Builder = {
def containerInfo(conf: SparkConf, secretConfig: MesosSecretConfig): ContainerInfo.Builder = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO a better name would be createContainerInfo or buildContainerInfo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll use buildContainerInfo.

@@ -17,10 +17,14 @@

package org.apache.spark.scheduler.cluster.mesos

import org.apache.mesos.Protos.{ContainerInfo, Image, NetworkInfo, Parameter, Volume}
import org.apache.mesos.Protos._
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid wild card imports if possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, IntelliJ added this automatically - I'll fix it.

if (referenceSecrets.nonEmpty) referenceSecrets else valueSecrets
}

private def illegalSecretInput(dest: Seq[String], s: Seq[Secret]): Boolean = {
Copy link
Contributor

@skonto skonto Oct 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s -> secrets

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -21,6 +21,39 @@ import java.util.concurrent.TimeUnit

import org.apache.spark.internal.config.ConfigBuilder

private[spark] class MesosSecretConfig(taskType: String) {
private[spark] val SECRET_NAME =
Copy link
Contributor

@skonto skonto Oct 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't be SECRET_NAMES? Same for the rest of the configs below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean. I'll change them.

}

private def illegalSecretInput(dest: Seq[String], s: Seq[Secret]): Boolean = {
if (dest.isEmpty) { // no destination set (ie not using secrets of this type
Copy link
Contributor

@skonto skonto Oct 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is redundant, it is covered by the last false statement anyway.
Does it make sense to have paths but no secrets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. If they specify paths but no secrets, it should throw an exception.

@skonto
Copy link
Contributor

skonto commented Oct 9, 2017

@susanxhuynh I think this a mesos 1.4 feature, shouldn't we document this for users?
https://issues.apache.org/jira/browse/MESOS-7418
Btw this scheduler still depends on mesos 1.3 proto,

@ArtRand
Copy link

ArtRand commented Oct 9, 2017

@susanxhuynh @skonto The secret-containing protos will be valid in Mesos 1.3 onwards, thus why the scheduler has that requirement. DC/OS with file-based secrets has Mesos 1.4 thus why we test it there.

Copy link
Contributor Author

@susanxhuynh susanxhuynh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll push another commit soon.

.getVariablesList
.asScala
assert(envVars
.filter(!_.getName.startsWith("SPARK_")).length == 2) // user-defined secret env vars
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll fix it.

@@ -21,6 +21,39 @@ import java.util.concurrent.TimeUnit

import org.apache.spark.internal.config.ConfigBuilder

private[spark] class MesosSecretConfig(taskType: String) {
private[spark] val SECRET_NAME =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean. I'll change them.

@@ -17,10 +17,14 @@

package org.apache.spark.scheduler.cluster.mesos

import org.apache.mesos.Protos.{ContainerInfo, Image, NetworkInfo, Parameter, Volume}
import org.apache.mesos.Protos._
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, IntelliJ added this automatically - I'll fix it.

@@ -122,7 +126,7 @@ private[mesos] object MesosSchedulerBackendUtil extends Logging {
.toList
}

def containerInfo(conf: SparkConf): ContainerInfo.Builder = {
def containerInfo(conf: SparkConf, secretConfig: MesosSecretConfig): ContainerInfo.Builder = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll use buildContainerInfo.

if (referenceSecrets.nonEmpty) referenceSecrets else valueSecrets
}

private def illegalSecretInput(dest: Seq[String], s: Seq[Secret]): Boolean = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

private def illegalSecretInput(dest: Seq[String], s: Seq[Secret]): Boolean = {
if (dest.isEmpty) { // no destination set (ie not using secrets of this type
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. If they specify paths but no secrets, it should throw an exception.

.getVariablesList
.asScala
assert(envVars
.filter(!_.getName.startsWith("SPARK_")).length == 2) // user-defined secret env vars
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

…(2) renamed 'containerInfo' -> 'buildContainerInfo', (3) added additional case to illegalSecretInput() check.
@SparkQA
Copy link

SparkQA commented Oct 9, 2017

Test build #82565 has finished for PR 19437 at commit 73b2cbf.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@skonto
Copy link
Contributor

skonto commented Oct 11, 2017

LGTM. @susanxhuynh have you tested this with TLS, just curious.

@susanxhuynh
Copy link
Contributor Author

@skonto I haven't tested with TLS; I'll work on that in the next couple of days.

@susanxhuynh
Copy link
Contributor Author

@vanzin Would you mind reviewing this PR? A followup to ArtRand's secrets PR.

Copy link

@ArtRand ArtRand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few nits mostly. Thanks.

@@ -159,7 +160,8 @@ private[spark] class MesosFineGrainedSchedulerBackend(
.setCommand(command)
.setData(ByteString.copyFrom(createExecArg()))

executorInfo.setContainer(MesosSchedulerBackendUtil.containerInfo(sc.conf))
executorInfo.setContainer(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd almost prefer that we don't add any features to fine-grained right now. As we have virtually no test coverage on whether or not this will work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 There is a PR for removing it already waiting for spark 3.0. Let's to give users the wrong impression that we maintain it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I've reverted this change in fine-grained mode.

@@ -122,7 +126,8 @@ private[mesos] object MesosSchedulerBackendUtil extends Logging {
.toList
}

def containerInfo(conf: SparkConf): ContainerInfo.Builder = {
def buildContainerInfo(conf: SparkConf, secretConfig: MesosSecretConfig):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe change secretConfig to mesosConfig and pass the whole thing? That way if we want to add new functionality later this function is more general. Given that most of what we do is proto-generation, I bet we'll have to do this eventually anyways.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed that second parameter and moved the secret stuff out of this method, since it's called by Fine-Grained mode, and we don't want to touch Fine-Grained mode.

@@ -170,9 +175,119 @@ private[mesos] object MesosSchedulerBackendUtil extends Logging {
containerInfo.addNetworkInfos(info)
}

getSecretVolume(conf, secretConfig).foreach { volume =>
if (volume.getSource.getSecret.getReference.isInitialized) {
logInfo(s"Setting reference secret ${volume.getSource.getSecret.getReference.getName}" +
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need a space at the end of this log line (my bad!)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

secretConfig: MesosSecretConfig): Unit = {
getSecretEnvVar(conf, secretConfig).foreach { variable =>
if (variable.getSecret.getReference.isInitialized) {
logInfo(s"Setting reference secret ${variable.getSecret.getReference.getName}" +
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space at the end of this log line too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

<td><code>spark.mesos.executor.secret.envkeys</code></td>
<td><code>(none)</code></td>
<td>
A comma-separated list that, if set, the contents of the secret referenced
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about putting an example here like we do for spark.mesos.network.labels - something general for all secrets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add some examples. I didn't find a good general example; I added a separate example to each config option.

containerInfo
}

def addSecretEnvVar(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to make this return List[Variable] like it used to as opposed to mutating the Environment.Builder, just more consistent (e.g. getSecretVolume)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed this method. To be more consistent, I've moved this code back into MesosClusterScheduler. There's a little duplication, because MesosCoarseGrainedSchedulerBackend now has a similar code snippet, but it does avoid the mutation.

}

private def getSecrets(conf: SparkConf, secretConfig: MesosSecretConfig):
Seq[Secret] = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -17,10 +17,14 @@

package org.apache.spark.scheduler.cluster.mesos
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, why do we have this file and MesosSchedulerUtils?

Copy link
Contributor

@skonto skonto Oct 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is for the MesosScheduler's helper functions but there are methods (eg. createResource) used all over the place. We need to cleanup the code at some point.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok. One of these days let's make a "clean up" JIRA and harmonize all of this code. The naming is also all over the place..

…e in FineGrainedSchedulerBackend, and moved the getSecretEnvVar and getSecretVolumes code blocks to be more consistent with rest of code.
Copy link
Contributor Author

@susanxhuynh susanxhuynh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ArtRand @skonto I reverted the change in Fine-Grained mode. There's a change in the method name, but that's it.

@ArtRand I've added the doc examples, and did a little re-arranging of the code to address the consistency issue you raised (getSecretEnvVar and getSecretVolumes code blocks).

<td><code>spark.mesos.executor.secret.envkeys</code></td>
<td><code>(none)</code></td>
<td>
A comma-separated list that, if set, the contents of the secret referenced
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add some examples. I didn't find a good general example; I added a separate example to each config option.

@@ -159,7 +160,8 @@ private[spark] class MesosFineGrainedSchedulerBackend(
.setCommand(command)
.setData(ByteString.copyFrom(createExecArg()))

executorInfo.setContainer(MesosSchedulerBackendUtil.containerInfo(sc.conf))
executorInfo.setContainer(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I've reverted this change in fine-grained mode.

@@ -122,7 +126,8 @@ private[mesos] object MesosSchedulerBackendUtil extends Logging {
.toList
}

def containerInfo(conf: SparkConf): ContainerInfo.Builder = {
def buildContainerInfo(conf: SparkConf, secretConfig: MesosSecretConfig):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed that second parameter and moved the secret stuff out of this method, since it's called by Fine-Grained mode, and we don't want to touch Fine-Grained mode.

@@ -170,9 +175,119 @@ private[mesos] object MesosSchedulerBackendUtil extends Logging {
containerInfo.addNetworkInfos(info)
}

getSecretVolume(conf, secretConfig).foreach { volume =>
if (volume.getSource.getSecret.getReference.isInitialized) {
logInfo(s"Setting reference secret ${volume.getSource.getSecret.getReference.getName}" +
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

containerInfo
}

def addSecretEnvVar(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed this method. To be more consistent, I've moved this code back into MesosClusterScheduler. There's a little duplication, because MesosCoarseGrainedSchedulerBackend now has a similar code snippet, but it does avoid the mutation.

}

private def getSecrets(conf: SparkConf, secretConfig: MesosSecretConfig):
Seq[Secret] = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

secretConfig: MesosSecretConfig): Unit = {
getSecretEnvVar(conf, secretConfig).foreach { variable =>
if (variable.getSecret.getReference.isInitialized) {
logInfo(s"Setting reference secret ${variable.getSecret.getReference.getName}" +
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@SparkQA
Copy link

SparkQA commented Oct 18, 2017

Test build #82867 has finished for PR 19437 at commit 770d307.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA
Copy link

SparkQA commented Oct 18, 2017

Test build #82868 has finished for PR 19437 at commit b2a3675.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

Copy link

@ArtRand ArtRand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -17,10 +17,14 @@

package org.apache.spark.scheduler.cluster.mesos
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok. One of these days let's make a "clean up" JIRA and harmonize all of this code. The naming is also all over the place..

}

def getSecretEnvVar(conf: SparkConf, secretConfig: MesosSecretConfig):
List[Variable] = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -501,23 +503,74 @@ See the [configuration page](configuration.html) for information on Spark config
spark.mesos.driver.secret.names or spark.mesos.driver.secret.values will be
written to the provided file. Paths are relative to the container's work
directory. Absolute paths must already exist. Consult the Mesos Secret
protobuf for more information.
protobuf for more information. Example:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the policy should be on this, but IIUC file-based secrets does require a backend module. Should we mention that here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mentioned custom module and added link to Mesos documentation.

@@ -122,7 +126,8 @@ private[mesos] object MesosSchedulerBackendUtil extends Logging {
.toList
}

def containerInfo(conf: SparkConf): ContainerInfo.Builder = {
def buildContainerInfo(conf: SparkConf):
ContainerInfo.Builder = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@SparkQA
Copy link

SparkQA commented Oct 18, 2017

Test build #82885 has finished for PR 19437 at commit a801799.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@susanxhuynh
Copy link
Contributor Author

@srowen Would you like to help review? Adding Mesos secrets support in driver for executor tasks.

@susanxhuynh
Copy link
Contributor Author

@vanzin Ping, would you mind reviewing this PR?

@susanxhuynh
Copy link
Contributor Author

@srowen Ping, would you like to help review?

Copy link
Contributor

@vanzin vanzin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't really comment on the functionality since I don't know Mesos, but the docs are really confusing.

<td><code>spark.mesos.executor.secret.envkeys</code></td>
<td><code>(none)</code></td>
<td>
A comma-separated list that, if set, the contents of the secret referenced
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot really understand this description.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me try to improve the descriptions of all these secret configs.


<pre>ENVKEY1,ENVKEY2</pre>
</td>
</tr>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation doesn't match other rows.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

</td>
</tr>
<tr>
<td><code>spark.mesos.executor.secret.filenames</code></td>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is off.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

<td><code>spark.mesos.executor.secret.filenames</code></td>
<td><code>(none)</code></td>
<td>
A comma-separated list that, if set, the contents of the secret referenced by
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is another description that is very weirdly worded. What I can understand of this:

"A comma-separated list of file names to which secret names and values will be written."

But I can't really know whether that's the case because it's really confusing.

</td>
</tr>
<tr>
<td><code>spark.mesos.driver.secret.values</code></td>
<td><code>(none)</code></td>
<td>
A comma-separated list of secret values. Consult the Mesos Secret
protobuf for more information.
protobuf for more information. Example:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "protobuf" thing is mentioned in a bunch of places but there's no link nor explanation of what it is. Are Mesos users just supposed to know what that is?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have grouped some of these properties together to make the description clearer. Please let me know what you think.

@@ -394,9 +393,10 @@ private[spark] class MesosClusterScheduler(
}

// add secret environment variables
getSecretEnvVar(desc).foreach { variable =>
MesosSchedulerBackendUtil.getSecretEnvVar(desc.conf, config.driverSecretConfig)
.foreach { variable =>
if (variable.getSecret.getReference.isInitialized) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block now needs to be indented further.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


MesosSchedulerBackendUtil.getSecretVolume(desc.conf, config.driverSecretConfig)
.foreach { volume =>
if (volume.getSource.getSecret.getReference.isInitialized) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent further.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@@ -122,7 +126,8 @@ private[mesos] object MesosSchedulerBackendUtil extends Logging {
.toList
}

def containerInfo(conf: SparkConf): ContainerInfo.Builder = {
def buildContainerInfo(conf: SparkConf):
ContainerInfo.Builder = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to previous line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

}

secrets.zip(secretPaths).map {
case (s, p) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to previous line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

}

secrets.zip(secretEnvKeys).map {
case (s, k) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to previous line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

…tation, added private constructor, fixed formatting.
Copy link
Contributor Author

@susanxhuynh susanxhuynh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vanzin Thanks for the feedback! PTAL:

</td>
</tr>
<tr>
<td><code>spark.mesos.driver.secret.values</code></td>
<td><code>(none)</code></td>
<td>
A comma-separated list of secret values. Consult the Mesos Secret
protobuf for more information.
protobuf for more information. Example:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have grouped some of these properties together to make the description clearer. Please let me know what you think.


<pre>ENVKEY1,ENVKEY2</pre>
</td>
</tr>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

<td><code>spark.mesos.executor.secret.envkeys</code></td>
<td><code>(none)</code></td>
<td>
A comma-separated list that, if set, the contents of the secret referenced
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me try to improve the descriptions of all these secret configs.

</td>
</tr>
<tr>
<td><code>spark.mesos.executor.secret.filenames</code></td>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@@ -21,6 +21,39 @@ import java.util.concurrent.TimeUnit

import org.apache.spark.internal.config.ConfigBuilder

private[spark] class MesosSecretConfig(taskType: String) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I've moved this MesosSecretConfig class inside the config object, and made the constructor private to that object.

@@ -394,9 +393,10 @@ private[spark] class MesosClusterScheduler(
}

// add secret environment variables
getSecretEnvVar(desc).foreach { variable =>
MesosSchedulerBackendUtil.getSecretEnvVar(desc.conf, config.driverSecretConfig)
.foreach { variable =>
if (variable.getSecret.getReference.isInitialized) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


MesosSchedulerBackendUtil.getSecretVolume(desc.conf, config.driverSecretConfig)
.foreach { volume =>
if (volume.getSource.getSecret.getReference.isInitialized) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@@ -122,7 +126,8 @@ private[mesos] object MesosSchedulerBackendUtil extends Logging {
.toList
}

def containerInfo(conf: SparkConf): ContainerInfo.Builder = {
def buildContainerInfo(conf: SparkConf):
ContainerInfo.Builder = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

}

secrets.zip(secretPaths).map {
case (s, p) =>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

}

secrets.zip(secretEnvKeys).map {
case (s, k) =>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@SparkQA
Copy link

SparkQA commented Oct 25, 2017

Test build #83049 has finished for PR 19437 at commit 3cd1ae8.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

Copy link
Contributor

@vanzin vanzin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly just want to confirm the docs look ok. They are much clearer now (aside from the question about the secret store).

A comma-separated list that, if set, the contents of the secret referenced
by spark.mesos.driver.secret.names or spark.mesos.driver.secret.values will be
set to the provided environment variable in the driver's process.
<code>spark.mesos.driver.secret.values</code>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you generate the docs to see how this looks? I wonder how browsers will try to render this extra-wide column.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks okay in a browser. This column takes up about 25% of the page width. Here's a screenshot:
documentation screenshot

A secret is specified by its contents and destination. These properties
specify a secret's contents. To specify a secret's destination, see the cell below.

You can specify a secret's contents either (1) by value or (2) by reference.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to confirm this cell renders as expected, and not in a single paragraph or something odd like that. I'm not really familiar with how jekyll translates this into HTML.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I added <p> paragraph tags to separate paragraphs in this table cell. (Jekyll doesn't need them in normal text body, only inside a table cell.)


<pre>spark.mesos.driver.secret.values=guessme</pre>

(2) To specify a secret that has been placed in a secret store
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this secret store? I don't remember Spark providing this feature, so it's not clear how this secret store is configured or used by Spark.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a note about this. The secret store has to be provided by the user. You can configure Mesos to integrate with a secret store via a custom Mesos module.

}

if (valueSecrets.nonEmpty && referenceSecrets.nonEmpty) {
throw new SparkException("Cannot specify VALUE type secrets and REFERENCE types ones")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Cannot specify both value-type and reference-type secrets."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

}

val referenceSecrets: Seq[Secret] =
conf.get(secretConfig.SECRET_NAMES).getOrElse(Nil).map(s => createReferenceSecret(s))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (also in other places): .map { s => ... }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@SparkQA
Copy link

SparkQA commented Oct 26, 2017

Test build #83085 has finished for PR 19437 at commit 88dfb42.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

Copy link
Contributor Author

@susanxhuynh susanxhuynh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vanzin I've built the docs and made sure they look good:

A comma-separated list that, if set, the contents of the secret referenced
by spark.mesos.driver.secret.names or spark.mesos.driver.secret.values will be
set to the provided environment variable in the driver's process.
<code>spark.mesos.driver.secret.values</code>,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks okay in a browser. This column takes up about 25% of the page width. Here's a screenshot:
documentation screenshot

A secret is specified by its contents and destination. These properties
specify a secret's contents. To specify a secret's destination, see the cell below.

You can specify a secret's contents either (1) by value or (2) by reference.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I added <p> paragraph tags to separate paragraphs in this table cell. (Jekyll doesn't need them in normal text body, only inside a table cell.)


<pre>spark.mesos.driver.secret.values=guessme</pre>

(2) To specify a secret that has been placed in a secret store
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a note about this. The secret store has to be provided by the user. You can configure Mesos to integrate with a secret store via a custom Mesos module.

}

if (valueSecrets.nonEmpty && referenceSecrets.nonEmpty) {
throw new SparkException("Cannot specify VALUE type secrets and REFERENCE types ones")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

}

val referenceSecrets: Seq[Secret] =
conf.get(secretConfig.SECRET_NAMES).getOrElse(Nil).map(s => createReferenceSecret(s))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@vanzin
Copy link
Contributor

vanzin commented Oct 26, 2017

Merging to master.

@asfgit asfgit closed this in 5415963 Oct 26, 2017
susanxhuynh added a commit to mesosphere/spark that referenced this pull request Nov 14, 2017
In apache#18837 , ArtRand added Mesos secrets support to the dispatcher. **This PR is to add the same secrets support to the drivers.** This means if the secret configs are set, the driver will launch executors that have access to either env or file-based secrets.

One use case for this is to support TLS in the driver <=> executor communication.

Most of the changes are a refactor of the dispatcher secrets support (apache#18837) - moving it to a common place that can be used by both the dispatcher and drivers. The same goes for the unit tests.

There are four config combinations: [env or file-based] x [value or reference secret]. For each combination:
- Added a unit test.
- Tested in DC/OS.

Author: Susan X. Huynh <xhuynh@mesosphere.com>

Closes apache#19437 from susanxhuynh/sh-mesos-driver-secret.
@susanxhuynh susanxhuynh deleted the sh-mesos-driver-secret branch November 15, 2017 17:43
susanxhuynh added a commit to mesosphere/spark that referenced this pull request Jan 14, 2018
In apache#18837 , ArtRand added Mesos secrets support to the dispatcher. **This PR is to add the same secrets support to the drivers.** This means if the secret configs are set, the driver will launch executors that have access to either env or file-based secrets.

One use case for this is to support TLS in the driver <=> executor communication.

Most of the changes are a refactor of the dispatcher secrets support (apache#18837) - moving it to a common place that can be used by both the dispatcher and drivers. The same goes for the unit tests.

There are four config combinations: [env or file-based] x [value or reference secret]. For each combination:
- Added a unit test.
- Tested in DC/OS.

Author: Susan X. Huynh <xhuynh@mesosphere.com>

Closes apache#19437 from susanxhuynh/sh-mesos-driver-secret.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants