diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index e52010af5817..b014cbf8d7e0 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -864,7 +864,7 @@ func RunKubelet(kubeFlags *options.KubeletFlags, kubeCfg *componentconfig.Kubele if kubeDeps.OSInterface == nil { kubeDeps.OSInterface = kubecontainer.RealOS{} } - k, err := builder(kubeCfg, kubeDeps, &kubeFlags.ContainerRuntimeOptions, standaloneMode, kubeFlags.HostnameOverride, kubeFlags.NodeIP, kubeFlags.ProviderID) + k, err := builder(kubeCfg, kubeDeps, &kubeFlags.ContainerRuntimeOptions, standaloneMode, kubeFlags.HostnameOverride, kubeFlags.NodeIP, kubeFlags.ProviderID, kubeFlags.KubeConfig.Value()) if err != nil { return fmt.Errorf("failed to create kubelet: %v", err) } @@ -908,11 +908,11 @@ func startKubelet(k kubelet.KubeletBootstrap, podCfg *config.PodConfig, kubeCfg } } -func CreateAndInitKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *kubelet.KubeletDeps, crOptions *options.ContainerRuntimeOptions, standaloneMode bool, hostnameOverride, nodeIP, providerID string) (k kubelet.KubeletBootstrap, err error) { +func CreateAndInitKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *kubelet.KubeletDeps, crOptions *options.ContainerRuntimeOptions, standaloneMode bool, hostnameOverride, nodeIP, providerID, kubeConfig string) (k kubelet.KubeletBootstrap, err error) { // TODO: block until all sources have delivered at least one update to the channel, or break the sync loop // up into "per source" synchronizations - k, err = kubelet.NewMainKubelet(kubeCfg, kubeDeps, crOptions, standaloneMode, hostnameOverride, nodeIP, providerID) + k, err = kubelet.NewMainKubelet(kubeCfg, kubeDeps, crOptions, standaloneMode, hostnameOverride, nodeIP, providerID, kubeConfig) if err != nil { return nil, err } diff --git a/pkg/kubelet/dockershim/docker_service.go b/pkg/kubelet/dockershim/docker_service.go index 05b73394aa5d..c721cd85e7f5 100644 --- a/pkg/kubelet/dockershim/docker_service.go +++ b/pkg/kubelet/dockershim/docker_service.go @@ -106,6 +106,9 @@ type NetworkPluginSettings struct { // MTU is the desired MTU for network devices created by the plugin. MTU int + // Path to a kubeconfig file which can be used to create a kubernetes client + KubeConfigPath string + // RuntimeHost is an interface that serves as a trap-door from plugin back // into the kubelet. // TODO: This shouldn't be required, remove once we move host ports into CNI @@ -200,7 +203,7 @@ func NewDockerService(client libdocker.Interface, seccompProfileRoot string, pod &namespaceGetter{ds}, &portMappingGetter{ds}, } - plug, err := network.InitNetworkPlugin(cniPlugins, pluginSettings.PluginName, netHost, pluginSettings.HairpinMode, pluginSettings.NonMasqueradeCIDR, pluginSettings.MTU) + plug, err := network.InitNetworkPlugin(cniPlugins, pluginSettings.PluginName, netHost, pluginSettings.HairpinMode, pluginSettings.NonMasqueradeCIDR, pluginSettings.MTU, pluginSettings.KubeConfigPath) if err != nil { return nil, fmt.Errorf("didn't find compatible CNI plugin with given settings %+v: %v", pluginSettings, err) } diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index b2a5bdc08e4a..1e1b976bf024 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -190,7 +190,7 @@ type KubeletBootstrap interface { } // create and initialize a Kubelet instance -type KubeletBuilder func(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *KubeletDeps, crOptions *options.ContainerRuntimeOptions, standaloneMode bool, hostnameOverride, nodeIP, providerID string) (KubeletBootstrap, error) +type KubeletBuilder func(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *KubeletDeps, crOptions *options.ContainerRuntimeOptions, standaloneMode bool, hostnameOverride, nodeIP, providerID, kubeConfig string) (KubeletBootstrap, error) // KubeletDeps is a bin for things we might consider "injected dependencies" -- objects constructed // at runtime that are necessary for running the Kubelet. This is a temporary solution for grouping @@ -285,7 +285,7 @@ func getRuntimeAndImageServices(config *componentconfig.KubeletConfiguration) (i // NewMainKubelet instantiates a new Kubelet object along with all the required internal modules. // No initialization of Kubelet and its modules should happen here. -func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *KubeletDeps, crOptions *options.ContainerRuntimeOptions, standaloneMode bool, hostnameOverride, nodeIP, providerID string) (*Kubelet, error) { +func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *KubeletDeps, crOptions *options.ContainerRuntimeOptions, standaloneMode bool, hostnameOverride, nodeIP, providerID, kubeConfig string) (*Kubelet, error) { if kubeCfg.RootDirectory == "" { return nil, fmt.Errorf("invalid root directory %q", kubeCfg.RootDirectory) } @@ -514,7 +514,7 @@ func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *Kub glog.Warningf("Failed to close iptables lock file: %v", err) } - if plug, err := network.InitNetworkPlugin(kubeDeps.NetworkPlugins, crOptions.NetworkPluginName, &criNetworkHost{&networkHost{klet}, &network.NoopPortMappingGetter{}}, hairpinMode, kubeCfg.NonMasqueradeCIDR, int(crOptions.NetworkPluginMTU)); err != nil { + if plug, err := network.InitNetworkPlugin(kubeDeps.NetworkPlugins, crOptions.NetworkPluginName, &criNetworkHost{&networkHost{klet}, &network.NoopPortMappingGetter{}}, hairpinMode, kubeCfg.NonMasqueradeCIDR, int(crOptions.NetworkPluginMTU), kubeConfig); err != nil { return nil, err } else { klet.networkPlugin = plug @@ -552,6 +552,7 @@ func NewMainKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *Kub PluginConfDir: crOptions.CNIConfDir, PluginBinDir: binDir, MTU: int(crOptions.NetworkPluginMTU), + KubeConfigPath: kubeConfig, } // Remote runtime shim just cannot talk back to kubelet, so it doesn't diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 15b9bf614400..c65c9954df16 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -160,7 +160,7 @@ func newTestKubeletWithImageList( kubelet.nodeName = types.NodeName(testKubeletHostname) kubelet.runtimeState = newRuntimeState(maxWaitForContainerRuntime) kubelet.runtimeState.setNetworkState(nil) - kubelet.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", nettest.NewFakeHost(nil), componentconfig.HairpinNone, "", 1440) + kubelet.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", nettest.NewFakeHost(nil), componentconfig.HairpinNone, "", 1440, "") if tempDir, err := ioutil.TempDir("/tmp", "kubelet_test."); err != nil { t.Fatalf("can't make a temp rootdir: %v", err) } else { diff --git a/pkg/kubelet/network/cni/cni.go b/pkg/kubelet/network/cni/cni.go index 1e9c91b818b4..f50d569f4ed0 100644 --- a/pkg/kubelet/network/cni/cni.go +++ b/pkg/kubelet/network/cni/cni.go @@ -30,6 +30,9 @@ import ( kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/network" utilexec "k8s.io/kubernetes/pkg/util/exec" + + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" ) const ( @@ -53,6 +56,8 @@ type cniNetworkPlugin struct { pluginDir string binDir string vendorCNIDirPrefix string + + kubeClient *kubernetes.Clientset } type cniNetwork struct { @@ -83,8 +88,6 @@ func probeNetworkPluginsWithVendorCNIDirPrefix(pluginDir, binDir, vendorCNIDirPr vendorCNIDirPrefix: vendorCNIDirPrefix, } - // sync NetworkConfig in best effort during probing. - plugin.syncNetworkConfig() return []network.NetworkPlugin{plugin} } @@ -171,8 +174,20 @@ func getLoNetwork(binDir, vendorDirPrefix string) *cniNetwork { return loNetwork } -func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { +func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int, kubeConfig string) error { var err error + + if kubeConfig != "" { + config, err := clientcmd.BuildConfigFromFlags("", kubeConfig) + if err != nil { + return fmt.Errorf("unable to read kubeconfig %q: %v", kubeConfig, err) + } + plugin.kubeClient, err = kubernetes.NewForConfig(config) + if err != nil { + return fmt.Errorf("unable to create kubernetes client with config %q: %v", kubeConfig, err) + } + } + plugin.nsenterPath, err = plugin.execer.LookPath("nsenter") if err != nil { return err diff --git a/pkg/kubelet/network/cni/cni_test.go b/pkg/kubelet/network/cni/cni_test.go index 8b3b078718bb..e16d90bc12a3 100644 --- a/pkg/kubelet/network/cni/cni_test.go +++ b/pkg/kubelet/network/cni/cni_test.go @@ -227,7 +227,7 @@ func TestCNIPlugin(t *testing.T) { } fakeHost := NewFakeHost(nil, pods, ports) - plug, err := network.InitNetworkPlugin(plugins, "cni", fakeHost, componentconfig.HairpinNone, "10.0.0.0/8", network.UseDefaultMTU) + plug, err := network.InitNetworkPlugin(plugins, "cni", fakeHost, componentconfig.HairpinNone, "10.0.0.0/8", network.UseDefaultMTU, "") if err != nil { t.Fatalf("Failed to select the desired plugin: %v", err) } diff --git a/pkg/kubelet/network/kubenet/kubenet_linux.go b/pkg/kubelet/network/kubenet/kubenet_linux.go index 81aa2373b840..8d6e40836c4f 100644 --- a/pkg/kubelet/network/kubenet/kubenet_linux.go +++ b/pkg/kubelet/network/kubenet/kubenet_linux.go @@ -124,7 +124,7 @@ func NewPlugin(networkPluginDir string) network.NetworkPlugin { } } -func (plugin *kubenetNetworkPlugin) Init(host network.Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { +func (plugin *kubenetNetworkPlugin) Init(host network.Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int, kubeConfig string) error { plugin.host = host plugin.hairpinMode = hairpinMode plugin.nonMasqueradeCIDR = nonMasqueradeCIDR diff --git a/pkg/kubelet/network/plugins.go b/pkg/kubelet/network/plugins.go index ca75c95a336a..6d352b67162c 100644 --- a/pkg/kubelet/network/plugins.go +++ b/pkg/kubelet/network/plugins.go @@ -47,7 +47,7 @@ const NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR = "pod-cidr" type NetworkPlugin interface { // Init initializes the plugin. This will be called exactly once // before any other methods are called. - Init(host Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error + Init(host Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int, kubeConfig string) error // Called on various events like: // NET_PLUGIN_EVENT_POD_CIDR_CHANGE @@ -154,11 +154,11 @@ type PortMappingGetter interface { } // InitNetworkPlugin inits the plugin that matches networkPluginName. Plugins must have unique names. -func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) (NetworkPlugin, error) { +func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int, kubeConfig string) (NetworkPlugin, error) { if networkPluginName == "" { // default to the no_op plugin plug := &NoopNetworkPlugin{} - if err := plug.Init(host, hairpinMode, nonMasqueradeCIDR, mtu); err != nil { + if err := plug.Init(host, hairpinMode, nonMasqueradeCIDR, mtu, kubeConfig); err != nil { return nil, err } return plug, nil @@ -183,7 +183,7 @@ func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host H chosenPlugin := pluginMap[networkPluginName] if chosenPlugin != nil { - err := chosenPlugin.Init(host, hairpinMode, nonMasqueradeCIDR, mtu) + err := chosenPlugin.Init(host, hairpinMode, nonMasqueradeCIDR, mtu, kubeConfig) if err != nil { allErrs = append(allErrs, fmt.Errorf("Network plugin %q failed init: %v", networkPluginName, err)) } else { @@ -205,7 +205,7 @@ type NoopNetworkPlugin struct { const sysctlBridgeCallIPTables = "net/bridge/bridge-nf-call-iptables" -func (plugin *NoopNetworkPlugin) Init(host Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { +func (plugin *NoopNetworkPlugin) Init(host Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int, kubeConfig string) error { // Set bridge-nf-call-iptables=1 to maintain compatibility with older // kubernetes versions to ensure the iptables-based kube proxy functions // correctly. Other plugins are responsible for setting this correctly diff --git a/pkg/kubelet/network/testing/mock_network_plugin.go b/pkg/kubelet/network/testing/mock_network_plugin.go index 9015c360a39f..84d8ed3a4658 100644 --- a/pkg/kubelet/network/testing/mock_network_plugin.go +++ b/pkg/kubelet/network/testing/mock_network_plugin.go @@ -82,7 +82,7 @@ func (_mr *_MockNetworkPluginRecorder) GetPodNetworkStatus(arg0, arg1, arg2 inte return _mr.mock.ctrl.RecordCall(_mr.mock, "GetPodNetworkStatus", arg0, arg1, arg2) } -func (_m *MockNetworkPlugin) Init(_param0 network.Host, _param1 componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { +func (_m *MockNetworkPlugin) Init(_param0 network.Host, _param1 componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int, kubeConfig string) error { ret := _m.ctrl.Call(_m, "Init", _param0, _param1) ret0, _ := ret[0].(error) return ret0 diff --git a/pkg/kubelet/network/testing/plugins_test.go b/pkg/kubelet/network/testing/plugins_test.go index fd12c0ef42db..1af2118492bf 100644 --- a/pkg/kubelet/network/testing/plugins_test.go +++ b/pkg/kubelet/network/testing/plugins_test.go @@ -32,7 +32,7 @@ import ( func TestSelectDefaultPlugin(t *testing.T) { all_plugins := []network.NetworkPlugin{} - plug, err := network.InitNetworkPlugin(all_plugins, "", NewFakeHost(nil), componentconfig.HairpinNone, "10.0.0.0/8", network.UseDefaultMTU) + plug, err := network.InitNetworkPlugin(all_plugins, "", NewFakeHost(nil), componentconfig.HairpinNone, "10.0.0.0/8", network.UseDefaultMTU, "") if err != nil { t.Fatalf("Unexpected error in selecting default plugin: %v", err) } @@ -113,7 +113,7 @@ func newHookableFakeNetworkPlugin(setupHook hookableFakeNetworkPluginSetupHook) } } -func (p *hookableFakeNetworkPlugin) Init(host network.Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error { +func (p *hookableFakeNetworkPlugin) Init(host network.Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int, kubeConfig string) error { return nil } diff --git a/pkg/kubelet/runonce_test.go b/pkg/kubelet/runonce_test.go index 0dc79cdad8af..dbbeae2e25cd 100644 --- a/pkg/kubelet/runonce_test.go +++ b/pkg/kubelet/runonce_test.go @@ -113,7 +113,7 @@ func TestRunOnce(t *testing.T) { false, /* experimentalCheckNodeCapabilitiesBeforeMount */ false /* keepTerminatedPodVolumes */) - kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", nettest.NewFakeHost(nil), componentconfig.HairpinNone, "", network.UseDefaultMTU) + kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", nettest.NewFakeHost(nil), componentconfig.HairpinNone, "", network.UseDefaultMTU, "") // TODO: Factor out "StatsProvider" from Kubelet so we don't have a cyclic dependency volumeStatsAggPeriod := time.Second * 10 kb.resourceAnalyzer = stats.NewResourceAnalyzer(kb, volumeStatsAggPeriod, kb.containerRuntime)