Linux之29—— ip netns 命令 network namespace 显示所有命名的 network namespace 创建命名的 network namespace 删除命名的 network namespace 查看进程的 network namespace 查看 network namespace 中进程的 PID 在指定的 network namespace 中执行命令 监控对 network namespace 的操作 理解 ip netns add 命令

ip netns 命令用来管理 network namespace。它可以创建命名的 network namespace,然后通过名字来引用 network namespace,所以使用起来很方便。

ip netns 命令格式如下:
ip [ OPTIONS ] netns  { COMMAND | help }

可以通过 help 命令查看 ip netns 所有操作的帮助信息:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

network namespace 在逻辑上是网络堆栈的一个副本,它有自己的路由、防火墙规则和网络设备。
默认情况下,子进程继承其父进程的 network namespace。也就是说,如果不显式创建新的 network namespace,所有进程都从 init 进程继承相同的默认 network namespace。
根据约定,命名的 network namespace 是可以打开的 /var/run/netns/ 目录下的一个对象。比如有一个名称为 net1 的 network namespace 对象,则可以由打开 /var/run/netns/net1 对象产生的文件描述符引用 network namespace net1。通过引用该文件描述符,可以修改进程的 network namespace。

显示所有命名的 network namespace

ip netns list 命令显示所有命名的 network namesapce,其实就是显示 /var/run/netns 目录下的所有 network namespace 对象:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

创建命名的 network namespace

ip netns add NAME 命令创建一个命名的 network namespace:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

删除命名的 network namespace

ip [-all] netns del [ NAME ] 命令删除指定名称的 network namespace。如果指定了 -all 选项,则尝试删除所有的 network namespace。

注意,如果我们把网卡设置到了某个 network namespace 中,并在该 network namespace 中启动了进程:

$ sudo ip netns add net0
$ sudo ip link set dev eth0 netns net0
$ sudo ip netns exec net0 bash

在另一个 bash 进程中删除 network namespace net0:

$ sudo ip netns del net0

此时虽然可以删除 netowrk namespace,但是在进程退出之前,网卡一直会保持在你已经删除了的那个 network namespace 中。

查看进程的 network namespace

ip netns identify [PID] 命令用来查看进程的 network namespace。如果不指定 PID 就显示当前进程的 network namespace:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

下面的命令指定了 PID:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

查看 network namespace 中进程的 PID

ip netns pids NAME 命令用来查看指定的 network namespace 中的进程的 PID。这个命令其实就是去检查 /proc 下的所有进程,看进程的 network namespace 是不是指定的 network namespace:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

在指定的 network namespace 中执行命令

ip [-all] netns exec [ NAME ] cmd 命令用来在指定的 network namespace 中执行命令。比如我们要看一下某个 network namespace 中有哪些网卡:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

ip netns exec 后面跟着 namespace 的名字,比如这里的 neta,然后是要执行的命令,只要是合法的 shell 命令都能运行,比如上面的 ip addr 或者 bash。
更棒的是,执行的可以是任何命令,不只是和网络相关的(当然,和网络无关命令执行的结果和在外部执行没有区别)。比如下面例子中,执行 bash 命令之后,后面所有的命令都是在这个 network namespace 中执行的,好处是不用每次执行命令都要把 ip netns exec NAME 补全,缺点是你无法清楚知道自己当前所在的 shell,容易混淆:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

通过 -all 参数我们可以同时在所有的 network namespace 执行命令:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

输出中的 netns: 指示在某个 network namespace 中执行的结果。

监控对 network namespace 的操作

ip netns monitor 命令用来监控对 network namespace 的操作。比如我们删除一个 network namespace 时就会收到相应的通知:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

理解 ip netns add 命令

我们通过下面的演示来理解 ip netns add 命令的本质。
查看默认 network namespace 的 ID:

$ readlink /proc/$$/ns/net

在 /var/run/netns 目录下创建一个用于绑定 network namespace 的文件,名为 mynet:

$ sudo mkdir -p /var/run/netns
$ sudo touch /var/run/netns/mynet

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

通过 unshare 命令创建新的 network namespace,并在新的 namespace 中启动新的 bash:

$ sudo unshare --net bash

查看新的 network namespace ID:

# readlink /proc/$$/ns/net

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

通过绑定挂载把当前 bash 进程的 network namespace 文件挂载到前面创建的 mynet 文件上:

# mount --bind /proc/$$/ns/net /var/run/netns/mynet
# ls -I /var/run/netns/mynet

通过 ls -I 命令可以看到文件 mynet 的 inode 号和 network namespace 的 ID 相同,说明绑定成功:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

退出新创建的 bash,再检查一次 mynet 文件的 inode:

# exit
$ ls -I /var/run/netns/mynet

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

可以看出 mynet 文件的 inode 没有发生变化,说明我们使用了绑定挂载后,虽然新的 network namespace 中已经没有进程了,但这个新的 network namespace 还继续存在。

上面的一系列操作其实等同于执行了命令:sudo ip netns add mynet
下面的 nsenter 命令则等同于执行了命令: sudo ip netns exec mynet bash

$ sudo nsenter --net=/var/run/netns/mynet bash
# readlink /proc/$$/ns/net

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

通过 nsenter 命令新建了一个 bash 进程,并把它加入 mynet 所关联的 network namespace(net:[4026532616])。

从上面的示例可以看出,创建命名的 network namespace 其实就是创建一个文件,然后通过绑定挂载的方式将新创建的 network namespace 文件(/proc/$$/ns/net)和该文件绑定,就算该 network namespace 里的所有进程都退出了,内核还是会保留该 network namespace,以后我们还可以通过这个绑定的文件来加入该 network namespace。

参考:
ip netns man page
Linux Namespace系列(06):network namespace

ip netns 命令用来管理 network namespace。它可以创建命名的 network namespace,然后通过名字来引用 network namespace,所以使用起来很方便。

ip netns 命令格式如下:
ip [ OPTIONS ] netns  { COMMAND | help }

可以通过 help 命令查看 ip netns 所有操作的帮助信息:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

network namespace 在逻辑上是网络堆栈的一个副本,它有自己的路由、防火墙规则和网络设备。
默认情况下,子进程继承其父进程的 network namespace。也就是说,如果不显式创建新的 network namespace,所有进程都从 init 进程继承相同的默认 network namespace。
根据约定,命名的 network namespace 是可以打开的 /var/run/netns/ 目录下的一个对象。比如有一个名称为 net1 的 network namespace 对象,则可以由打开 /var/run/netns/net1 对象产生的文件描述符引用 network namespace net1。通过引用该文件描述符,可以修改进程的 network namespace。

显示所有命名的 network namespace

ip netns list 命令显示所有命名的 network namesapce,其实就是显示 /var/run/netns 目录下的所有 network namespace 对象:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

创建命名的 network namespace

ip netns add NAME 命令创建一个命名的 network namespace:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

删除命名的 network namespace

ip [-all] netns del [ NAME ] 命令删除指定名称的 network namespace。如果指定了 -all 选项,则尝试删除所有的 network namespace。

注意,如果我们把网卡设置到了某个 network namespace 中,并在该 network namespace 中启动了进程:

$ sudo ip netns add net0
$ sudo ip link set dev eth0 netns net0
$ sudo ip netns exec net0 bash

在另一个 bash 进程中删除 network namespace net0:

$ sudo ip netns del net0

此时虽然可以删除 netowrk namespace,但是在进程退出之前,网卡一直会保持在你已经删除了的那个 network namespace 中。

查看进程的 network namespace

ip netns identify [PID] 命令用来查看进程的 network namespace。如果不指定 PID 就显示当前进程的 network namespace:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

下面的命令指定了 PID:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

查看 network namespace 中进程的 PID

ip netns pids NAME 命令用来查看指定的 network namespace 中的进程的 PID。这个命令其实就是去检查 /proc 下的所有进程,看进程的 network namespace 是不是指定的 network namespace:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

在指定的 network namespace 中执行命令

ip [-all] netns exec [ NAME ] cmd 命令用来在指定的 network namespace 中执行命令。比如我们要看一下某个 network namespace 中有哪些网卡:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

ip netns exec 后面跟着 namespace 的名字,比如这里的 neta,然后是要执行的命令,只要是合法的 shell 命令都能运行,比如上面的 ip addr 或者 bash。
更棒的是,执行的可以是任何命令,不只是和网络相关的(当然,和网络无关命令执行的结果和在外部执行没有区别)。比如下面例子中,执行 bash 命令之后,后面所有的命令都是在这个 network namespace 中执行的,好处是不用每次执行命令都要把 ip netns exec NAME 补全,缺点是你无法清楚知道自己当前所在的 shell,容易混淆:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

通过 -all 参数我们可以同时在所有的 network namespace 执行命令:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

输出中的 netns: 指示在某个 network namespace 中执行的结果。

监控对 network namespace 的操作

ip netns monitor 命令用来监控对 network namespace 的操作。比如我们删除一个 network namespace 时就会收到相应的通知:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

理解 ip netns add 命令

我们通过下面的演示来理解 ip netns add 命令的本质。
查看默认 network namespace 的 ID:

$ readlink /proc/$$/ns/net

在 /var/run/netns 目录下创建一个用于绑定 network namespace 的文件,名为 mynet:

$ sudo mkdir -p /var/run/netns
$ sudo touch /var/run/netns/mynet

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

通过 unshare 命令创建新的 network namespace,并在新的 namespace 中启动新的 bash:

$ sudo unshare --net bash

查看新的 network namespace ID:

# readlink /proc/$$/ns/net

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

通过绑定挂载把当前 bash 进程的 network namespace 文件挂载到前面创建的 mynet 文件上:

# mount --bind /proc/$$/ns/net /var/run/netns/mynet
# ls -I /var/run/netns/mynet

通过 ls -I 命令可以看到文件 mynet 的 inode 号和 network namespace 的 ID 相同,说明绑定成功:

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

退出新创建的 bash,再检查一次 mynet 文件的 inode:

# exit
$ ls -I /var/run/netns/mynet

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

可以看出 mynet 文件的 inode 没有发生变化,说明我们使用了绑定挂载后,虽然新的 network namespace 中已经没有进程了,但这个新的 network namespace 还继续存在。

上面的一系列操作其实等同于执行了命令:sudo ip netns add mynet
下面的 nsenter 命令则等同于执行了命令: sudo ip netns exec mynet bash

$ sudo nsenter --net=/var/run/netns/mynet bash
# readlink /proc/$$/ns/net

Linux之29—— ip netns 命令
network namespace
显示所有命名的 network namespace
创建命名的 network namespace
删除命名的 network namespace
查看进程的 network namespace
查看 network namespace 中进程的 PID
在指定的 network namespace 中执行命令
监控对 network namespace 的操作
理解 ip netns add 命令

通过 nsenter 命令新建了一个 bash 进程,并把它加入 mynet 所关联的 network namespace(net:[4026532616])。

从上面的示例可以看出,创建命名的 network namespace 其实就是创建一个文件,然后通过绑定挂载的方式将新创建的 network namespace 文件(/proc/$$/ns/net)和该文件绑定,就算该 network namespace 里的所有进程都退出了,内核还是会保留该 network namespace,以后我们还可以通过这个绑定的文件来加入该 network namespace。

参考:
ip netns man page
Linux Namespace系列(06):network namespace