Skip to content

Commit 0746dcc

Browse files
[Carry 2535] rootless: support detach-netns mode
When RootlessKit v2.0 (rootless-containers/rootlesskit PR 379) is installed, `containerd-rootless.sh` launches it with `--detach-netns` so as to run the daemon in the host network namespace. This will enable: - Accelerated (and deflaked) `nerdctl pull`, `nerdctl push`, `nerdctl build`, etc - Proper support for `nerdctl pull 127.0.0.1:.../...` - Proper support for `nerdctl run --net=host` Replaces Fahed Dorgaa's PR 2535 Co-authored-by: fahed dorgaa <fahed.dorgaa@gmail.com> Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
1 parent d2bcb5a commit 0746dcc

File tree

17 files changed

+246
-21
lines changed

17 files changed

+246
-21
lines changed

.github/workflows/test.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,31 +158,40 @@ jobs:
158158
include:
159159
- ubuntu: 20.04
160160
containerd: v1.6.26
161+
rootlesskit: v1.1.1
161162
target: test-integration-rootless
162163
- ubuntu: 20.04
163164
containerd: v1.7.11
165+
rootlesskit: v2.0.0-beta.0
164166
target: test-integration-rootless
165167
- ubuntu: 22.04
166168
containerd: v1.7.11
169+
rootlesskit: v1.1.1
167170
target: test-integration-rootless
168171
- ubuntu: 22.04
169172
containerd: main
173+
rootlesskit: v2.0.0-beta.0
170174
target: test-integration-rootless
171175
- ubuntu: 20.04
172176
containerd: v1.6.26
177+
rootlesskit: v1.1.1
173178
target: test-integration-rootless-port-slirp4netns
174179
- ubuntu: 20.04
175180
containerd: v1.7.11
181+
rootlesskit: v2.0.0-beta.0
176182
target: test-integration-rootless-port-slirp4netns
177183
- ubuntu: 22.04
178184
containerd: v1.7.11
185+
rootlesskit: v1.1.1
179186
target: test-integration-rootless-port-slirp4netns
180187
- ubuntu: 22.04
181188
containerd: main
189+
rootlesskit: v2.0.0-beta.0
182190
target: test-integration-rootless-port-slirp4netns
183191
env:
184192
UBUNTU_VERSION: "${{ matrix.ubuntu }}"
185193
CONTAINERD_VERSION: "${{ matrix.containerd }}"
194+
ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}"
186195
TEST_TARGET: "${{ matrix.target }}"
187196
steps:
188197
- uses: actions/checkout@v4.1.1
@@ -191,7 +200,7 @@ jobs:
191200
- name: "Register QEMU (tonistiigi/binfmt)"
192201
run: docker run --privileged --rm tonistiigi/binfmt --install all
193202
- name: "Prepare (network driver=slirp4netns, port driver=builtin)"
194-
run: DOCKER_BUILDKIT=1 docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} .
203+
run: DOCKER_BUILDKIT=1 docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} --build-arg ROOTLESSKIT_VERSION=${ROOTLESSKIT_VERSION} .
195204
- name: "Test (network driver=slirp4netns, port driver=builtin)"
196205
run: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=1 ${TEST_TARGET}
197206

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1
2929
# Extra deps: Encryption
3030
ARG IMGCRYPT_VERSION=v1.1.9
3131
# Extra deps: Rootless
32-
ARG ROOTLESSKIT_VERSION=v1.1.1
32+
ARG ROOTLESSKIT_VERSION=v2.0.0-beta.0
3333
ARG SLIRP4NETNS_VERSION=v1.2.2
3434
# Extra deps: bypass4netns
3535
ARG BYPASS4NETNS_VERSION=v0.3.0
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
7c8c07c159aef32b5e68f5b8dc508dc422499744f61fa916c246bfae16a0d85c rootlesskit-aarch64.tar.gz
2+
683ba2c34bfa4a3477f9c50508a233c94b71a6eeaa0ee080abd1ebc2c09a8b9c rootlesskit-armv7l.tar.gz
3+
844b6297021d914be9f266e341ff77da4b98f43074504fe9cc020ae5c61a791d rootlesskit-ppc64le.tar.gz
4+
d317e9c519d862508d6659083f9e1773573e899aa6e48e89d121211e5e823b6a rootlesskit-riscv64.tar.gz
5+
720b425c608f8ab4326354582bc92825031d9d8c40865df155c2c7cb8368f115 rootlesskit-s390x.tar.gz
6+
d29edd2e3d903974754edb14b251ef19bfa9317e6626436fac760d1213879e8d rootlesskit-x86_64.tar.gz

