kubelet/network: return but tolerate errors returned from GetNetNS()

Runtimes should never return "" and nil errors, since network plugin
drivers need to treat netns differently in different cases.  So return
errors when we can't get the netns, and fix up the plugins to do the
right thing.

Namely, we don't need a NetNS on pod network teardown.  We do need
a netns for pod Status checks and for network setup.
This commit is contained in:
Dan Williams 2017-03-30 17:33:58 -05:00
parent 72710b7542
commit 45dffed8ac
5 changed files with 16 additions and 8 deletions

View File

@ -315,7 +315,7 @@ func (ds *dockerService) GetNetNS(podSandboxID string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
return getNetworkNamespace(r), nil return getNetworkNamespace(r)
} }
// GetPodPortMappings returns the port mappings of the given podSandbox ID. // GetPodPortMappings returns the port mappings of the given podSandbox ID.

View File

@ -266,8 +266,12 @@ func getApparmorSecurityOpts(sc *runtimeapi.LinuxContainerSecurityContext, separ
return fmtOpts, nil return fmtOpts, nil
} }
func getNetworkNamespace(c *dockertypes.ContainerJSON) string { func getNetworkNamespace(c *dockertypes.ContainerJSON) (string, error) {
return fmt.Sprintf(dockerNetNSFmt, c.State.Pid) if c.State.Pid == 0 {
// Docker reports pid 0 for an exited container.
return "", fmt.Errorf("Cannot find network namespace for the terminated container %q", c.ID)
}
return fmt.Sprintf(dockerNetNSFmt, c.State.Pid), nil
} }
// dockerFilter wraps around dockerfilters.Args and provides methods to modify // dockerFilter wraps around dockerfilters.Args and provides methods to modify

View File

@ -251,9 +251,11 @@ func (plugin *cniNetworkPlugin) TearDownPod(namespace string, name string, id ku
if err := plugin.checkInitialized(); err != nil { if err := plugin.checkInitialized(); err != nil {
return err return err
} }
// Lack of namespace should not be fatal on teardown
netnsPath, err := plugin.host.GetNetNS(id.ID) netnsPath, err := plugin.host.GetNetNS(id.ID)
if err != nil { if err != nil {
return fmt.Errorf("CNI failed to retrieve network namespace path: %v", err) glog.Warningf("CNI failed to retrieve network namespace path: %v", err)
} }
return plugin.deleteFromNetwork(plugin.getDefaultNetwork(), name, namespace, id, netnsPath) return plugin.deleteFromNetwork(plugin.getDefaultNetwork(), name, namespace, id, netnsPath)

View File

@ -741,9 +741,9 @@ func podIsExited(p *kubecontainer.Pod) bool {
return true return true
} }
func (plugin *kubenetNetworkPlugin) buildCNIRuntimeConf(ifName string, id kubecontainer.ContainerID) (*libcni.RuntimeConf, error) { func (plugin *kubenetNetworkPlugin) buildCNIRuntimeConf(ifName string, id kubecontainer.ContainerID, needNetNs bool) (*libcni.RuntimeConf, error) {
netnsPath, err := plugin.host.GetNetNS(id.ID) netnsPath, err := plugin.host.GetNetNS(id.ID)
if err != nil { if needNetNs && err != nil {
glog.Errorf("Kubenet failed to retrieve network namespace path: %v", err) glog.Errorf("Kubenet failed to retrieve network namespace path: %v", err)
} }
@ -755,7 +755,7 @@ func (plugin *kubenetNetworkPlugin) buildCNIRuntimeConf(ifName string, id kubeco
} }
func (plugin *kubenetNetworkPlugin) addContainerToNetwork(config *libcni.NetworkConfig, ifName, namespace, name string, id kubecontainer.ContainerID) (cnitypes.Result, error) { func (plugin *kubenetNetworkPlugin) addContainerToNetwork(config *libcni.NetworkConfig, ifName, namespace, name string, id kubecontainer.ContainerID) (cnitypes.Result, error) {
rt, err := plugin.buildCNIRuntimeConf(ifName, id) rt, err := plugin.buildCNIRuntimeConf(ifName, id, true)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error building CNI config: %v", err) return nil, fmt.Errorf("Error building CNI config: %v", err)
} }
@ -769,7 +769,7 @@ func (plugin *kubenetNetworkPlugin) addContainerToNetwork(config *libcni.Network
} }
func (plugin *kubenetNetworkPlugin) delContainerFromNetwork(config *libcni.NetworkConfig, ifName, namespace, name string, id kubecontainer.ContainerID) error { func (plugin *kubenetNetworkPlugin) delContainerFromNetwork(config *libcni.NetworkConfig, ifName, namespace, name string, id kubecontainer.ContainerID) error {
rt, err := plugin.buildCNIRuntimeConf(ifName, id) rt, err := plugin.buildCNIRuntimeConf(ifName, id, false)
if err != nil { if err != nil {
return fmt.Errorf("Error building CNI config: %v", err) return fmt.Errorf("Error building CNI config: %v", err)
} }

View File

@ -144,6 +144,8 @@ type Host interface {
// CNI plugin wrappers like kubenet. // CNI plugin wrappers like kubenet.
type NamespaceGetter interface { type NamespaceGetter interface {
// GetNetNS returns network namespace information for the given containerID. // GetNetNS returns network namespace information for the given containerID.
// Runtimes should *never* return an empty namespace and nil error for
// a container; if error is nil then the namespace string must be valid.
GetNetNS(containerID string) (string, error) GetNetNS(containerID string) (string, error)
} }