Implement mount propagation in docker shim

This commit is contained in:
Jan Safranek 2017-08-29 10:01:04 +02:00
parent 9a7465a4e2
commit 0c767355d8
2 changed files with 91 additions and 13 deletions

View File

@ -124,29 +124,40 @@ func extractLabels(input map[string]string) (map[string]string, map[string]strin
// generateMountBindings converts the mount list to a list of strings that // generateMountBindings converts the mount list to a list of strings that
// can be understood by docker. // can be understood by docker.
// Each element in the string is in the form of: // '<HostPath>:<ContainerPath>[:options]', where 'options'
// '<HostPath>:<ContainerPath>', or // is a comma-separated list of the following strings:
// '<HostPath>:<ContainerPath>:ro', if the path is read only, or // 'ro', if the path is read only
// '<HostPath>:<ContainerPath>:Z', if the volume requires SELinux // 'Z', if the volume requires SELinux relabeling
// relabeling and the pod provides an SELinux label // propagation mode such as 'rslave'
func generateMountBindings(mounts []*runtimeapi.Mount) []string { func generateMountBindings(mounts []*runtimeapi.Mount) []string {
result := make([]string, 0, len(mounts)) result := make([]string, 0, len(mounts))
for _, m := range mounts { for _, m := range mounts {
bind := fmt.Sprintf("%s:%s", m.HostPath, m.ContainerPath) bind := fmt.Sprintf("%s:%s", m.HostPath, m.ContainerPath)
readOnly := m.Readonly var attrs []string
if readOnly { if m.Readonly {
bind += ":ro" attrs = append(attrs, "ro")
} }
// Only request relabeling if the pod provides an SELinux context. If the pod // Only request relabeling if the pod provides an SELinux context. If the pod
// does not provide an SELinux context relabeling will label the volume with // does not provide an SELinux context relabeling will label the volume with
// the container's randomly allocated MCS label. This would restrict access // the container's randomly allocated MCS label. This would restrict access
// to the volume to the container which mounts it first. // to the volume to the container which mounts it first.
if m.SelinuxRelabel { if m.SelinuxRelabel {
if readOnly { attrs = append(attrs, "Z")
bind += ",Z" }
} else { switch m.Propagation {
bind += ":Z" case runtimeapi.MountPropagation_PROPAGATION_PRIVATE:
} // noop, private is default
case runtimeapi.MountPropagation_PROPAGATION_BIDIRECTIONAL:
attrs = append(attrs, "rshared")
case runtimeapi.MountPropagation_PROPAGATION_HOST_TO_CONTAINER:
attrs = append(attrs, "rslave")
default:
glog.Warningf("unknown propagation mode for hostPath %q", m.HostPath)
// Falls back to "private"
}
if len(attrs) > 0 {
bind = fmt.Sprintf("%s:%s", bind, strings.Join(attrs, ","))
} }
result = append(result, bind) result = append(result, bind)
} }

View File

@ -323,3 +323,70 @@ func TestMakePortsAndBindings(t *testing.T) {
assert.Equal(t, test.portmappings, actualPortMappings) assert.Equal(t, test.portmappings, actualPortMappings)
} }
} }
func TestGenerateMountBindings(t *testing.T) {
mounts := []*runtimeapi.Mount{
// everything default
{
HostPath: "/mnt/1",
ContainerPath: "/var/lib/mysql/1",
},
// readOnly
{
HostPath: "/mnt/2",
ContainerPath: "/var/lib/mysql/2",
Readonly: true,
},
// SELinux
{
HostPath: "/mnt/3",
ContainerPath: "/var/lib/mysql/3",
SelinuxRelabel: true,
},
// Propagation private
{
HostPath: "/mnt/4",
ContainerPath: "/var/lib/mysql/4",
Propagation: runtimeapi.MountPropagation_PROPAGATION_PRIVATE,
},
// Propagation rslave
{
HostPath: "/mnt/5",
ContainerPath: "/var/lib/mysql/5",
Propagation: runtimeapi.MountPropagation_PROPAGATION_HOST_TO_CONTAINER,
},
// Propagation rshared
{
HostPath: "/mnt/6",
ContainerPath: "/var/lib/mysql/6",
Propagation: runtimeapi.MountPropagation_PROPAGATION_BIDIRECTIONAL,
},
// Propagation unknown (falls back to private)
{
HostPath: "/mnt/7",
ContainerPath: "/var/lib/mysql/7",
Propagation: runtimeapi.MountPropagation(42),
},
// Everything
{
HostPath: "/mnt/8",
ContainerPath: "/var/lib/mysql/8",
Readonly: true,
SelinuxRelabel: true,
Propagation: runtimeapi.MountPropagation_PROPAGATION_BIDIRECTIONAL,
},
}
expectedResult := []string{
"/mnt/1:/var/lib/mysql/1",
"/mnt/2:/var/lib/mysql/2:ro",
"/mnt/3:/var/lib/mysql/3:Z",
"/mnt/4:/var/lib/mysql/4",
"/mnt/5:/var/lib/mysql/5:rslave",
"/mnt/6:/var/lib/mysql/6:rshared",
"/mnt/7:/var/lib/mysql/7",
"/mnt/8:/var/lib/mysql/8:ro,Z,rshared",
}
result := generateMountBindings(mounts)
assert.Equal(t, result, expectedResult)
}