Skip to content

Conversation

@liyinan926
Copy link
Contributor

@liyinan926 liyinan926 commented Jan 4, 2018

What changes were proposed in this pull request?

User-specified secrets are mounted into both the main container and init-container (when it is used) in a Spark driver/executor pod, using the MountSecretsBootstrap. Because MountSecretsBootstrap always adds new secret volumes for the secrets to the pod, the same secret volumes get added twice, one when mounting the secrets to the main container, and the other when mounting the secrets to the init-container. This PR fixes the issue by separating MountSecretsBootstrap.mountSecrets out into two methods: addSecretVolumes for adding secret volumes to a pod and mountSecrets for mounting secret volumes to a container, respectively. addSecretVolumes is only called once for each pod, whereas mountSecrets is called individually for the main container and the init-container (if it is used).

Ref: apache-spark-on-k8s#594.

How was this patch tested?

Unit tested.

@vanzin @jiangxb1987 @ueshin This is to fix a critical bug in 2.3. PTAL. Thanks!
@hex108 @foxish @kimoonkim

*
* @param pod the pod into which the secret volumes are being added.
* @param container the container into which the secret volumes are being mounted.
* @param addNewVolumes whether to add new secret volumes for the secrets.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this problem arose because we're conflating two things here - adding secret volumes (which are pod-scoped) and adding volume-mounts (which are container-scoped). I think we should separate these out. The branching may work for now, but we should have a future work item to separate these out.

cc/ @mccheah

Copy link
Contributor Author

@liyinan926 liyinan926 Jan 4, 2018

Choose a reason for hiding this comment

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

Agreed. I didn't separate it out because we will touch this code as part of refactoring the steps code anyway as planned in https://issues.apache.org/jira/browse/SPARK-22839.

@SparkQA
Copy link

SparkQA commented Jan 4, 2018

Test build #85664 has finished for PR 20148 at commit 9be26a8.

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

