*: initial update to kube 1.8

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
Antonio Murdaca 2017-09-26 16:23:09 +02:00
parent 2453222695
commit d6e819133d
No known key found for this signature in database
GPG key ID: B2BEAD150DE936B9
1237 changed files with 84117 additions and 564982 deletions

View file

@ -25,7 +25,7 @@ import (
"strings"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/util/exec"
"k8s.io/utils/exec"
)
// NsenterMounter is part of experimental support for running the kubelet
@ -51,7 +51,7 @@ import (
// contents. TODO: remove this requirement.
// 6. The host image must have mount, findmnt, and umount binaries in /bin,
// /usr/sbin, or /usr/bin
//
// 7. The host image should have systemd-run in /bin, /usr/sbin, or /usr/bin
// For more information about mount propagation modes, see:
// https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
type NsenterMounter struct {
@ -62,9 +62,10 @@ type NsenterMounter struct {
func NewNsenterMounter() *NsenterMounter {
m := &NsenterMounter{
paths: map[string]string{
"mount": "",
"findmnt": "",
"umount": "",
"mount": "",
"findmnt": "",
"umount": "",
"systemd-run": "",
},
}
// search for the mount command in other locations besides /usr/bin
@ -80,6 +81,7 @@ func NewNsenterMounter() *NsenterMounter {
break
}
// TODO: error, so that the kubelet can stop if the mounts don't exist
// (don't forget that systemd-run is optional)
}
return m
}
@ -88,9 +90,11 @@ func NewNsenterMounter() *NsenterMounter {
var _ = Interface(&NsenterMounter{})
const (
hostRootFsPath = "/rootfs"
hostProcMountsPath = "/rootfs/proc/1/mounts"
nsenterPath = "nsenter"
hostRootFsPath = "/rootfs"
hostProcMountsPath = "/rootfs/proc/1/mounts"
hostProcMountinfoPath = "/rootfs/proc/1/mountinfo"
hostMountNamespacePath = "/rootfs/proc/1/ns/mnt"
nsenterPath = "nsenter"
)
// Mount runs mount(8) in the host's root mount namespace. Aside from this
@ -128,26 +132,60 @@ func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options [
// makeNsenterArgs makes a list of argument to nsenter in order to do the
// requested mount.
func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options []string) []string {
nsenterArgs := []string{
"--mount=/rootfs/proc/1/ns/mnt",
"--",
n.absHostPath("mount"),
mountCmd := n.absHostPath("mount")
mountArgs := makeMountArgs(source, target, fstype, options)
if systemdRunPath, hasSystemd := n.paths["systemd-run"]; hasSystemd {
// Complete command line:
// nsenter --mount=/rootfs/proc/1/ns/mnt -- /bin/systemd-run --description=... --scope -- /bin/mount -t <type> <what> <where>
// Expected flow is:
// * nsenter breaks out of container's mount namespace and executes
// host's systemd-run.
// * systemd-run creates a transient scope (=~ cgroup) and executes its
// argument (/bin/mount) there.
// * mount does its job, forks a fuse daemon if necessary and finishes.
// (systemd-run --scope finishes at this point, returning mount's exit
// code and stdout/stderr - thats one of --scope benefits).
// * systemd keeps the fuse daemon running in the scope (i.e. in its own
// cgroup) until the fuse daemon dies (another --scope benefit).
// Kubelet container can be restarted and the fuse daemon survives.
// * When the daemon dies (e.g. during unmount) systemd removes the
// scope automatically.
mountCmd, mountArgs = addSystemdScope(systemdRunPath, target, mountCmd, mountArgs)
} else {
// Fall back to simple mount when the host has no systemd.
// Complete command line:
// nsenter --mount=/rootfs/proc/1/ns/mnt -- /bin/mount -t <type> <what> <where>
// Expected flow is:
// * nsenter breaks out of container's mount namespace and executes host's /bin/mount.
// * mount does its job, forks a fuse daemon if necessary and finishes.
// * Any fuse daemon runs in cgroup of kubelet docker container,
// restart of kubelet container will kill it!
// No code here, mountCmd and mountArgs use /bin/mount
}
args := makeMountArgs(source, target, fstype, options)
nsenterArgs := []string{
"--mount=" + hostMountNamespacePath,
"--",
mountCmd,
}
nsenterArgs = append(nsenterArgs, mountArgs...)
return append(nsenterArgs, args...)
return nsenterArgs
}
// Unmount runs umount(8) in the host's mount namespace.
func (n *NsenterMounter) Unmount(target string) error {
args := []string{
"--mount=/rootfs/proc/1/ns/mnt",
"--mount=" + hostMountNamespacePath,
"--",
n.absHostPath("umount"),
target,
}
// No need to execute systemd-run here, it's enough that unmount is executed
// in the host's mount namespace. It will finish appropriate fuse daemon(s)
// running in any scope.
glog.V(5).Infof("Unmount command: %v %v", nsenterPath, args)
exec := exec.New()
outputBytes, err := exec.Command(nsenterPath, args...).CombinedOutput()
@ -189,7 +227,7 @@ func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) {
// the first of multiple possible mountpoints using --first-only.
// Also add fstype output to make sure that the output of target file will give the full path
// TODO: Need more refactoring for this function. Track the solution with issue #26996
args := []string{"--mount=/rootfs/proc/1/ns/mnt", "--", n.absHostPath("findmnt"), "-o", "target,fstype", "--noheadings", "--first-only", "--target", file}
args := []string{"--mount=" + hostMountNamespacePath, "--", n.absHostPath("findmnt"), "-o", "target,fstype", "--noheadings", "--first-only", "--target", file}
glog.V(5).Infof("findmnt command: %v %v", nsenterPath, args)
exec := exec.New()
@ -201,8 +239,11 @@ func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) {
// It's safer to assume that it's not a mount point.
return true, nil
}
mountTarget := strings.Split(string(out), " ")[0]
mountTarget = strings.TrimSuffix(mountTarget, "\n")
mountTarget, err := parseFindMnt(string(out))
if err != nil {
return false, err
}
glog.V(5).Infof("IsLikelyNotMountPoint findmnt output for path %s: %v:", file, mountTarget)
if mountTarget == file {
@ -213,6 +254,18 @@ func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) {
return true, nil
}
// parse output of "findmnt -o target,fstype" and return just the target
func parseFindMnt(out string) (string, error) {
// cut trailing newline
out = strings.TrimSuffix(out, "\n")
// cut everything after the last space - it's the filesystem type
i := strings.LastIndex(out, " ")
if i == -1 {
return "", fmt.Errorf("error parsing findmnt output, expected at least one space: %q", out)
}
return out[:i], nil
}
// DeviceOpened checks if block device in use by calling Open with O_EXCL flag.
// Returns true if open returns errno EBUSY, and false if errno is nil.
// Returns an error if errno is any error other than EBUSY.
@ -239,3 +292,13 @@ func (n *NsenterMounter) absHostPath(command string) string {
}
return path
}
func (n *NsenterMounter) MakeRShared(path string) error {
nsenterCmd := nsenterPath
nsenterArgs := []string{
"--mount=" + hostMountNamespacePath,
"--",
n.absHostPath("mount"),
}
return doMakeRShared(path, hostProcMountinfoPath, nsenterCmd, nsenterArgs)
}