From 8f7b5bcfd33f12ce43733624c3308b906b3ea80a Mon Sep 17 00:00:00 2001 From: Euan Kemp Date: Mon, 11 Jul 2016 17:08:33 -0700 Subject: [PATCH 1/2] network/cni: Always setup 'lo' See issue #28561 --- pkg/kubelet/network/cni/cni.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/pkg/kubelet/network/cni/cni.go b/pkg/kubelet/network/cni/cni.go index 81e7d0c0cfa..4830aa79efe 100644 --- a/pkg/kubelet/network/cni/cni.go +++ b/pkg/kubelet/network/cni/cni.go @@ -39,6 +39,7 @@ const ( type cniNetworkPlugin struct { network.NoopNetworkPlugin + loNetwork *cniNetwork defaultNetwork *cniNetwork host network.Host execer utilexec.Interface @@ -104,6 +105,23 @@ func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode componentcon return err } + loConfig, err := libcni.ConfFromBytes([]byte(`{ + "cniVersion": "0.1.0", + "name": "cni-loopback", + "type": "loopback" +}`)) + if err != nil { + return err + } + cninet := &libcni.CNIConfig{ + Path: []string{DefaultCNIDir}, + } + plugin.loNetwork = &cniNetwork{ + name: "lo", + NetworkConfig: loConfig, + CNIConfig: cninet, + } + plugin.host = host return nil } @@ -118,6 +136,12 @@ func (plugin *cniNetworkPlugin) SetUpPod(namespace string, name string, id kubec return fmt.Errorf("CNI failed to retrieve network namespace path: %v", err) } + _, err = plugin.loNetwork.addToNetwork(name, namespace, id, netnsPath) + if err != nil { + glog.Errorf("Error while adding to cni lo network: %s", err) + return err + } + _, err = plugin.defaultNetwork.addToNetwork(name, namespace, id, netnsPath) if err != nil { glog.Errorf("Error while adding to cni network: %s", err) From 6aed2a0b1dfa50cc24f1729fe146307ea20bbb89 Mon Sep 17 00:00:00 2001 From: Euan Kemp Date: Tue, 19 Jul 2016 18:13:07 -0700 Subject: [PATCH 2/2] network/cni: Search `vendorDir` for lo plugin too Though frankly the vendor dir thing should probably be removed in a followup PR. --- pkg/kubelet/network/cni/cni.go | 39 ++++++++++++++++++----------- pkg/kubelet/network/cni/cni_test.go | 18 +++++++++++++ 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/pkg/kubelet/network/cni/cni.go b/pkg/kubelet/network/cni/cni.go index 4830aa79efe..0b6ba442493 100644 --- a/pkg/kubelet/network/cni/cni.go +++ b/pkg/kubelet/network/cni/cni.go @@ -49,7 +49,7 @@ type cniNetworkPlugin struct { type cniNetwork struct { name string NetworkConfig *libcni.NetworkConfig - CNIConfig *libcni.CNIConfig + CNIConfig libcni.CNI } func probeNetworkPluginsWithVendorCNIDirPrefix(pluginDir, vendorCNIDirPrefix string) []network.NetworkPlugin { @@ -60,6 +60,7 @@ func probeNetworkPluginsWithVendorCNIDirPrefix(pluginDir, vendorCNIDirPrefix str } return append(configList, &cniNetworkPlugin{ defaultNetwork: network, + loNetwork: getLoNetwork(vendorCNIDirPrefix), execer: utilexec.New(), }) } @@ -88,9 +89,9 @@ func getDefaultCNINetwork(pluginDir, vendorCNIDirPrefix string) (*cniNetwork, er continue } // Search for vendor-specific plugins as well as default plugins in the CNI codebase. - vendorCNIDir := fmt.Sprintf(VendorCNIDirTemplate, vendorCNIDirPrefix, conf.Network.Type) + vendorDir := vendorCNIDir(vendorCNIDirPrefix, conf.Network.Type) cninet := &libcni.CNIConfig{ - Path: []string{DefaultCNIDir, vendorCNIDir}, + Path: []string{DefaultCNIDir, vendorDir}, } network := &cniNetwork{name: conf.Network.Name, NetworkConfig: conf, CNIConfig: cninet} return network, nil @@ -98,30 +99,40 @@ func getDefaultCNINetwork(pluginDir, vendorCNIDirPrefix string) (*cniNetwork, er return nil, fmt.Errorf("No valid networks found in %s", pluginDir) } -func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string) error { - var err error - plugin.nsenterPath, err = plugin.execer.LookPath("nsenter") - if err != nil { - return err - } +func vendorCNIDir(prefix, pluginType string) string { + return fmt.Sprintf(VendorCNIDirTemplate, prefix, pluginType) +} +func getLoNetwork(vendorDirPrefix string) *cniNetwork { loConfig, err := libcni.ConfFromBytes([]byte(`{ "cniVersion": "0.1.0", "name": "cni-loopback", "type": "loopback" }`)) if err != nil { - return err + // The hardcoded config above should always be valid and unit tests will + // catch this + panic(err) } cninet := &libcni.CNIConfig{ - Path: []string{DefaultCNIDir}, + Path: []string{vendorCNIDir(vendorDirPrefix, loConfig.Network.Type), DefaultCNIDir}, } - plugin.loNetwork = &cniNetwork{ + loNetwork := &cniNetwork{ name: "lo", NetworkConfig: loConfig, CNIConfig: cninet, } + return loNetwork +} + +func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string) error { + var err error + plugin.nsenterPath, err = plugin.execer.LookPath("nsenter") + if err != nil { + return err + } + plugin.host = host return nil } @@ -184,7 +195,7 @@ func (network *cniNetwork) addToNetwork(podName string, podNamespace string, pod } netconf, cninet := network.NetworkConfig, network.CNIConfig - glog.V(4).Infof("About to run with conf.Network.Type=%v, c.Path=%v", netconf.Network.Type, cninet.Path) + glog.V(4).Infof("About to run with conf.Network.Type=%v", netconf.Network.Type) res, err := cninet.AddNetwork(netconf, rt) if err != nil { glog.Errorf("Error adding network: %v", err) @@ -202,7 +213,7 @@ func (network *cniNetwork) deleteFromNetwork(podName string, podNamespace string } netconf, cninet := network.NetworkConfig, network.CNIConfig - glog.V(4).Infof("About to run with conf.Network.Type=%v, c.Path=%v", netconf.Network.Type, cninet.Path) + glog.V(4).Infof("About to run with conf.Network.Type=%v", netconf.Network.Type) err = cninet.DelNetwork(netconf, rt) if err != nil { glog.Errorf("Error deleting network: %v", err) diff --git a/pkg/kubelet/network/cni/cni_test.go b/pkg/kubelet/network/cni/cni_test.go index 2022c7e8f6d..cce12deed95 100644 --- a/pkg/kubelet/network/cni/cni_test.go +++ b/pkg/kubelet/network/cni/cni_test.go @@ -23,6 +23,7 @@ import ( "fmt" "io/ioutil" "math/rand" + "net" "os" "path" "testing" @@ -30,11 +31,14 @@ import ( clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" + cnitypes "github.com/appc/cni/pkg/types" + "github.com/stretchr/testify/mock" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/componentconfig" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" "k8s.io/kubernetes/pkg/kubelet/network" + "k8s.io/kubernetes/pkg/kubelet/network/cni/testing" utilexec "k8s.io/kubernetes/pkg/util/exec" utiltesting "k8s.io/kubernetes/pkg/util/testing" ) @@ -160,6 +164,9 @@ func TestCNIPlugin(t *testing.T) { }, } + mockLoCNI := &mock_cni.MockCNI{} + // TODO mock for the test plugin too + tmpDir := utiltesting.MkTmpdirOrDie("cni-test") testNetworkConfigPath := path.Join(tmpDir, "plugins", "net", "cni") testVendorCNIDirPrefix := tmpDir @@ -189,6 +196,9 @@ func TestCNIPlugin(t *testing.T) { t.Fatalf("Not a CNI network plugin!") } cniPlugin.execer = fexec + cniPlugin.loNetwork.CNIConfig = mockLoCNI + + mockLoCNI.On("AddNetwork", cniPlugin.loNetwork.NetworkConfig, mock.AnythingOfType("*libcni.RuntimeConf")).Return(&cnitypes.Result{IP4: &cnitypes.IPConfig{IP: net.IPNet{IP: []byte{127, 0, 0, 1}}}}, nil) plug, err := network.InitNetworkPlugin(plugins, "cni", NewFakeHost(nil, pods), componentconfig.HairpinNone, "10.0.0.0/8") if err != nil { @@ -231,4 +241,12 @@ func TestCNIPlugin(t *testing.T) { if string(output) != expectedOutput { t.Errorf("Mismatch in expected output for setup hook. Expected '%s', got '%s'", expectedOutput, string(output)) } + + mockLoCNI.AssertExpectations(t) +} + +func TestLoNetNonNil(t *testing.T) { + if conf := getLoNetwork(""); conf == nil { + t.Error("Expected non-nil lo network") + } }