在net netns列表中看不到docker网络命名空间

chr*_*ian 45 linux docker linux-namespaces

当我创建一个新的docker容器时

docker run -it -m 560m --cpuset-cpus=1,2 ubuntu sleep 120
Run Code Online (Sandbox Code Playgroud)

并检查其命名空间,我可以看到已创建新的命名空间(pid 7047的示例).

root@dude2:~# ls /proc/7047/ns -la
total 0
dr-x--x--x 2 root root 0 Jul  7 12:17 .
dr-xr-xr-x 9 root root 0 Jul  7 12:16 ..
lrwxrwxrwx 1 root root 0 Jul  7 12:17 ipc -> ipc:[4026532465]
lrwxrwxrwx 1 root root 0 Jul  7 12:17 mnt -> mnt:[4026532463]
lrwxrwxrwx 1 root root 0 Jul  7 12:17 net -> net:[4026532299]
lrwxrwxrwx 1 root root 0 Jul  7 12:17 pid -> pid:[4026532466]
lrwxrwxrwx 1 root root 0 Jul  7 12:17 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Jul  7 12:17 uts -> uts:[4026532464]
root@dude2:~# ls /proc/self/ns -la
Run Code Online (Sandbox Code Playgroud)

当我检查时, ip netns list我看不到新的网络命名空间.

dude@dude2:~/docker/testroot$ ip netns list
dude@dude2:~/docker/testroot$ 
Run Code Online (Sandbox Code Playgroud)

知道为什么吗?

jar*_*ary 52

那是因为docker没有创建所需的符号链接:

# (as root)
pid=$(docker inspect -f '{{.State.Pid}}' ${container_id})
mkdir -p /var/run/netns/
ln -sfT /proc/$pid/ns/net /var/run/netns/$container_id
Run Code Online (Sandbox Code Playgroud)

然后,可以检查容器的netns命名空间ip netns ${container_id},例如:

# e.g. show stats about eth0 inside the container 
ip netns exec "${container_id}" ip -s link show eth0
Run Code Online (Sandbox Code Playgroud)

  • 请绑定挂载(网络)命名空间引用,因为符号链接稍后可能指向重用的 PID 和完全不同的命名空间。相反,在 `/run/netns/` 中创建一个空文件 `foo`,然后简单地将 `/proc/.../ns/net` 绑定挂载到 `/run/netns/foo`。这将确保如果原始进程终止并且 PID 被重用,旧 PID 的网络命名空间仍然保持打开状态,直到您卸载或重新启动,但它永远不会错误地指向新进程的网络命名空间。 (6认同)
  • 您还可以在“ip”期望的位置挂载“/var/run/docker/netns”“docker run -it --rm -v /var/run/docker/netns:/var/run/netns --privileged=” true nicolaka/netshoot ip netns 列表` (2认同)

lar*_*sks 36

如@jary所示,该ip netns命令仅适用于命名空间符号链接/var/run/netns.但是,如果您有nsenter可用的命令(util-linux包的一部分),则可以使用docker容器的PID完成相同的操作.

要获取docker容器的PID,您可以运行:

docker inspect --format '{{.State.Pid}}' <container_name_or_Id>
Run Code Online (Sandbox Code Playgroud)

要在容器的网络命名空间内获取命令:

nsenter -t <contanier_pid> -n <command>
Run Code Online (Sandbox Code Playgroud)

例如:

$ docker inspect --format '{{.State.Pid}}' weechat
4432
$ sudo nsenter -t 4432 -n ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
75: eth0@if76: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:1b brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.27/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:1b/64 scope link 
       valid_lft forever preferred_lft forever
Run Code Online (Sandbox Code Playgroud)

以上相当于跑步ip netns exec <some_namespace> ip addr show.

如您所见,您需要以nsenterroot权限运行.


Lig*_*t.G 8

与@jary的答案类似但不同。
无需介绍/proc/<pid>/netster。下面仅需一步即可实现您想要的。因此,您可以操作容器的网络名称空间,就像在主机上手动创建它们一样。

一招:

ln -s /var/run/docker/netns  /var/run/netns 
Run Code Online (Sandbox Code Playgroud)

结果:

启动一个容器:

docker run -tid ubuntu:18.04 
Run Code Online (Sandbox Code Playgroud)

列出容器:

root@Light-G:/var/run# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
972909a27ea1        ubuntu:18.04        "/bin/bash"         19 seconds ago      Up 18 seconds                           peaceful_easley
Run Code Online (Sandbox Code Playgroud)

列出此容器的网络名称空间:

root@Light-G:/var/run# ip netns list
733443afef58 (id: 0)
Run Code Online (Sandbox Code Playgroud)

删除容器:

root@Light-G:/var/run# docker rm -f 972909a27ea1
972909a27ea1
Run Code Online (Sandbox Code Playgroud)

再次列出网络名称空间:

root@Light-G:/var/run# ip netns list
root@Light-G:/var/run#
Run Code Online (Sandbox Code Playgroud)

  • 正如经常发生的那样,您需要 `ln -Ts` 而不仅仅是 `ln -s` 。这样你就永远不会得到双重嵌套的 /var/run/netns/netns。 (2认同)