From 55e6eb2ce366b6e66a131f5fd836c51f2beac6b7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 2 May 2016 17:27:41 -0500 Subject: [PATCH] Allow using netns path instead of container PID to change hairpin mode --- pkg/kubelet/dockertools/manager.go | 2 +- pkg/kubelet/network/hairpin/hairpin.go | 31 ++++++++++++++------- pkg/kubelet/network/hairpin/hairpin_test.go | 3 +- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/pkg/kubelet/dockertools/manager.go b/pkg/kubelet/dockertools/manager.go index 10ac9e281f3..2258e7e222c 100644 --- a/pkg/kubelet/dockertools/manager.go +++ b/pkg/kubelet/dockertools/manager.go @@ -1957,7 +1957,7 @@ func (dm *DockerManager) SyncPod(pod *api.Pod, _ api.PodStatus, podStatus *kubec } if dm.configureHairpinMode { - if err = hairpin.SetUpContainer(podInfraContainer.State.Pid, network.DefaultInterfaceName); err != nil { + if err = hairpin.SetUpContainerPid(podInfraContainer.State.Pid, network.DefaultInterfaceName); err != nil { glog.Warningf("Hairpin setup failed for pod %q: %v", format.Pod(pod), err) } } diff --git a/pkg/kubelet/network/hairpin/hairpin.go b/pkg/kubelet/network/hairpin/hairpin.go index cf5d2937563..b725fbba3af 100644 --- a/pkg/kubelet/network/hairpin/hairpin.go +++ b/pkg/kubelet/network/hairpin/hairpin.go @@ -40,13 +40,23 @@ var ( ethtoolOutputRegex = regexp.MustCompile("peer_ifindex: (\\d+)") ) -func SetUpContainer(containerPid int, containerInterfaceName string) error { - e := exec.New() - return setUpContainerInternal(e, containerPid, containerInterfaceName) +func SetUpContainerPid(containerPid int, containerInterfaceName string) error { + pidStr := fmt.Sprintf("%d", containerPid) + nsenterArgs := []string{"-t", pidStr, "-n"} + return setUpContainerInternal(containerInterfaceName, pidStr, nsenterArgs) } -func setUpContainerInternal(e exec.Interface, containerPid int, containerInterfaceName string) error { - hostIfName, err := findPairInterfaceOfContainerInterface(e, containerPid, containerInterfaceName) +func SetUpContainerPath(netnsPath string, containerInterfaceName string) error { + if netnsPath[0] != '/' { + return fmt.Errorf("netnsPath path '%s' was invalid", netnsPath) + } + nsenterArgs := []string{"-n", netnsPath} + return setUpContainerInternal(containerInterfaceName, netnsPath, nsenterArgs) +} + +func setUpContainerInternal(containerInterfaceName, containerDesc string, nsenterArgs []string) error { + e := exec.New() + hostIfName, err := findPairInterfaceOfContainerInterface(e, containerInterfaceName, containerDesc, nsenterArgs) if err != nil { glog.Infof("Unable to find pair interface, setting up all interfaces: %v", err) return setUpAllInterfaces() @@ -54,7 +64,7 @@ func setUpContainerInternal(e exec.Interface, containerPid int, containerInterfa return setUpInterface(hostIfName) } -func findPairInterfaceOfContainerInterface(e exec.Interface, containerPid int, containerInterfaceName string) (string, error) { +func findPairInterfaceOfContainerInterface(e exec.Interface, containerInterfaceName, containerDesc string, nsenterArgs []string) (string, error) { nsenterPath, err := e.LookPath("nsenter") if err != nil { return "", err @@ -63,15 +73,16 @@ func findPairInterfaceOfContainerInterface(e exec.Interface, containerPid int, c if err != nil { return "", err } - // Get container's interface index - output, err := e.Command(nsenterPath, "-t", fmt.Sprintf("%d", containerPid), "-n", "-F", "--", ethtoolPath, "--statistics", containerInterfaceName).CombinedOutput() + + nsenterArgs = append(nsenterArgs, "-F", "--", ethtoolPath, "--statistics", containerInterfaceName) + output, err := e.Command(nsenterPath, nsenterArgs...).CombinedOutput() if err != nil { - return "", fmt.Errorf("Unable to query interface %s of container %d: %v: %s", containerInterfaceName, containerPid, err, string(output)) + return "", fmt.Errorf("Unable to query interface %s of container %s: %v: %s", containerInterfaceName, containerDesc, err, string(output)) } // look for peer_ifindex match := ethtoolOutputRegex.FindSubmatch(output) if match == nil { - return "", fmt.Errorf("No peer_ifindex in interface statistics for %s of container %d", containerInterfaceName, containerPid) + return "", fmt.Errorf("No peer_ifindex in interface statistics for %s of container %s", containerInterfaceName, containerDesc) } peerIfIndex, err := strconv.Atoi(string(match[1])) if err != nil { // seems impossible (\d+ not numeric) diff --git a/pkg/kubelet/network/hairpin/hairpin_test.go b/pkg/kubelet/network/hairpin/hairpin_test.go index 63bc9ef5bad..b94c7b997cb 100644 --- a/pkg/kubelet/network/hairpin/hairpin_test.go +++ b/pkg/kubelet/network/hairpin/hairpin_test.go @@ -69,7 +69,8 @@ func TestFindPairInterfaceOfContainerInterface(t *testing.T) { return fmt.Sprintf("/fake-bin/%s", file), nil }, } - name, err := findPairInterfaceOfContainerInterface(&fexec, 123, "eth0") + nsenterArgs := []string{"-t", "123", "-n"} + name, err := findPairInterfaceOfContainerInterface(&fexec, "eth0", "123", nsenterArgs) if test.expectErr { if err == nil { t.Errorf("unexpected non-error")