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 <paul.holzinger@web.de>
This commit is contained in:
Paul Holzinger
2021-02-18 13:51:27 +01:00
parent 8b599c5126
commit 54b588c07d
6 changed files with 440 additions and 191 deletions

View File

@ -11,7 +11,6 @@ import (
"github.com/containernetworking/cni/pkg/version"
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/podman/v3/pkg/util"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@ -223,9 +222,8 @@ func createBridge(name string, options entities.NetworkCreateOptions, runtimeCon
plugins = append(plugins, NewPortMapPlugin())
plugins = append(plugins, NewFirewallPlugin())
plugins = append(plugins, NewTuningPlugin())
// if we find the dnsname plugin or are rootless, we add configuration for it
// the rootless-cni-infra container has the dnsname plugin always installed
if (HasDNSNamePlugin(runtimeConfig.Network.CNIPluginDirs) || rootless.IsRootless()) && !options.DisableDNS {
// if we find the dnsname plugin we add configuration for it
if HasDNSNamePlugin(runtimeConfig.Network.CNIPluginDirs) && !options.DisableDNS {
if options.Internal {
logrus.Warnf("dnsname and --internal networks are incompatible. dnsname plugin not configured for network %s", name)
} else {