Merge pull request #7814 from dcantah/hostnet-helper
CRI: Add host networking helper
This commit is contained in:
		| @@ -21,6 +21,7 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"path" | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | 	goruntime "runtime" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| @@ -583,3 +584,22 @@ func (c *criService) getContainerStatuses(ctx context.Context, podSandboxID stri | |||||||
| 	} | 	} | ||||||
| 	return containerStatuses, nil | 	return containerStatuses, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // hostNetwork handles checking if host networking was requested. | ||||||
|  | func hostNetwork(config *runtime.PodSandboxConfig) bool { | ||||||
|  | 	var hostNet bool | ||||||
|  | 	switch goruntime.GOOS { | ||||||
|  | 	case "windows": | ||||||
|  | 		// Windows HostProcess pods can only run on the host network | ||||||
|  | 		hostNet = config.GetWindows().GetSecurityContext().GetHostProcess() | ||||||
|  | 	case "darwin": | ||||||
|  | 		// No CNI on Darwin yet. | ||||||
|  | 		hostNet = true | ||||||
|  | 	default: | ||||||
|  | 		// Even on other platforms, the logic containerd uses is to check if NamespaceMode == NODE. | ||||||
|  | 		// So this handles Linux, as well as any other platforms not governed by the cases above | ||||||
|  | 		// that have special quirks. | ||||||
|  | 		hostNet = config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE | ||||||
|  | 	} | ||||||
|  | 	return hostNet | ||||||
|  | } | ||||||
|   | |||||||
| @@ -21,7 +21,6 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	goruntime "runtime" |  | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| @@ -485,15 +484,8 @@ func (c *criService) loadSandbox(ctx context.Context, cntr containerd.Container) | |||||||
| } | } | ||||||
|  |  | ||||||
| func getNetNS(meta *sandboxstore.Metadata) *netns.NetNS { | func getNetNS(meta *sandboxstore.Metadata) *netns.NetNS { | ||||||
| 	if goruntime.GOOS != "windows" && | 	// Don't need to load netns for host network sandbox. | ||||||
| 		meta.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE { | 	if hostNetwork(meta.Config) { | ||||||
| 		// Don't need to load netns for host network sandbox. |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	if goruntime.GOOS == "windows" && meta.Config.GetWindows().GetSecurityContext().GetHostProcess() { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	if goruntime.GOOS == "darwin" { |  | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	return netns.LoadNetNS(meta.NetNSPath) | 	return netns.LoadNetNS(meta.NetNSPath) | ||||||
|   | |||||||
| @@ -25,8 +25,6 @@ import ( | |||||||
|  |  | ||||||
| 	"github.com/containerd/containerd/log" | 	"github.com/containerd/containerd/log" | ||||||
| 	"github.com/containernetworking/plugins/pkg/ns" | 	"github.com/containernetworking/plugins/pkg/ns" | ||||||
|  |  | ||||||
| 	runtime "k8s.io/cri-api/pkg/apis/runtime/v1" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // portForward uses netns to enter the sandbox namespace, and forwards a stream inside the | // portForward uses netns to enter the sandbox namespace, and forwards a stream inside the | ||||||
| @@ -37,12 +35,12 @@ func (c *criService) portForward(ctx context.Context, id string, port int32, str | |||||||
| 		return fmt.Errorf("failed to find sandbox %q in store: %w", id, err) | 		return fmt.Errorf("failed to find sandbox %q in store: %w", id, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var netNSDo func(func(ns.NetNS) error) error | 	var ( | ||||||
| 	// netNSPath is the network namespace path for logging. | 		netNSDo func(func(ns.NetNS) error) error | ||||||
| 	var netNSPath string | 		// netNSPath is the network namespace path for logging. | ||||||
| 	securityContext := s.Config.GetLinux().GetSecurityContext() | 		netNSPath string | ||||||
| 	hostNet := securityContext.GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE | 	) | ||||||
| 	if !hostNet { | 	if !hostNetwork(s.Config) { | ||||||
| 		if closed, err := s.NetNS.Closed(); err != nil { | 		if closed, err := s.NetNS.Closed(); err != nil { | ||||||
| 			return fmt.Errorf("failed to check netwok namespace closed for sandbox %q: %w", id, err) | 			return fmt.Errorf("failed to check netwok namespace closed for sandbox %q: %w", id, err) | ||||||
| 		} else if closed { | 		} else if closed { | ||||||
|   | |||||||
| @@ -23,7 +23,6 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"math" | 	"math" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	goruntime "runtime" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| @@ -146,24 +145,8 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox | |||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| 	podNetwork := true | 	// Setup the network namespace if host networking wasn't requested. | ||||||
| 	if goruntime.GOOS != "windows" && | 	if !hostNetwork(config) { | ||||||
| 		config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE { |  | ||||||
| 		// Pod network is not needed on linux with host network. |  | ||||||
| 		podNetwork = false |  | ||||||
| 	} |  | ||||||
| 	if goruntime.GOOS == "windows" && |  | ||||||
| 		config.GetWindows().GetSecurityContext().GetHostProcess() { |  | ||||||
| 		// Windows HostProcess pods can only run on the host network |  | ||||||
| 		podNetwork = false |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// No CNI on darwin yet |  | ||||||
| 	if goruntime.GOOS == "darwin" { |  | ||||||
| 		podNetwork = false |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if podNetwork { |  | ||||||
| 		netStart := time.Now() | 		netStart := time.Now() | ||||||
| 		// If it is not in host network namespace then create a namespace and set the sandbox | 		// If it is not in host network namespace then create a namespace and set the sandbox | ||||||
| 		// handle. NetNSPath in sandbox metadata and NetNS is non empty only for non host network | 		// handle. NetNSPath in sandbox metadata and NetNS is non empty only for non host network | ||||||
|   | |||||||
| @@ -19,7 +19,6 @@ package sbserver | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	goruntime "runtime" |  | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox" | 	sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox" | ||||||
| @@ -67,18 +66,9 @@ func (c *criService) PodSandboxStatus(ctx context.Context, r *runtime.PodSandbox | |||||||
| func (c *criService) getIPs(sandbox sandboxstore.Sandbox) (string, []string, error) { | func (c *criService) getIPs(sandbox sandboxstore.Sandbox) (string, []string, error) { | ||||||
| 	config := sandbox.Config | 	config := sandbox.Config | ||||||
|  |  | ||||||
| 	if goruntime.GOOS != "windows" && | 	// For sandboxes using the node network we are not | ||||||
| 		config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE { | 	// responsible for reporting the IP. | ||||||
| 		// For sandboxes using the node network we are not | 	if hostNetwork(config) { | ||||||
| 		// responsible for reporting the IP. |  | ||||||
| 		return "", nil, nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if goruntime.GOOS == "windows" && config.GetWindows().GetSecurityContext().GetHostProcess() { |  | ||||||
| 		return "", nil, nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if goruntime.GOOS == "darwin" { |  | ||||||
| 		return "", nil, nil | 		return "", nil, nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"path" | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | 	goruntime "runtime" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| @@ -582,3 +583,22 @@ func (c *criService) getContainerStatuses(ctx context.Context, podSandboxID stri | |||||||
| 	} | 	} | ||||||
| 	return containerStatuses, nil | 	return containerStatuses, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // hostNetwork handles checking if host networking was requested. | ||||||
|  | func hostNetwork(config *runtime.PodSandboxConfig) bool { | ||||||
|  | 	var hostNet bool | ||||||
|  | 	switch goruntime.GOOS { | ||||||
|  | 	case "windows": | ||||||
|  | 		// Windows HostProcess pods can only run on the host network | ||||||
|  | 		hostNet = config.GetWindows().GetSecurityContext().GetHostProcess() | ||||||
|  | 	case "darwin": | ||||||
|  | 		// No CNI on Darwin yet. | ||||||
|  | 		hostNet = true | ||||||
|  | 	default: | ||||||
|  | 		// Even on other platforms, the logic containerd uses is to check if NamespaceMode == NODE. | ||||||
|  | 		// So this handles Linux, as well as any other platforms not governed by the cases above | ||||||
|  | 		// that have special quirks. | ||||||
|  | 		hostNet = config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE | ||||||
|  | 	} | ||||||
|  | 	return hostNet | ||||||
|  | } | ||||||
|   | |||||||
| @@ -21,7 +21,6 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	goruntime "runtime" |  | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| @@ -426,15 +425,11 @@ func (c *criService) loadSandbox(ctx context.Context, cntr containerd.Container) | |||||||
| 	sandbox = sandboxstore.NewSandbox(*meta, s) | 	sandbox = sandboxstore.NewSandbox(*meta, s) | ||||||
| 	sandbox.Container = cntr | 	sandbox.Container = cntr | ||||||
|  |  | ||||||
|  | 	// Don't need to load netns for host network sandbox. | ||||||
|  | 	if hostNetwork(meta.Config) { | ||||||
|  | 		return sandbox, nil | ||||||
|  | 	} | ||||||
| 	// Load network namespace. | 	// Load network namespace. | ||||||
| 	if goruntime.GOOS != "windows" && |  | ||||||
| 		meta.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE { |  | ||||||
| 		// Don't need to load netns for host network sandbox. |  | ||||||
| 		return sandbox, nil |  | ||||||
| 	} |  | ||||||
| 	if goruntime.GOOS == "windows" && meta.Config.GetWindows().GetSecurityContext().GetHostProcess() { |  | ||||||
| 		return sandbox, nil |  | ||||||
| 	} |  | ||||||
| 	sandbox.NetNS = netns.LoadNetNS(meta.NetNSPath) | 	sandbox.NetNS = netns.LoadNetNS(meta.NetNSPath) | ||||||
|  |  | ||||||
| 	// It doesn't matter whether task is running or not. If it is running, sandbox | 	// It doesn't matter whether task is running or not. If it is running, sandbox | ||||||
|   | |||||||
| @@ -25,8 +25,6 @@ import ( | |||||||
|  |  | ||||||
| 	"github.com/containerd/containerd/log" | 	"github.com/containerd/containerd/log" | ||||||
| 	"github.com/containernetworking/plugins/pkg/ns" | 	"github.com/containernetworking/plugins/pkg/ns" | ||||||
|  |  | ||||||
| 	runtime "k8s.io/cri-api/pkg/apis/runtime/v1" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // portForward uses netns to enter the sandbox namespace, and forwards a stream inside the | // portForward uses netns to enter the sandbox namespace, and forwards a stream inside the | ||||||
| @@ -37,12 +35,12 @@ func (c *criService) portForward(ctx context.Context, id string, port int32, str | |||||||
| 		return fmt.Errorf("failed to find sandbox %q in store: %w", id, err) | 		return fmt.Errorf("failed to find sandbox %q in store: %w", id, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var netNSDo func(func(ns.NetNS) error) error | 	var ( | ||||||
| 	// netNSPath is the network namespace path for logging. | 		netNSDo func(func(ns.NetNS) error) error | ||||||
| 	var netNSPath string | 		// netNSPath is the network namespace path for logging. | ||||||
| 	securityContext := s.Config.GetLinux().GetSecurityContext() | 		netNSPath string | ||||||
| 	hostNet := securityContext.GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE | 	) | ||||||
| 	if !hostNet { | 	if !hostNetwork(s.Config) { | ||||||
| 		if closed, err := s.NetNS.Closed(); err != nil { | 		if closed, err := s.NetNS.Closed(); err != nil { | ||||||
| 			return fmt.Errorf("failed to check netwok namespace closed for sandbox %q: %w", id, err) | 			return fmt.Errorf("failed to check netwok namespace closed for sandbox %q: %w", id, err) | ||||||
| 		} else if closed { | 		} else if closed { | ||||||
|   | |||||||
| @@ -23,7 +23,6 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"math" | 	"math" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	goruntime "runtime" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| @@ -245,20 +244,8 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox | |||||||
| 		return nil, fmt.Errorf("failed to get sandbox container info: %w", err) | 		return nil, fmt.Errorf("failed to get sandbox container info: %w", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	podNetwork := true | 	// Setup the network namespace if host networking wasn't requested. | ||||||
|  | 	if !hostNetwork(config) { | ||||||
| 	if goruntime.GOOS != "windows" && |  | ||||||
| 		config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE { |  | ||||||
| 		// Pod network is not needed on linux with host network. |  | ||||||
| 		podNetwork = false |  | ||||||
| 	} |  | ||||||
| 	if goruntime.GOOS == "windows" && |  | ||||||
| 		config.GetWindows().GetSecurityContext().GetHostProcess() { |  | ||||||
| 		// Windows HostProcess pods can only run on the host network |  | ||||||
| 		podNetwork = false |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if podNetwork { |  | ||||||
| 		netStart := time.Now() | 		netStart := time.Now() | ||||||
|  |  | ||||||
| 		// If it is not in host network namespace then create a namespace and set the sandbox | 		// If it is not in host network namespace then create a namespace and set the sandbox | ||||||
|   | |||||||
| @@ -20,7 +20,6 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	goruntime "runtime" |  | ||||||
|  |  | ||||||
| 	"github.com/containerd/containerd" | 	"github.com/containerd/containerd" | ||||||
| 	"github.com/containerd/containerd/errdefs" | 	"github.com/containerd/containerd/errdefs" | ||||||
| @@ -70,13 +69,9 @@ func (c *criService) PodSandboxStatus(ctx context.Context, r *runtime.PodSandbox | |||||||
| func (c *criService) getIPs(sandbox sandboxstore.Sandbox) (string, []string, error) { | func (c *criService) getIPs(sandbox sandboxstore.Sandbox) (string, []string, error) { | ||||||
| 	config := sandbox.Config | 	config := sandbox.Config | ||||||
|  |  | ||||||
| 	if goruntime.GOOS != "windows" && | 	// For sandboxes using the node network we are not | ||||||
| 		config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE { | 	// responsible for reporting the IP. | ||||||
| 		// For sandboxes using the node network we are not | 	if hostNetwork(config) { | ||||||
| 		// responsible for reporting the IP. |  | ||||||
| 		return "", nil, nil |  | ||||||
| 	} |  | ||||||
| 	if goruntime.GOOS == "windows" && config.GetWindows().GetSecurityContext().GetHostProcess() { |  | ||||||
| 		return "", nil, nil | 		return "", nil, nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Derek McGowan
					Derek McGowan