mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +00:00
Merge pull request #5678 from GoogleCloudPlatform/revert-5069-network_hooks
Revert "[WIP] southbound networking hooks in kubelet"
This commit is contained in:
commit
1dd4600eb6
@ -20,9 +20,6 @@ package app
|
|||||||
import (
|
import (
|
||||||
// Credential providers
|
// Credential providers
|
||||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/credentialprovider/gcp"
|
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/credentialprovider/gcp"
|
||||||
// Network plugins
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network/exec"
|
|
||||||
// Volume plugins
|
// Volume plugins
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/empty_dir"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/empty_dir"
|
||||||
@ -47,13 +44,3 @@ func ProbeVolumePlugins() []volume.Plugin {
|
|||||||
|
|
||||||
return allPlugins
|
return allPlugins
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProbeNetworkPlugins collects all compiled-in plugins
|
|
||||||
func ProbeNetworkPlugins() []network.NetworkPlugin {
|
|
||||||
allPlugins := []network.NetworkPlugin{}
|
|
||||||
|
|
||||||
// for each existing plugin, add to the list
|
|
||||||
allPlugins = append(allPlugins, exec.ProbeNetworkPlugins()...)
|
|
||||||
|
|
||||||
return allPlugins
|
|
||||||
}
|
|
||||||
|
@ -33,7 +33,6 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/cadvisor"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/cadvisor"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/config"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/config"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
@ -80,7 +79,6 @@ type KubeletServer struct {
|
|||||||
StreamingConnectionIdleTimeout time.Duration
|
StreamingConnectionIdleTimeout time.Duration
|
||||||
ImageGCHighThresholdPercent int
|
ImageGCHighThresholdPercent int
|
||||||
ImageGCLowThresholdPercent int
|
ImageGCLowThresholdPercent int
|
||||||
NetworkPluginName string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKubeletServer will create a new KubeletServer with default values.
|
// NewKubeletServer will create a new KubeletServer with default values.
|
||||||
@ -106,7 +104,6 @@ func NewKubeletServer() *KubeletServer {
|
|||||||
MasterServiceNamespace: api.NamespaceDefault,
|
MasterServiceNamespace: api.NamespaceDefault,
|
||||||
ImageGCHighThresholdPercent: 90,
|
ImageGCHighThresholdPercent: 90,
|
||||||
ImageGCLowThresholdPercent: 80,
|
ImageGCLowThresholdPercent: 80,
|
||||||
NetworkPluginName: "",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +142,6 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) {
|
|||||||
fs.DurationVar(&s.StreamingConnectionIdleTimeout, "streaming_connection_idle_timeout", 0, "Maximum time a streaming connection can be idle before the connection is automatically closed. Example: '5m'")
|
fs.DurationVar(&s.StreamingConnectionIdleTimeout, "streaming_connection_idle_timeout", 0, "Maximum time a streaming connection can be idle before the connection is automatically closed. Example: '5m'")
|
||||||
fs.IntVar(&s.ImageGCHighThresholdPercent, "image_gc_high_threshold", s.ImageGCHighThresholdPercent, "The percent of disk usage after which image garbage collection is always run. Default: 90%%")
|
fs.IntVar(&s.ImageGCHighThresholdPercent, "image_gc_high_threshold", s.ImageGCHighThresholdPercent, "The percent of disk usage after which image garbage collection is always run. Default: 90%%")
|
||||||
fs.IntVar(&s.ImageGCLowThresholdPercent, "image_gc_low_threshold", s.ImageGCLowThresholdPercent, "The percent of disk usage before which image garbage collection is never run. Lowest disk usage to garbage collect to. Default: 80%%")
|
fs.IntVar(&s.ImageGCLowThresholdPercent, "image_gc_low_threshold", s.ImageGCLowThresholdPercent, "The percent of disk usage before which image garbage collection is never run. Lowest disk usage to garbage collect to. Default: 80%%")
|
||||||
fs.StringVar(&s.NetworkPluginName, "network_plugin", s.NetworkPluginName, "<Warning: Alpha feature> The name of the network plugin to be invoked for various events in kubelet/pod lifecycle")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the specified KubeletServer. This should never exit.
|
// Run runs the specified KubeletServer. This should never exit.
|
||||||
@ -204,8 +200,6 @@ func (s *KubeletServer) Run(_ []string) error {
|
|||||||
KubeClient: client,
|
KubeClient: client,
|
||||||
MasterServiceNamespace: s.MasterServiceNamespace,
|
MasterServiceNamespace: s.MasterServiceNamespace,
|
||||||
VolumePlugins: ProbeVolumePlugins(),
|
VolumePlugins: ProbeVolumePlugins(),
|
||||||
NetworkPlugins: ProbeNetworkPlugins(),
|
|
||||||
NetworkPluginName: s.NetworkPluginName,
|
|
||||||
StreamingConnectionIdleTimeout: s.StreamingConnectionIdleTimeout,
|
StreamingConnectionIdleTimeout: s.StreamingConnectionIdleTimeout,
|
||||||
ImageGCPolicy: imageGCPolicy,
|
ImageGCPolicy: imageGCPolicy,
|
||||||
}
|
}
|
||||||
@ -403,8 +397,6 @@ type KubeletConfig struct {
|
|||||||
Runonce bool
|
Runonce bool
|
||||||
MasterServiceNamespace string
|
MasterServiceNamespace string
|
||||||
VolumePlugins []volume.Plugin
|
VolumePlugins []volume.Plugin
|
||||||
NetworkPlugins []network.NetworkPlugin
|
|
||||||
NetworkPluginName string
|
|
||||||
StreamingConnectionIdleTimeout time.Duration
|
StreamingConnectionIdleTimeout time.Duration
|
||||||
Recorder record.EventRecorder
|
Recorder record.EventRecorder
|
||||||
TLSOptions *kubelet.TLSOptions
|
TLSOptions *kubelet.TLSOptions
|
||||||
@ -445,8 +437,6 @@ func createAndInitKubelet(kc *KubeletConfig, pc *config.PodConfig) (*kubelet.Kub
|
|||||||
net.IP(kc.ClusterDNS),
|
net.IP(kc.ClusterDNS),
|
||||||
kc.MasterServiceNamespace,
|
kc.MasterServiceNamespace,
|
||||||
kc.VolumePlugins,
|
kc.VolumePlugins,
|
||||||
kc.NetworkPlugins,
|
|
||||||
kc.NetworkPluginName,
|
|
||||||
kc.StreamingConnectionIdleTimeout,
|
kc.StreamingConnectionIdleTimeout,
|
||||||
kc.Recorder,
|
kc.Recorder,
|
||||||
kc.CadvisorInterface,
|
kc.CadvisorInterface,
|
||||||
|
@ -42,7 +42,6 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/envvars"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/envvars"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/metrics"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/metrics"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/probe"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/probe"
|
||||||
@ -119,8 +118,6 @@ func NewMainKubelet(
|
|||||||
clusterDNS net.IP,
|
clusterDNS net.IP,
|
||||||
masterServiceNamespace string,
|
masterServiceNamespace string,
|
||||||
volumePlugins []volume.Plugin,
|
volumePlugins []volume.Plugin,
|
||||||
networkPlugins []network.NetworkPlugin,
|
|
||||||
networkPluginName string,
|
|
||||||
streamingConnectionIdleTimeout time.Duration,
|
streamingConnectionIdleTimeout time.Duration,
|
||||||
recorder record.EventRecorder,
|
recorder record.EventRecorder,
|
||||||
cadvisorInterface cadvisor.Interface,
|
cadvisorInterface cadvisor.Interface,
|
||||||
@ -223,12 +220,6 @@ func NewMainKubelet(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if plug, err := network.InitNetworkPlugin(networkPlugins, networkPluginName, &networkHost{klet}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
} else {
|
|
||||||
klet.networkPlugin = plug
|
|
||||||
}
|
|
||||||
|
|
||||||
klet.podStatuses = make(map[string]api.PodStatus)
|
klet.podStatuses = make(map[string]api.PodStatus)
|
||||||
|
|
||||||
klet.mirrorManager = newBasicMirrorManager(klet.kubeClient)
|
klet.mirrorManager = newBasicMirrorManager(klet.kubeClient)
|
||||||
@ -310,9 +301,6 @@ type Kubelet struct {
|
|||||||
// Volume plugins.
|
// Volume plugins.
|
||||||
volumePluginMgr volume.PluginMgr
|
volumePluginMgr volume.PluginMgr
|
||||||
|
|
||||||
// Network plugin
|
|
||||||
networkPlugin network.NetworkPlugin
|
|
||||||
|
|
||||||
// probe runner holder
|
// probe runner holder
|
||||||
prober probeHolder
|
prober probeHolder
|
||||||
// container readiness state holder
|
// container readiness state holder
|
||||||
@ -1369,11 +1357,6 @@ func (kl *Kubelet) syncPod(pod *api.Pod, hasMirrorPod bool, containersInPod dock
|
|||||||
}
|
}
|
||||||
glog.Infof("Creating pod infra container for %q", podFullName)
|
glog.Infof("Creating pod infra container for %q", podFullName)
|
||||||
podInfraContainerID, err = kl.createPodInfraContainer(pod)
|
podInfraContainerID, err = kl.createPodInfraContainer(pod)
|
||||||
|
|
||||||
// Call the networking plugin
|
|
||||||
if err == nil {
|
|
||||||
err = kl.networkPlugin.SetUpPod(pod.Namespace, pod.Name, podInfraContainerID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to create pod infra container: %v; Skipping pod %q", err, podFullName)
|
glog.Errorf("Failed to create pod infra container: %v; Skipping pod %q", err, podFullName)
|
||||||
return err
|
return err
|
||||||
@ -1565,14 +1548,6 @@ func (kl *Kubelet) SyncPods(allPods []api.Pod, podSyncTypes map[types.UID]metric
|
|||||||
pc := podContainer{podFullName, uid, containerName}
|
pc := podContainer{podFullName, uid, containerName}
|
||||||
_, ok := desiredContainers[pc]
|
_, ok := desiredContainers[pc]
|
||||||
if err != nil || !ok {
|
if err != nil || !ok {
|
||||||
// call the networking plugin for teardown
|
|
||||||
if containerName == dockertools.PodInfraContainerName {
|
|
||||||
name, namespace, _ := ParsePodFullName(podFullName)
|
|
||||||
err := kl.networkPlugin.TearDownPod(namespace, name, dockertools.DockerID(dockerContainers[ix].ID))
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Network plugin pre-delete method returned an error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glog.V(1).Infof("Killing unwanted container %+v", pc)
|
glog.V(1).Infof("Killing unwanted container %+v", pc)
|
||||||
err = kl.killContainer(dockerContainers[ix])
|
err = kl.killContainer(dockerContainers[ix])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -39,7 +39,6 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/cadvisor"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/cadvisor"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/metrics"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/metrics"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume"
|
||||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/host_path"
|
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/volume/host_path"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
|
||||||
@ -74,7 +73,6 @@ func newTestKubelet(t *testing.T) *TestKubelet {
|
|||||||
kubelet.kubeClient = fakeKubeClient
|
kubelet.kubeClient = fakeKubeClient
|
||||||
kubelet.dockerPuller = &dockertools.FakeDockerPuller{}
|
kubelet.dockerPuller = &dockertools.FakeDockerPuller{}
|
||||||
kubelet.hostname = "testnode"
|
kubelet.hostname = "testnode"
|
||||||
kubelet.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil))
|
|
||||||
if tempDir, err := ioutil.TempDir("/tmp", "kubelet_test."); err != nil {
|
if tempDir, err := ioutil.TempDir("/tmp", "kubelet_test."); err != nil {
|
||||||
t.Fatalf("can't make a temp rootdir: %v", err)
|
t.Fatalf("can't make a temp rootdir: %v", err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package exec scans and loads networking plugins that are installed
|
|
||||||
// under /usr/libexec/kubernetes/kubelet-plugins/net/exec/
|
|
||||||
// The layout convention for a plugin is:
|
|
||||||
// plugin-name/ (plugins have to be directories first)
|
|
||||||
// plugin-name/plugin-name (executable that will be called out, see Vendoring Note for more nuances)
|
|
||||||
// plugin-name/<other-files>
|
|
||||||
// where, 'executable' has the following requirements:
|
|
||||||
// - should have exec permissions
|
|
||||||
// - should give non-zero exit code on failure, and zero on sucess
|
|
||||||
// - the arguments will be <action> <pod_namespace> <pod_name> <docker_id_of_infra_container>
|
|
||||||
// whereupon, <action> will be one of:
|
|
||||||
// - init, called when the kubelet loads the plugin
|
|
||||||
// - setup, called after the infra container of a pod is
|
|
||||||
// created, but before other containers of the pod are created
|
|
||||||
// - teardown, called before the pod infra container is killed
|
|
||||||
// As the executables are called, the file-descriptors stdin, stdout, stderr
|
|
||||||
// remain open. The combined output of stdout/stderr is captured and logged.
|
|
||||||
//
|
|
||||||
// Note: If the pod infra container self-terminates (e.g. crashes or is killed),
|
|
||||||
// the entire pod lifecycle will be restarted, but teardown will not be called.
|
|
||||||
//
|
|
||||||
// Vendoring Note:
|
|
||||||
// Plugin Names can be vendored also. Use '~' as the escaped name for plugin directories.
|
|
||||||
// And expect command line argument to call vendored plugins as 'vendor/pluginName'
|
|
||||||
// e.g. pluginName = mysdn
|
|
||||||
// vendorname = mycompany
|
|
||||||
// then, plugin layout should be
|
|
||||||
// mycompany~mysdn/
|
|
||||||
// mycompany~mysdn/mysdn (this becomes the executable)
|
|
||||||
// mycompany~mysdn/<other-files>
|
|
||||||
// and, call the kubelet with '--network-plugin=mycompany/mysdn'
|
|
||||||
package exec
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network"
|
|
||||||
utilexec "github.com/GoogleCloudPlatform/kubernetes/pkg/util/exec"
|
|
||||||
"github.com/golang/glog"
|
|
||||||
)
|
|
||||||
|
|
||||||
type execNetworkPlugin struct {
|
|
||||||
execName string
|
|
||||||
execPath string
|
|
||||||
host network.Host
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
initCmd = "init"
|
|
||||||
setUpCmd = "setup"
|
|
||||||
tearDownCmd = "teardown"
|
|
||||||
execDir = "/usr/libexec/kubernetes/kubelet-plugins/net/exec/"
|
|
||||||
X_OK = 0x1
|
|
||||||
)
|
|
||||||
|
|
||||||
func ProbeNetworkPlugins() []network.NetworkPlugin {
|
|
||||||
return probeNetworkPluginsWithExecDir(execDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
func probeNetworkPluginsWithExecDir(pluginDir string) []network.NetworkPlugin {
|
|
||||||
execPlugins := []network.NetworkPlugin{}
|
|
||||||
|
|
||||||
files, _ := ioutil.ReadDir(pluginDir)
|
|
||||||
for _, f := range files {
|
|
||||||
// only directories are counted as plugins
|
|
||||||
// and pluginDir/dirname/dirname should be an executable
|
|
||||||
// unless dirname contains '~' for escaping namespace
|
|
||||||
// e.g. dirname = vendor~ipvlan
|
|
||||||
// then, executable will be pluginDir/dirname/ipvlan
|
|
||||||
if f.IsDir() {
|
|
||||||
execPath := path.Join(pluginDir, f.Name())
|
|
||||||
execPlugins = append(execPlugins, &execNetworkPlugin{execName: network.UnescapePluginName(f.Name()), execPath: execPath})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return execPlugins
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *execNetworkPlugin) Init(host network.Host) error {
|
|
||||||
err := plugin.validate()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
plugin.host = host
|
|
||||||
// call the init script
|
|
||||||
out, err := utilexec.New().Command(plugin.getExecutable(), initCmd).CombinedOutput()
|
|
||||||
glog.V(5).Infof("Init 'exec' network plugin output: %s, %v", string(out), err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *execNetworkPlugin) getExecutable() string {
|
|
||||||
parts := strings.Split(plugin.execName, "/")
|
|
||||||
execName := parts[len(parts)-1]
|
|
||||||
return path.Join(plugin.execPath, execName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *execNetworkPlugin) Name() string {
|
|
||||||
return plugin.execName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *execNetworkPlugin) validate() error {
|
|
||||||
if syscall.Access(plugin.getExecutable(), X_OK) != nil {
|
|
||||||
errStr := fmt.Sprintf("Invalid exec plugin. Executable '%s' does not have correct permissions.", plugin.execName)
|
|
||||||
return errors.New(errStr)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *execNetworkPlugin) SetUpPod(namespace string, name string, id dockertools.DockerID) error {
|
|
||||||
out, err := utilexec.New().Command(plugin.getExecutable(), setUpCmd, namespace, name, string(id)).CombinedOutput()
|
|
||||||
glog.V(5).Infof("SetUpPod 'exec' network plugin output: %s, %v", string(out), err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *execNetworkPlugin) TearDownPod(namespace string, name string, id dockertools.DockerID) error {
|
|
||||||
out, err := utilexec.New().Command(plugin.getExecutable(), tearDownCmd, namespace, name, string(id)).CombinedOutput()
|
|
||||||
glog.V(5).Infof("TearDownPod 'exec' network plugin output: %s, %v", string(out), err)
|
|
||||||
return err
|
|
||||||
}
|
|
@ -1,179 +0,0 @@
|
|||||||
// +build linux
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package exec
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"math/rand"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network"
|
|
||||||
)
|
|
||||||
|
|
||||||
// The temp dir where test plugins will be stored.
|
|
||||||
const testPluginPath = "/tmp/fake/plugins/net"
|
|
||||||
|
|
||||||
func installPluginUnderTest(t *testing.T, vendorName string, plugName string) {
|
|
||||||
vendoredName := plugName
|
|
||||||
if vendorName != "" {
|
|
||||||
vendoredName = fmt.Sprintf("%s~%s", vendorName, plugName)
|
|
||||||
}
|
|
||||||
pluginDir := path.Join(testPluginPath, vendoredName)
|
|
||||||
err := os.MkdirAll(pluginDir, 0777)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to create plugin: %v", err)
|
|
||||||
}
|
|
||||||
pluginExec := path.Join(pluginDir, plugName)
|
|
||||||
f, err := os.Create(pluginExec)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to install plugin")
|
|
||||||
}
|
|
||||||
err = f.Chmod(0777)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to set exec perms on plugin")
|
|
||||||
}
|
|
||||||
writeStr := fmt.Sprintf("#!/bin/bash\necho -n $@ &> %s", path.Join(pluginDir, plugName+".out"))
|
|
||||||
_, err = f.WriteString(writeStr)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to write plugin exec")
|
|
||||||
}
|
|
||||||
f.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func tearDownPlugin(plugName string) {
|
|
||||||
err := os.RemoveAll(testPluginPath)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error in cleaning up test: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSelectPlugin(t *testing.T) {
|
|
||||||
// install some random plugin under testPluginPath
|
|
||||||
pluginName := fmt.Sprintf("test%d", rand.Intn(1000))
|
|
||||||
defer tearDownPlugin(pluginName)
|
|
||||||
installPluginUnderTest(t, "", pluginName)
|
|
||||||
|
|
||||||
plug, err := network.InitNetworkPlugin(probeNetworkPluginsWithExecDir(testPluginPath), pluginName, network.NewFakeHost(nil))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to select the desired plugin: %v", err)
|
|
||||||
}
|
|
||||||
if plug.Name() != pluginName {
|
|
||||||
t.Errorf("Wrong plugin selected, chose %s, got %s\n", pluginName, plug.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSelectVendoredPlugin(t *testing.T) {
|
|
||||||
// install some random plugin under testPluginPath
|
|
||||||
pluginName := fmt.Sprintf("test%d", rand.Intn(1000))
|
|
||||||
defer tearDownPlugin(pluginName)
|
|
||||||
vendor := "mycompany"
|
|
||||||
installPluginUnderTest(t, vendor, pluginName)
|
|
||||||
|
|
||||||
vendoredPluginName := fmt.Sprintf("%s/%s", vendor, pluginName)
|
|
||||||
plug, err := network.InitNetworkPlugin(probeNetworkPluginsWithExecDir(testPluginPath), vendoredPluginName, network.NewFakeHost(nil))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to select the desired plugin: %v", err)
|
|
||||||
}
|
|
||||||
if plug.Name() != vendoredPluginName {
|
|
||||||
t.Errorf("Wrong plugin selected, chose %s, got %s\n", vendoredPluginName, plug.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSelectWrongPlugin(t *testing.T) {
|
|
||||||
// install some random plugin under testPluginPath
|
|
||||||
pluginName := fmt.Sprintf("test%d", rand.Intn(1000))
|
|
||||||
defer tearDownPlugin(pluginName)
|
|
||||||
installPluginUnderTest(t, "", pluginName)
|
|
||||||
|
|
||||||
wrongPlugin := "abcd"
|
|
||||||
plug, err := network.InitNetworkPlugin(probeNetworkPluginsWithExecDir(testPluginPath), wrongPlugin, network.NewFakeHost(nil))
|
|
||||||
if plug != nil || err == nil {
|
|
||||||
t.Errorf("Expected to see an error. Wrong plugin selected.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPluginValidation(t *testing.T) {
|
|
||||||
pluginName := fmt.Sprintf("test%d", rand.Intn(1000))
|
|
||||||
defer tearDownPlugin(pluginName)
|
|
||||||
installPluginUnderTest(t, "", pluginName)
|
|
||||||
|
|
||||||
// modify the perms of the pluginExecutable
|
|
||||||
f, err := os.Open(path.Join(testPluginPath, pluginName, pluginName))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Nil value expected.")
|
|
||||||
}
|
|
||||||
err = f.Chmod(0444)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to set perms on plugin exec")
|
|
||||||
}
|
|
||||||
f.Close()
|
|
||||||
|
|
||||||
_, err = network.InitNetworkPlugin(probeNetworkPluginsWithExecDir(testPluginPath), pluginName, network.NewFakeHost(nil))
|
|
||||||
if err == nil {
|
|
||||||
// we expected an error here because validation would have failed
|
|
||||||
t.Errorf("Expected non-nil value.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPluginSetupHook(t *testing.T) {
|
|
||||||
pluginName := fmt.Sprintf("test%d", rand.Intn(1000))
|
|
||||||
defer tearDownPlugin(pluginName)
|
|
||||||
installPluginUnderTest(t, "", pluginName)
|
|
||||||
|
|
||||||
plug, err := network.InitNetworkPlugin(probeNetworkPluginsWithExecDir(testPluginPath), pluginName, network.NewFakeHost(nil))
|
|
||||||
|
|
||||||
err = plug.SetUpPod("podNamespace", "podName", "dockerid2345")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Expected nil: %v", err)
|
|
||||||
}
|
|
||||||
// check output of setup hook
|
|
||||||
output, err := ioutil.ReadFile(path.Join(testPluginPath, pluginName, pluginName+".out"))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Expected nil")
|
|
||||||
}
|
|
||||||
expectedOutput := "setup podNamespace podName dockerid2345"
|
|
||||||
if string(output) != expectedOutput {
|
|
||||||
t.Errorf("Mismatch in expected output for setup hook. Expected '%s', got '%s'", expectedOutput, string(output))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPluginTearDownHook(t *testing.T) {
|
|
||||||
pluginName := fmt.Sprintf("test%d", rand.Intn(1000))
|
|
||||||
defer tearDownPlugin(pluginName)
|
|
||||||
installPluginUnderTest(t, "", pluginName)
|
|
||||||
|
|
||||||
plug, err := network.InitNetworkPlugin(probeNetworkPluginsWithExecDir(testPluginPath), pluginName, network.NewFakeHost(nil))
|
|
||||||
|
|
||||||
err = plug.TearDownPod("podNamespace", "podName", "dockerid2345")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Expected nil")
|
|
||||||
}
|
|
||||||
// check output of setup hook
|
|
||||||
output, err := ioutil.ReadFile(path.Join(testPluginPath, pluginName, pluginName+".out"))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Expected nil")
|
|
||||||
}
|
|
||||||
expectedOutput := "teardown podNamespace podName dockerid2345"
|
|
||||||
if string(output) != expectedOutput {
|
|
||||||
t.Errorf("Mismatch in expected output for teardown hook. Expected '%s', got '%s'", expectedOutput, string(output))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package network
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors"
|
|
||||||
"github.com/golang/glog"
|
|
||||||
)
|
|
||||||
|
|
||||||
const DefaultPluginName = "kubernetes.io/no-op"
|
|
||||||
|
|
||||||
// Plugin is an interface to network plugins for the kubelet
|
|
||||||
type NetworkPlugin interface {
|
|
||||||
// Init initializes the plugin. This will be called exactly once
|
|
||||||
// before any other methods are called.
|
|
||||||
Init(host Host) error
|
|
||||||
|
|
||||||
// Name returns the plugin's name. This will be used when searching
|
|
||||||
// for a plugin by name, e.g.
|
|
||||||
Name() string
|
|
||||||
|
|
||||||
// SetUpPod is the method called after the infra container of
|
|
||||||
// the pod has been created but before the other containers of the
|
|
||||||
// pod are launched.
|
|
||||||
SetUpPod(namespace string, name string, podInfraContainerID dockertools.DockerID) error
|
|
||||||
|
|
||||||
// TearDownPod is the method called before a pod's infra container will be deleted
|
|
||||||
TearDownPod(namespace string, name string, podInfraContainerID dockertools.DockerID) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Host is an interface that plugins can use to access the kubelet.
|
|
||||||
type Host interface {
|
|
||||||
// Get the pod structure by its name, namespace
|
|
||||||
GetPodByName(namespace, name string) (*api.Pod, bool)
|
|
||||||
|
|
||||||
// GetKubeClient returns a client interface
|
|
||||||
GetKubeClient() client.Interface
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitNetworkPlugin inits the plugin that matches networkPluginName. Plugins must have unique names.
|
|
||||||
func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host Host) (NetworkPlugin, error) {
|
|
||||||
if networkPluginName == "" {
|
|
||||||
// default to the no_op plugin
|
|
||||||
plug := &noopNetworkPlugin{}
|
|
||||||
return plug, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginMap := map[string]NetworkPlugin{}
|
|
||||||
|
|
||||||
allErrs := []error{}
|
|
||||||
for _, plugin := range plugins {
|
|
||||||
name := plugin.Name()
|
|
||||||
if !util.IsQualifiedName(name) {
|
|
||||||
allErrs = append(allErrs, fmt.Errorf("network plugin has invalid name: %#v", plugin))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, found := pluginMap[name]; found {
|
|
||||||
allErrs = append(allErrs, fmt.Errorf("network plugin %q was registered more than once", name))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pluginMap[name] = plugin
|
|
||||||
}
|
|
||||||
|
|
||||||
chosenPlugin := pluginMap[networkPluginName]
|
|
||||||
if chosenPlugin != nil {
|
|
||||||
err := chosenPlugin.Init(host)
|
|
||||||
if err != nil {
|
|
||||||
allErrs = append(allErrs, fmt.Errorf("Network plugin %q failed init: %v", networkPluginName, err))
|
|
||||||
} else {
|
|
||||||
glog.V(1).Infof("Loaded network plugin %q", networkPluginName)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
allErrs = append(allErrs, fmt.Errorf("Network plugin %q not found.", networkPluginName))
|
|
||||||
}
|
|
||||||
|
|
||||||
return chosenPlugin, errors.NewAggregate(allErrs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnescapePluginName(in string) string {
|
|
||||||
return strings.Replace(in, "~", "/", -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
type noopNetworkPlugin struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *noopNetworkPlugin) Init(host Host) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *noopNetworkPlugin) Name() string {
|
|
||||||
return DefaultPluginName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *noopNetworkPlugin) SetUpPod(namespace string, name string, id dockertools.DockerID) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *noopNetworkPlugin) TearDownPod(namespace string, name string, id dockertools.DockerID) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package network
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSelectDefaultPlugin(t *testing.T) {
|
|
||||||
all_plugins := []NetworkPlugin{}
|
|
||||||
plug, err := InitNetworkPlugin(all_plugins, "", NewFakeHost(nil))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Unexpected error in selecting default plugin: %v", err)
|
|
||||||
}
|
|
||||||
if plug == nil {
|
|
||||||
t.Fatalf("Failed to select the default plugin.")
|
|
||||||
}
|
|
||||||
if plug.Name() != DefaultPluginName {
|
|
||||||
t.Errorf("Failed to select the default plugin. Expected %s. Got %s", DefaultPluginName, plug.Name())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package network
|
|
||||||
|
|
||||||
// helper for testing plugins
|
|
||||||
// a fake host is created here that can be used by plugins for testing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
type fakeNetworkHost struct {
|
|
||||||
kubeClient client.Interface
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFakeHost(kubeClient client.Interface) *fakeNetworkHost {
|
|
||||||
host := &fakeNetworkHost{kubeClient: kubeClient}
|
|
||||||
return host
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fnh *fakeNetworkHost) GetPodByName(name, namespace string) (*api.Pod, bool) {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fnh *fakeNetworkHost) GetKubeClient() client.Interface {
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kubelet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This just exports required functions from kubelet proper, for use by network
|
|
||||||
// plugins.
|
|
||||||
type networkHost struct {
|
|
||||||
kubelet *Kubelet
|
|
||||||
}
|
|
||||||
|
|
||||||
func (nh *networkHost) GetPodByName(name, namespace string) (*api.Pod, bool) {
|
|
||||||
return nh.kubelet.GetPodByName(name, namespace)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (nh *networkHost) GetKubeClient() client.Interface {
|
|
||||||
return nh.kubelet.kubeClient
|
|
||||||
}
|
|
@ -26,7 +26,6 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/record"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/record"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/cadvisor"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/cadvisor"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/network"
|
|
||||||
docker "github.com/fsouza/go-dockerclient"
|
docker "github.com/fsouza/go-dockerclient"
|
||||||
cadvisorApi "github.com/google/cadvisor/info/v1"
|
cadvisorApi "github.com/google/cadvisor/info/v1"
|
||||||
)
|
)
|
||||||
@ -79,7 +78,6 @@ func TestRunOnce(t *testing.T) {
|
|||||||
cadvisor: cadvisor,
|
cadvisor: cadvisor,
|
||||||
}
|
}
|
||||||
|
|
||||||
kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil))
|
|
||||||
if err := kb.setupDataDirs(); err != nil {
|
if err := kb.setupDataDirs(); err != nil {
|
||||||
t.Errorf("Failed to init data dirs: %v", err)
|
t.Errorf("Failed to init data dirs: %v", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user