cmd/nerdctl/container_run_network_linux_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,11 @@ func TestRunContainerWithMACAddress(t *testing.T) {
494494
}
495495

496496
func TestHostsFileMounts(t *testing.T) {
497+
if rootlessutil.IsRootless() {
498+
if detachedNetNS, _ := rootlessutil.DetachedNetNS(); detachedNetNS != "" {
499+
t.Skip("/etc/hosts is not writable")
500+
}
501+
}
497502
base := testutil.NewBase(t)
498503

499504
base.Cmd("run", "--rm", testutil.CommonImage,

cmd/nerdctl/ipfs_linux_test.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,21 @@ func TestIPFSAddress(t *testing.T) {
7373

7474
func runIPFSDaemonContainer(t *testing.T, base *testutil.Base) (ipfsAddress string, done func()) {
7575
name := "test-ipfs-address"
76-
base.Cmd("run", "-d", "--name", name, "--entrypoint=/bin/sh", testutil.KuboImage, "-c", "ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/5001 && ipfs daemon --offline").AssertOK()
77-
iplines := base.Cmd("inspect", name, "-f", "'{{json .NetworkSettings.IPAddress}}'").OutLines()
78-
t.Logf("IPAddress=%v", iplines)
79-
assert.Equal(t, len(iplines), 2)
80-
matches := iplineRegexp.FindStringSubmatch(iplines[0])
81-
t.Logf("ip address matches=%v", matches)
82-
assert.Equal(t, len(matches), 2)
83-
ipfsaddr := fmt.Sprintf("/ip4/%s/tcp/5001", matches[1])
76+
var ipfsaddr string
77+
if detachedNetNS, _ := rootlessutil.DetachedNetNS(); detachedNetNS != "" {
78+
// detached-netns mode can't use .NetworkSettings.IPAddress, because the daemon and CNI has different network namespaces
79+
base.Cmd("run", "-d", "-p", "127.0.0.1:5999:5999", "--name", name, "--entrypoint=/bin/sh", testutil.KuboImage, "-c", "ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/5999 && ipfs daemon --offline").AssertOK()
80+
ipfsaddr = "/ip4/127.0.0.1/tcp/5999"
81+
} else {
82+
base.Cmd("run", "-d", "--name", name, "--entrypoint=/bin/sh", testutil.KuboImage, "-c", "ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/5001 && ipfs daemon --offline").AssertOK()
83+
iplines := base.Cmd("inspect", name, "-f", "'{{json .NetworkSettings.IPAddress}}'").OutLines()
84+
t.Logf("IPAddress=%v", iplines)
85+
assert.Equal(t, len(iplines), 2)
86+
matches := iplineRegexp.FindStringSubmatch(iplines[0])
87+
t.Logf("ip address matches=%v", matches)
88+
assert.Equal(t, len(matches), 2)
89+
ipfsaddr = fmt.Sprintf("/ip4/%s/tcp/5001", matches[1])
90+
}
8491
return ipfsaddr, func() {
8592
base.Cmd("kill", "test-ipfs-address").AssertOK()
8693
base.Cmd("rm", "test-ipfs-address").AssertOK()

docs/rootless.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,35 @@ $ nerdctl run -it --rm -p 8080:80 --label nerdctl/bypass4netns=true alpine
130130

131131
More detail is available at [https://github.com/rootless-containers/bypass4netns/blob/master/README.md](https://github.com/rootless-containers/bypass4netns/blob/master/README.md)
132132

133+
## Configuring RootlessKit
134+
135+
Rootless containerd recognizes the following environment variables to configure the behavior of [RootlessKit](https://github.com/rootless-containers/rootlesskit):
136+
137+
* `CONTAINERD_ROOTLESS_ROOTLESSKIT_STATE_DIR=DIR`: the rootlesskit state dir. Defaults to `$XDG_RUNTIME_DIR/containerd-rootless`.
138+
* `CONTAINERD_ROOTLESS_ROOTLESSKIT_NET=(slirp4netns|vpnkit|lxc-user-nic)`: the rootlesskit network driver. Defaults to "slirp4netns" if slirp4netns (>= v0.4.0) is installed. Otherwise defaults to "vpnkit".
139+
* `CONTAINERD_ROOTLESS_ROOTLESSKIT_MTU=NUM`: the MTU value for the rootlesskit network driver. Defaults to 65520 for slirp4netns, 1500 for other drivers.
140+
* `CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=(builtin|slirp4netns)`: the rootlesskit port driver. Defaults to "builtin".
141+
* `CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SANDBOX=(auto|true|false)`: whether to protect slirp4netns with a dedicated mount namespace. Defaults to "auto".
142+
* `CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SECCOMP=(auto|true|false)`: whether to protect slirp4netns with seccomp. Defaults to "auto".
143+
* `CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS=(auto|true|false)`: whether to launch rootlesskit with the "detach-netns" mode.
144+
Defaults to "auto", which is resolved to "true" if RootlessKit >= 2.0 is installed.
145+
The "detached-netns" mode accelerates `nerdctl (pull|push|build)` and enables `nerdctl run --net=host`,
146+
however, there is a relatively minor drawback with the current version of BuildKit (planned to be fixed in [BuildKit v0.13](https://github.com/moby/buildkit/pull/4546)):
147+
the host loopback IP address (127.0.0.1) is exposed to Dockerfile's "RUN" instructions during `nerdctl build` (not `nerdctl run`).
148+
If you want to hide 127.0.0.1 from "RUN" instructions, you should set `CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS` to "false".
149+
150+
To set these variables, create `~/.config/systemd/user/containerd.service.d/override.conf` as follows:
151+
```ini
152+
[Service]
153+
Environment=CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS="false"
154+
```
155+
156+
And then run the following commands:
157+
```bash
158+
systemctl --user daemon-reload
159+
systemctl --user restart containerd
160+
```
161+
133162
## Troubleshooting
134163

135164
### Hint to Fedora users

extras/rootless/containerd-rootless-setuptool.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,12 @@ cmd_entrypoint_check() {
143143
cmd_entrypoint_nsenter() {
144144
# No need to call init()
145145
pid=$(cat "$XDG_RUNTIME_DIR/containerd-rootless/child_pid")
146-
exec nsenter --no-fork --wd="$(pwd)" --preserve-credentials -m -n -U -t "$pid" -- "$@"
146+
n=""
147+
# If RootlessKit is running with `--detach-netns` mode, we do NOT enter the detached netns here
148+
if [ ! -e "$XDG_RUNTIME_DIR/containerd-rootless/netns" ]; then
149+
n="-n"
150+
fi
151+
exec nsenter --no-fork --wd="$(pwd)" --preserve-credentials -m $n -U -t "$pid" -- "$@"
147152
}
148153

149154
show_systemd_error() {

extras/rootless/containerd-rootless.sh

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
# External dependencies:
2929
# * newuidmap and newgidmap needs to be installed.
3030
# * /etc/subuid and /etc/subgid needs to be configured for the current user.
31-
# * RootlessKit (>= v0.10.0) needs to be installed. RootlessKit >= v0.14.1 is recommended.
31+
# * RootlessKit (>= v0.10.0) needs to be installed. RootlessKit >= v2.0.0 is recommended.
3232
# * Either one of slirp4netns (>= v0.4.0), VPNKit, lxc-user-nic needs to be installed. slirp4netns >= v1.1.7 is recommended.
3333
#
3434
# Recognized environment variables:
@@ -38,6 +38,14 @@
3838
# * CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=(builtin|slirp4netns): the rootlesskit port driver. Defaults to "builtin".
3939
# * CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SANDBOX=(auto|true|false): whether to protect slirp4netns with a dedicated mount namespace. Defaults to "auto".
4040
# * CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SECCOMP=(auto|true|false): whether to protect slirp4netns with seccomp. Defaults to "auto".
41+
# * CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS=(auto|true|false): whether to launch rootlesskit with the "detach-netns" mode.
42+
# Defaults to "auto", which is resolved to "true" if RootlessKit >= 2.0 is installed.
43+
# The "detached-netns" mode accelerates `nerdctl (pull|push|build)` and enables `nerdctl run --net=host`,
44+
# however, there is a relatively minor drawback with the current version of BuildKit (planned to be fixed in BuildKit v0.13):
45+
# the host loopback IP address (127.0.0.1) is exposed to Dockerfile's "RUN" instructions during `nerdctl build` (not `nerdctl run`).
46+
# If you want to hide 127.0.0.1 from "RUN" instructions, you should set CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS to "false".
47+
48+
# See also: https://github.com/containerd/nerdctl/blob/main/docs/rootless.md#configuring-rootlesskit
4149

4250
set -e
4351
if ! [ -w $XDG_RUNTIME_DIR ]; then
@@ -69,6 +77,7 @@ if [ -z $_CONTAINERD_ROOTLESS_CHILD ]; then
6977
: "${CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER:=builtin}"
7078
: "${CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SANDBOX:=auto}"
7179
: "${CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SECCOMP:=auto}"
80+
: "${CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS:=auto}"
7281
net=$CONTAINERD_ROOTLESS_ROOTLESSKIT_NET
7382
mtu=$CONTAINERD_ROOTLESS_ROOTLESSKIT_MTU
7483
if [ -z $net ]; then
@@ -107,6 +116,25 @@ if [ -z $_CONTAINERD_ROOTLESS_CHILD ]; then
107116
export _CONTAINERD_ROOTLESS_SELINUX
108117
fi
109118
fi
119+
120+
case "$CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS" in
121+
auto)
122+
if rootlesskit --help | grep -qw -- "--detach-netns"; then
123+
CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS=--detach-netns $CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS
124+
fi
125+
;;
126+
1 | true)
127+
CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS=--detach-netns $CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS
128+
;;
129+
0 | false)
130+
# NOP
131+
;;
132+
*)
133+
echo "Unknown CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS value: $CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS"
134+
exit 1
135+
;;
136+
esac
137+
110138
# Re-exec the script via RootlessKit, so as to create unprivileged {user,mount,network} namespaces.
111139
#
112140
# --copy-up allows removing/creating files in the directories by creating tmpfs and symlinks

pkg/cmd/container/create.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import (
5050
"github.com/containerd/nerdctl/pkg/namestore"
5151
"github.com/containerd/nerdctl/pkg/platformutil"
5252
"github.com/containerd/nerdctl/pkg/referenceutil"
53+
"github.com/containerd/nerdctl/pkg/rootlessutil"
5354
"github.com/containerd/nerdctl/pkg/strutil"
5455
dockercliopts "github.com/docker/cli/opts"
5556
dockeropts "github.com/docker/docker/opts"
@@ -418,6 +419,29 @@ func GenerateLogURI(dataStore string) (*url.URL, error) {
418419
}
419420

420421
func withNerdctlOCIHook(cmd string, args []string) (oci.SpecOpts, error) {
422+
if rootlessutil.IsRootless() {
423+
detachedNetNS, err := rootlessutil.DetachedNetNS()
424+
if err != nil {
425+
return nil, fmt.Errorf("failed to check whether RootlessKit is running with --detach-netns: %w", err)
426+
}
427+
if detachedNetNS != "" {
428+
// Rewrite {cmd, args} if RootlessKit with running with --detach-netns, so that the hook can gain
429+
// CAP_NET_ADMIN in the namespaces.
430+
// - Old:
431+
// - cmd: "/usr/local/bin/nerdctl"
432+
// - args: {"--data-root=/foo", "internal", "oci-hook"}
433+
// - New:
434+
// - cmd: "/usr/bin/nsenter"
435+
// - args: {"-n/run/user/1000/containerd-rootless/netns", "-F", "--", "/usr/local/bin/nerdctl", "--data-root=/foo", "internal", "oci-hook"}
436+
oldCmd, oldArgs := cmd, args
437+
cmd, err = exec.LookPath("nsenter")
438+
if err != nil {
439+
return nil, err
440+
}
441+
args = append([]string{"-n" + detachedNetNS, "-F", "--", oldCmd}, oldArgs...)
442+
}
443+
}
444+
421445
args = append([]string{cmd}, append(args, "internal", "oci-hook")...)
422446
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
423447
if s.Hooks == nil {

pkg/containerutil/container_network_manager.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"github.com/containerd/nerdctl/pkg/mountutil"
3939
"github.com/containerd/nerdctl/pkg/netutil"
4040
"github.com/containerd/nerdctl/pkg/netutil/nettype"
41+
"github.com/containerd/nerdctl/pkg/rootlessutil"
4142
"github.com/containerd/nerdctl/pkg/strutil"
4243
"github.com/opencontainers/runtime-spec/specs-go"
4344
)
@@ -461,9 +462,49 @@ func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containe
461462
}
462463
}
463464

465+
if rootlessutil.IsRootless() {
466+
detachedNetNS, err := rootlessutil.DetachedNetNS()
467+
if err != nil {
468+
return nil, nil, fmt.Errorf("failed to check whether RootlessKit is running with --detach-netns: %w", err)
469+
}
470+
if detachedNetNS != "" {
471+
// For rootless + host netns, we can't mount sysfs.
472+
// We can't (non-recursively) bind mount /sys, either.
473+
//
474+
// TODO: consider to just rbind /sys from the host with rro,
475+
// when rro is available (kernel >= 5.12, runc >= 1.1).
476+
//
477+
// Relevant: https://github.com/moby/buildkit/blob/v0.12.4/util/rootless/specconv/specconv_linux.go#L15-L34
478+
specs = append(specs, withRemoveSysfs)
479+
}
480+
}
481+
464482
return specs, cOpts, nil
465483
}
466484

485+
func withRemoveSysfs(_ context.Context, _ oci.Client, c *containers.Container, s *oci.Spec) error {
486+
var hasSysfs bool
487+
for _, mount := range s.Mounts {
488+
if mount.Type == "sysfs" {
489+
hasSysfs = true
490+
break
491+
}
492+
}
493+
if !hasSysfs {
494+
// NOP, as the user has specified a custom /sys mount
495+
return nil
496+
}
497+
var mounts []specs.Mount // nolint: prealloc
498+
for _, mount := range s.Mounts {
499+
if strings.HasPrefix(mount.Destination, "/sys") {
500+
continue
501+
}
502+
mounts = append(mounts, mount)
503+
}
504+
s.Mounts = mounts
505+
return nil
506+
}
507+
467508
// types.NetworkOptionsManager implementation for CNI networking settings.
468509
// This is a more specialized and OS-dependendant networking model so this
469510
// struct provides different implementations on different platforms.

pkg/defaults/defaults_linux.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ func HostsDirs() []string {
138138

139139
// HostGatewayIP returns the non-loop-back host ip if available and returns empty string if running into error.
140140
func HostGatewayIP() string {
141+
// no need to use [rootlessutil.WithDetachedNetNSIfAny] here
141142
addrs, err := net.InterfaceAddrs()
142143
if err != nil {
143144
return ""

pkg/netutil/netutil_unix.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/Masterminds/semver/v3"
3232
"github.com/containerd/log"
3333
"github.com/containerd/nerdctl/pkg/defaults"
34+
"github.com/containerd/nerdctl/pkg/rootlessutil"
3435
"github.com/containerd/nerdctl/pkg/strutil"
3536
"github.com/containerd/nerdctl/pkg/systemutil"
3637
"github.com/mitchellh/mapstructure"
@@ -322,11 +323,13 @@ func guessFirewallPluginVersion(stderr string) (*semver.Version, error) {
322323
}
323324

324325
func removeBridgeNetworkInterface(netIf string) error {
325-
link, err := netlink.LinkByName(netIf)
326-
if err == nil {
327-
if err := netlink.LinkDel(link); err != nil {
328-
return fmt.Errorf("failed to remove network interface %s: %v", netIf, err)
326+
return rootlessutil.WithDetachedNetNSIfAny(func() error {
327+
link, err := netlink.LinkByName(netIf)
328+
if err == nil {
329+
if err := netlink.LinkDel(link); err != nil {
330+
return fmt.Errorf("failed to remove network interface %s: %v", netIf, err)
331+
}
329332
}
330-
}
331-
return nil
333+
return nil
334+
})
332335
}

pkg/netutil/subnet/subnet.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,17 @@ package subnet
1919
import (
2020
"fmt"
2121
"net"
22+
23+
"github.com/containerd/nerdctl/pkg/rootlessutil"
2224
)
2325

2426
func GetLiveNetworkSubnets() ([]*net.IPNet, error) {
25-
addrs, err := net.InterfaceAddrs()
26-
if err != nil {
27+
var addrs []net.Addr
28+
if err := rootlessutil.WithDetachedNetNSIfAny(func() error {
29+
var err2 error
30+
addrs, err2 = net.InterfaceAddrs()
31+
return err2
32+
}); err != nil {
2733
return nil, err
2834
}
2935
nets := make([]*net.IPNet, 0, len(addrs))

pkg/rootlessutil/parent_linux.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ func ParentMain(hostGatewayIP string) error {
7777
return err
7878
}
7979

80+
detachedNetNSPath, err := detachedNetNS(stateDir)
81+
if err != nil {
82+
return err
83+
}
84+
detachNetNSMode := detachedNetNSPath != ""
85+
log.L.Debugf("RootlessKit detach-netns mode: %v", detachNetNSMode)
86+
if err != nil {
87+
return err
88+
}
89+
8090
wd, err := os.Getwd()
8191
if err != nil {
8292
return err
@@ -92,10 +102,13 @@ func ParentMain(hostGatewayIP string) error {
92102
"-r/", // root dir (busybox nsenter wants this to be explicitly specified),
93103
"-w" + wd, // work dir
94104
"--preserve-credentials",
95-
"-m", "-n", "-U",
105+
"-m", "-U",
96106
"-t", strconv.Itoa(childPid),
97107
"-F", // no fork
98108
}
109+
if !detachNetNSMode {
110+
args = append(args, "-n")
111+
}
99112
args = append(args, os.Args...)
100113
log.L.Debugf("rootless parent main: executing %q with %v", arg0, args)
101114

0 commit comments

Comments
 (0)