diff --git a/docs/cri/config.md b/docs/cri/config.md index 417862396..83b183968 100644 --- a/docs/cri/config.md +++ b/docs/cri/config.md @@ -59,6 +59,11 @@ version = 2 # ReadOnlyRootFilesystem since containers won't silently mount a temporary volume. ignore_image_defined_volumes = false + # netns_mounts_under_state_dir places all mounts for network namespaces under StateDir/netns + # instead of being placed under the hardcoded directory /var/run/netns. Changing this setting + # requires that all containers are deleted. + netns_mounts_under_state_dir = false + # 'plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming' contains a x509 valid key pair to stream with tls. [plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming] # tls_cert_file is the filepath to the certificate paired with the "tls_key_file" diff --git a/pkg/cri/config/config.go b/pkg/cri/config/config.go index 7c5a20ecf..2eededa23 100644 --- a/pkg/cri/config/config.go +++ b/pkg/cri/config/config.go @@ -253,6 +253,10 @@ type PluginConfig struct { // isolation, security and early detection of issues in the mount configuration when using // ReadOnlyRootFilesystem since containers won't silently mount a temporary volume. IgnoreImageDefinedVolumes bool `toml:"ignore_image_defined_volumes" json:"ignoreImageDefinedVolumes"` + // NetNSMountsUnderStateDir places all mounts for network namespaces under StateDir/netns instead + // of being placed under the hardcoded directory /var/run/netns. Changing this setting requires + // that all containers are deleted. + NetNSMountsUnderStateDir bool `toml:"netns_mounts_under_state_dir" json:"netnsMountsUnderStateDir"` } // X509KeyPairStreaming contains the x509 configuration for streaming diff --git a/pkg/cri/server/sandbox_run.go b/pkg/cri/server/sandbox_run.go index 0ae6466ac..af3b5ecd9 100644 --- a/pkg/cri/server/sandbox_run.go +++ b/pkg/cri/server/sandbox_run.go @@ -19,6 +19,7 @@ package server import ( "encoding/json" "math" + "path/filepath" goruntime "runtime" "strings" @@ -120,7 +121,11 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox // handle. NetNSPath in sandbox metadata and NetNS is non empty only for non host network // namespaces. If the pod is in host network namespace then both are empty and should not // be used. - sandbox.NetNS, err = netns.NewNetNS() + var netnsMountDir string = "/var/run/netns" + if c.config.NetNSMountsUnderStateDir { + netnsMountDir = filepath.Join(c.config.StateDir, "netns") + } + sandbox.NetNS, err = netns.NewNetNS(netnsMountDir) if err != nil { return nil, errors.Wrapf(err, "failed to create network namespace for sandbox %q", id) } diff --git a/pkg/netns/netns_linux.go b/pkg/netns/netns_linux.go index 65b7f1010..d58f8ab92 100644 --- a/pkg/netns/netns_linux.go +++ b/pkg/netns/netns_linux.go @@ -46,14 +46,12 @@ import ( "golang.org/x/sys/unix" ) -const nsRunDir = "/var/run/netns" - // Some of the following functions are migrated from // https://github.com/containernetworking/plugins/blob/master/pkg/testutils/netns_linux.go // newNS creates a new persistent (bind-mounted) network namespace and returns the // path to the network namespace. -func newNS() (nsPath string, err error) { +func newNS(baseDir string) (nsPath string, err error) { b := make([]byte, 16) if _, err := rand.Reader.Read(b); err != nil { return "", errors.Wrap(err, "failed to generate random netns name") @@ -62,13 +60,13 @@ func newNS() (nsPath string, err error) { // Create the directory for mounting network namespaces // This needs to be a shared mountpoint in case it is mounted in to // other namespaces (containers) - if err := os.MkdirAll(nsRunDir, 0755); err != nil { + if err := os.MkdirAll(baseDir, 0755); err != nil { return "", err } // create an empty file at the mount point nsName := fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) - nsPath = path.Join(nsRunDir, nsName) + nsPath = path.Join(baseDir, nsName) mountPointFd, err := os.Create(nsPath) if err != nil { return "", err @@ -162,8 +160,8 @@ type NetNS struct { } // NewNetNS creates a network namespace. -func NewNetNS() (*NetNS, error) { - path, err := newNS() +func NewNetNS(baseDir string) (*NetNS, error) { + path, err := newNS(baseDir) if err != nil { return nil, errors.Wrap(err, "failed to setup netns") } diff --git a/pkg/netns/netns_other.go b/pkg/netns/netns_other.go index 0e618e4f7..e2000bf7f 100644 --- a/pkg/netns/netns_other.go +++ b/pkg/netns/netns_other.go @@ -30,7 +30,7 @@ type NetNS struct { } // NewNetNS creates a network namespace. -func NewNetNS() (*NetNS, error) { +func NewNetNS(baseDir string) (*NetNS, error) { return nil, errNotImplementedOnUnix } diff --git a/pkg/netns/netns_windows.go b/pkg/netns/netns_windows.go index 6fdee1ccb..1386f5364 100644 --- a/pkg/netns/netns_windows.go +++ b/pkg/netns/netns_windows.go @@ -26,7 +26,7 @@ type NetNS struct { } // NewNetNS creates a network namespace for the sandbox -func NewNetNS() (*NetNS, error) { +func NewNetNS(baseDir string) (*NetNS, error) { temp := hcn.HostComputeNamespace{} hcnNamespace, err := temp.Create() if err != nil {