* @return the updated pod and container with the secrets mounted.
*/
def mountSecrets(pod: Pod, container: Container): (Pod, Container) = {
def mountSecrets(
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we separate this method into addSecretVolumes and mountSecrets? The former would just need the pod argument, and the latter would take the container as argument. That way, we could probably separate this out better and it would make it more readable than the branching. WDYT?

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. Done.

=== "secret1-volume")
assert(executor.getSpec.getInitContainers.get(0).getVolumeMounts.get(0)
.getMountPath === "/var/secret1")
assert(SecretVolumeUtils.containerHasVolume(
Copy link

Choose a reason for hiding this comment

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

It might be better to change None at line 168 to Some(secretBootstrap) and check volumes' number to avoid regression.

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.

Copy link

@hex108 hex108 Jan 4, 2018

Choose a reason for hiding this comment

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

Thanks! We also need check volumes' num in pod spec.

// check volume mounted.
assert(executor.getSpec.getVolumes.size() === 1)
assert(executor.getSpec.getVolumes.get(0).getSecret.getSecretName === "secret1")

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. 93e1d64.

@SparkQA
Copy link

SparkQA commented Jan 4, 2018

Test build #85667 has finished for PR 20148 at commit 2e6f7db.

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

@SparkQA
Copy link

SparkQA commented Jan 4, 2018

Test build #85668 has finished for PR 20148 at commit 92251aa.

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

@SparkQA
Copy link

SparkQA commented Jan 4, 2018

Test build #85669 has finished for PR 20148 at commit 93e1d64.

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

@jiangxb1987
Copy link
Contributor

LGTM, please also update the PR description.

@liyinan926
Copy link
Contributor Author

@jiangxb1987 Updated PR description.

def podHasVolume(driverPod: Pod, volumeName: String): Boolean = {
driverPod.getSpec.getVolumes.asScala.exists(volume => volume.getName == volumeName)
def podHasVolume(pod: Pod, volumeName: String): Boolean = {
pod.getSpec.getVolumes.asScala.exists(volume => volume.getName == volumeName)
Copy link
Contributor

Choose a reason for hiding this comment

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

Since you're touching this, the style is always .exists { foo => ... }.

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.

mountPath: String): Boolean = {
driverContainer.getVolumeMounts.asScala.exists(volumeMount =>
def containerHasVolume(container: Container, volumeName: String, mountPath: String): Boolean = {
container.getVolumeMounts.asScala.exists(volumeMount =>
Copy link
Contributor

Choose a reason for hiding this comment

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

Same 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.

Done.

@SparkQA
Copy link

SparkQA commented Jan 4, 2018

Test build #85690 has finished for PR 20148 at commit b17fe4d.

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A note on this change: it seems double quotes get literally added. With the double quotes appended explicitly here, when running SparkPi with an argument 5, an NumberFormatException will be thrown complaining that ""5"" is not parsable. So the explicit double quotes are not really needed.

Copy link
Contributor

@foxish foxish Jan 4, 2018

Choose a reason for hiding this comment

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

Thanks for calling this out - let's try and test this using an integration test as well in https://github.com/apache-spark-on-k8s/spark-integration/. Would be good to put in manual integration testing results here until we have the PRB automation figured out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I will add one to the PR under review.

@SparkQA
Copy link

SparkQA commented Jan 4, 2018

Test build #85693 has finished for PR 20148 at commit 6636410.

  • This patch fails Spark unit tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA
Copy link

SparkQA commented Jan 4, 2018

Test build #85694 has finished for PR 20148 at commit 92ef568.

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

@SparkQA
Copy link

SparkQA commented Jan 4, 2018

Test build #85695 has finished for PR 20148 at commit 5278ea7.

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

@liyinan926
Copy link
Contributor Author

@vanzin Can this be merged?

@vanzin
Copy link
Contributor

vanzin commented Jan 4, 2018

Merging to master / 2.3.

@vanzin
Copy link
Contributor

vanzin commented Jan 4, 2018

Actually no. Please open the PR against master instead.

@liyinan926
Copy link
Contributor Author

Why master?

@vanzin
Copy link
Contributor

vanzin commented Jan 4, 2018

Because all changes go to master first.

@liyinan926
Copy link
Contributor Author

liyinan926 commented Jan 4, 2018

Got it. @vanzin created #20159. Closing this one.

@liyinan926 liyinan926 closed this Jan 4, 2018
asfgit pushed a commit that referenced this pull request Jan 4, 2018
…container is used

## What changes were proposed in this pull request?

User-specified secrets are mounted into both the main container and init-container (when it is used) in a Spark driver/executor pod, using the `MountSecretsBootstrap`. Because `MountSecretsBootstrap` always adds new secret volumes for the secrets to the pod, the same secret volumes get added twice, one when mounting the secrets to the main container, and the other when mounting the secrets to the init-container. This PR fixes the issue by separating `MountSecretsBootstrap.mountSecrets` out into two methods: `addSecretVolumes` for adding secret volumes to a pod and `mountSecrets` for mounting secret volumes to a container, respectively. `addSecretVolumes` is only called once for each pod, whereas `mountSecrets` is called individually for the main container and the init-container (if it is used).

Ref: apache-spark-on-k8s#594.

## How was this patch tested?
Unit tested and manually tested.

vanzin This replaces #20148.
hex108 foxish kimoonkim

Author: Yinan Li <[email protected]>

Closes #20159 from liyinan926/master.

(cherry picked from commit e288fc8)
Signed-off-by: Marcelo Vanzin <[email protected]>
asfgit pushed a commit that referenced this pull request Jan 4, 2018
…container is used

## What changes were proposed in this pull request?

User-specified secrets are mounted into both the main container and init-container (when it is used) in a Spark driver/executor pod, using the `MountSecretsBootstrap`. Because `MountSecretsBootstrap` always adds new secret volumes for the secrets to the pod, the same secret volumes get added twice, one when mounting the secrets to the main container, and the other when mounting the secrets to the init-container. This PR fixes the issue by separating `MountSecretsBootstrap.mountSecrets` out into two methods: `addSecretVolumes` for adding secret volumes to a pod and `mountSecrets` for mounting secret volumes to a container, respectively. `addSecretVolumes` is only called once for each pod, whereas `mountSecrets` is called individually for the main container and the init-container (if it is used).

Ref: apache-spark-on-k8s#594.

## How was this patch tested?
Unit tested and manually tested.

vanzin This replaces #20148.
hex108 foxish kimoonkim

Author: Yinan Li <[email protected]>

Closes #20159 from liyinan926/master.
@liyinan926 liyinan926 deleted the branch-2.3 branch January 5, 2018 06:17
liyinan926 added a commit to apache-spark-on-k8s/spark that referenced this pull request Jan 12, 2018
…597)

* Avoids adding duplicated secret volumes when init-container is used

Cherry-picked from apache#20148.

* Added the missing commit from upstream
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants