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

Capability to specify per volume mount propagation mode #17034

Merged
merged 3 commits into from Dec 15, 2015

Conversation

rhvgoyal
Copy link
Contributor

Fixes #14630

This patch set allows one to specify mount propagation setting of a volume. Allowed values are "shared" or "slave" or "private".

For example.

docker run -ti -v /root/mnt-source:/root/mnt-dest:slave fedora bash

@rhvgoyal
Copy link
Contributor Author

@rhatdan
Copy link
Contributor

rhatdan commented Oct 14, 2015

If I specify two volumes one as shared and one as private

+   if hasSharedVolume {
+       execdriver.SetRootPropagation(container, mount.SHARED)
+       return nil
+   }
+
+   if hasSlaveVolume {
+       execdriver.SetRootPropagation(container, mount.RSLAVE)
+       return nil
+   }

Won't propogation end up being RSLAVE?

@rhvgoyal
Copy link
Contributor Author

I first check if there are any shared volumes and set propagation to "shared" and return. I think you missed the "return" statement.

@rhatdan
Copy link
Contributor

rhatdan commented Oct 14, 2015

Simpler would be to just check if a higher level is set and then don't change it.

if root prop = shared don't set to private, or slave,
If root prop == slave don't set to private

@rhvgoyal
Copy link
Contributor Author

@rhatdan I had thought about it. I think it is a good idea to implement it. Will do.

@rhvgoyal
Copy link
Contributor Author

  • Took care of Dan's comments. Now modifying root propagation only if needed.
  • Updated documentation of man pages.
  • Exported Propagation status through docker-inspect Mounts.

@rhvgoyal
Copy link
Contributor Author

HOW TO TEST

  • Make sure that source mount of directory being bind mounted is shared (for shared volumes) or shared/slave (for slave volumes).
  • Bind mount a directory as shared volume.
    docker run -ti /root/mnt-source:/root/mnt-dest:shared --cap-add SYS_ADMIN fedora bash
  • Inside container make sure mount is shared.
    findmnt -o TARGET,PROPAGATION /root/mnt-dest
  • Do a mount under shared volume inside container
    mkdir -p /root/mnt-dest/mnt1
    cd /root/mnt-dest
    mount --bind mnt1 mnt1
  • Make sure this new mount propagates to host. Run following on host.
    findmnt /root/mnt-source/mnt1

HOW TO DETERMINE SOURCE MOUNT

  • Run df <directory> and it will tell what's the source mount. Looks for column Mounted on

HOW TO CHECK PROPAGATION PROPERTY OF A MOUNT
findmnt -o TARGET,PROPAGATION <mount-point>

HOW TO CHANGE PROPAGATION PROPERTY OF A MOUNT
mount --make-shared <mnt-point>
mount --make-slave <mnt-point>

@@ -288,18 +289,42 @@ func (d *Driver) setupMounts(container *configs.Config, c *execdriver.Command) e

for _, m := range c.Mounts {
flags := syscall.MS_BIND | syscall.MS_REC
var propagationFlags []int
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this an array?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case it does not have to be. Will change it to integer.

@rhvgoyal
Copy link
Contributor Author

@crosbymichael Fixed the array issue. Also I have added another patch which verifies that source mount point has appropriate propagation properties for volume mount to work, otherwise container start will fail. PTAL.

@crosbymichael
Copy link
Contributor

Looks like your additional change broke some stuff and there was a bad rebase

@rhvgoyal
Copy link
Contributor Author

@crosbymichael Found the bug I had introduced. PropagationFlags need to be nil if there is no propagation flag to be applied. With the second round of changes, it got initialized to 0 and libcontainer was trying to apply that and failing. Fixed it.

Also rebased on top of latest code. This volume support on windows moved quite a few things around.

@crosbymichael
Copy link
Contributor

Build error on windows binaries

@rhvgoyal
Copy link
Contributor Author

hmm..., Need to define volume.GetPropagation() for windows. Will do.

@rhvgoyal
Copy link
Contributor Author

Defined a function GetPropagation() for windows which returns nil string. Hopefully that fixes windows build. lets see.

return rwModes[strings.ToLower(mode)]
}

// Windows does not support mount propagation. Just return empty string.
Copy link
Member

Choose a reason for hiding this comment

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

This should be godoc'd starting with the function name - something like "GetPropagation is a platform-specific function to ..... This is not supported on Windows".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jhowardmsft Will do. Thanks.

@lowenna
Copy link
Member

lowenna commented Oct 26, 2015

Apart from the godoc nit, LGTM from a Windows perspective. @rhvgoyal Apologies for the rebase pain with the introduction of volume support on Windows.

@rhvgoyal
Copy link
Contributor Author

Took care of validate-lint issue. Added a comment starting with GetPropagation.

@rhvgoyal
Copy link
Contributor Author

@crosbymichael Did some more changes. PTAL.

  • Added some unit and integration tests.
  • Reorganized the code a bit. Propagation logic is specific to linux and not all unix. So moved it to volume/volume_propagation_linux.go. And made windows, freebsd and darwin use definition from volume/volume_propagation_unsupported.go.

@rhvgoyal
Copy link
Contributor Author

@crosbymichael Right now these are 3 patches. Do let me know if you want me to merge all this in single patch.

@rhvgoyal
Copy link
Contributor Author

My newly introduced integration test TestRunVolumesMountedAsShared is failing. It passes on my local machine (make test-integration-cli). so this has something to do with environment. I am not sure what though. Anybody has a clue what might be going on or what else can I try.

FAIL: docker_cli_run_test.go:3615: DockerSuite.TestRunVolumesMountedAsShared

docker_cli_run_test.go:3644:
c.Fatalf("Failed to bind mount /volume-dest/mnt1: exit code %d", code)
... Error: Failed to bind mount /volume-dest/mnt1: exit code 255

@griwes
Copy link

griwes commented Dec 25, 2015

Oh look, this is exactly what I need for a thing I'm doing at this moment. When can a release including this functionality be expected to appear?

@thaJeztah thaJeztah added this to the 1.10 milestone Dec 25, 2015
@thaJeztah
Copy link
Member

@griwes this will be in the 1.10 release, probably in February. If you want to give it a test, you can either try the builds from master (https://master.dockerproject.org) or the experimental builds https://experimental.docker.com.

@lox
Copy link

lox commented Dec 26, 2015

Is it assumed knowledge that /root/mnt-source in your example needs to be mounted as "shared" on the host before this will work?

$ sudo mount --bind /root/mnt-source /root/mnt-source
$ sudo mount --make-shared /root/mnt-source

Without this I got an error indicating that /root/mnt-source wasn't shared (under Ubuntu 14.04 with the latest experimental docker).

@rhatdan
Copy link
Contributor

rhatdan commented Dec 27, 2015

Yes this is expected. Note that RHEL7, Fedora, And Centos come this way by default.


To change propagation properties of a mount point use `mount` command. For
example, if one wants to bind mount source directory `/foo` one can do
`mount --bind /foo /foo` and `mount --make-private --make-shared /foo`. This

Choose a reason for hiding this comment

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

shouldn't this be mount --make-shared (i.e. without --make-private)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Usage of --make-private decouples the mount from any other sharing already going on. So while this is not strictly necessary, this might be little less confusing in some of the configurations when propagation actually happens.

@kiwenlau
Copy link

@lox @rhatdan

How to set following permanently? I have to re mount it after reboot ubuntu...

sudo mount --bind /root/mnt-source /root/mnt-source
sudo mount --make-shared /root/mnt-source

Thx

@rhatdan
Copy link
Contributor

rhatdan commented Mar 11, 2016

Make a unit file or service script to do this.

@ghost
Copy link

ghost commented Mar 11, 2016

@kiwenlau on 14.10+ with systemd you can set the MountFlags=shared and you wont need to set --make-shared each time. You can also set that in /etc/fstab with 14.10+.

on 14.04 you are limited to some type of init script for this (can also be a udev trigger depending on if that makes the situation better)

@kiwenlau
Copy link

@rhatdan @SamYaple I use Ubuntu 14.04.
I can set mount in /etc/fstab:
/root/mnt-sourc         /root/mnt-sourc             none    bind            0       0

However, I can not set shared mount for it in fstab file. I have to manually set it when I reboot ubuntu
sudo mount --make-shared /root/mnt-source

It's OK for me, and I will try some init script to do it. Thanks.

@ghost
Copy link

ghost commented Mar 13, 2016

@kiwenlau Yes i believe I stated that this only works on 14.10+ when set in /etc/fstab or with the mount binary.

If you pullin the mount binary from 14.10+ it would work, but may break other things

lebauce pushed a commit to skydive-project/skydive that referenced this pull request Feb 8, 2017
As mentioned in moby/moby#17034
in order to follow the netns corresponding file when it gets bind mounted,
the netns directory bind mounted in the skydive agent container with a
docker volume option needs to have the "shared" propagation flag set.

By default, the propagation flag of a docker volume is "private", not
"shared".

This works since the usual source (/var/run/netns) also has the
"shared" propagation flag. Otherwise, one has to set it on the
source before starting the skydive agent container.

Change-Id: Ic321681269aba267a51bc0782f68683660c9eca0
Reviewed-on: https://softwarefactory-project.io/r/6397
Reviewed-by: Nicolas PLANEL <nplanel@redhat.com>
Reviewed-by: Sylvain Baubeau <sbaubeau@redhat.com>
Tested-by: Sylvain Baubeau <sbaubeau@redhat.com>
Workflow: Sylvain Baubeau <sbaubeau@redhat.com>
Tested-by: Jenkins CI <jenkins@softwarefactory-project.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet