From 54b588c07d05858c9bbc523eeff0badb85d53f76 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Thu, 18 Feb 2021 13:51:27 +0100 Subject: rootless cni without infra container Instead of creating an extra container create a network and mount namespace inside the podman user namespace. This ns is used to for rootless cni operations. This helps to align the rootless and rootful network code path. If we run as rootless we just have to set up a extra net ns and initialize slirp4netns in it. The ocicni lib will be called in that net ns. This design allows allows easier maintenance, no extra container with pause processes, support for rootless cni with --uidmap and possibly more. The biggest problem is backwards compatibility. I don't think live migration can be possible. If the user reboots or restart all cni containers everything should work as expected again. The user is left with the rootless-cni-infa container and image but this can safely be removed. To make the existing cni configs work we need execute the cni plugins in a extra mount namespace. This ensures that we can safely mount over /run and /var which have to be writeable for the cni plugins without removing access to these files by the main podman process. One caveat is that we need to keep the netns files at `XDG_RUNTIME_DIR/netns` accessible. `XDG_RUNTIME_DIR/rootless-cni/{run,var}` will be mounted to `/{run,var}`. To ensure that we keep the netns directory we bind mount this relative to the new root location, e.g. XDG_RUNTIME_DIR/rootless-cni/run/user/1000/netns before we mount the run directory. The run directory is mounted recursive, this makes the netns directory at the same path accessible as before. This also allows iptables-legacy to work because /run/xtables.lock is now writeable. Signed-off-by: Paul Holzinger --- pkg/netns/netns_linux.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'pkg') diff --git a/pkg/netns/netns_linux.go b/pkg/netns/netns_linux.go index 0b7d1782c..ecefb65ff 100644 --- a/pkg/netns/netns_linux.go +++ b/pkg/netns/netns_linux.go @@ -35,9 +35,9 @@ import ( "golang.org/x/sys/unix" ) -// get NSRunDir returns the dir of where to create the netNS. When running +// GetNSRunDir returns the dir of where to create the netNS. When running // rootless, it needs to be at a location writable by user. -func getNSRunDir() (string, error) { +func GetNSRunDir() (string, error) { if rootless.IsRootless() { rootlessDir, err := util.GetRuntimeDir() if err != nil { @@ -51,15 +51,21 @@ func getNSRunDir() (string, error) { // NewNS creates a new persistent (bind-mounted) network namespace and returns // an object representing that namespace, without switching to it. func NewNS() (ns.NetNS, error) { - nsRunDir, err := getNSRunDir() + b := make([]byte, 16) + _, err := rand.Reader.Read(b) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to generate random netns name: %v", err) } + nsName := fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) + return NewNSWithName(nsName) +} - b := make([]byte, 16) - _, err = rand.Reader.Read(b) +// NewNSWithName creates a new persistent (bind-mounted) network namespace and returns +// an object representing that namespace, without switching to it. +func NewNSWithName(name string) (ns.NetNS, error) { + nsRunDir, err := GetNSRunDir() if err != nil { - return nil, fmt.Errorf("failed to generate random netns name: %v", err) + return nil, err } // Create the directory for mounting network namespaces @@ -93,10 +99,8 @@ func NewNS() (ns.NetNS, error) { } } - nsName := fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) - // create an empty file at the mount point - nsPath := path.Join(nsRunDir, nsName) + nsPath := path.Join(nsRunDir, name) mountPointFd, err := os.Create(nsPath) if err != nil { return nil, err @@ -177,7 +181,7 @@ func NewNS() (ns.NetNS, error) { // UnmountNS unmounts the NS held by the netns object func UnmountNS(ns ns.NetNS) error { - nsRunDir, err := getNSRunDir() + nsRunDir, err := GetNSRunDir() if err != nil { return err } -- cgit v1.2.3-54-g00ecf