原文链接:https://www.cpweb.top/343 |
---|
ip netns 命令是用来管理 网络命名空间 的,网络命名空间可以实现 网络隔离。每个网络命名空间都提供了一个完全独立的网络协议栈,包括网络设备接口、IPV4 和 IPV6 协议栈、IP路由表、防火墙规则、端口、sockets 等。像 docker 就是利用 Linux 的网络命名空间来实现容器网络的隔离。
用法 | 含义 |
---|---|
ip netns list | 列出网络命名空间。此命令显示的是 “/var/run/netns” 中的所有网络命名空间。 |
ip netns add NAME | 添加网络命名空间 |
ip [-all] netns delete [NAME] | 删除网络命名空间 |
ip [-all] netns exec [NAME] cmd … | 在指定的网络命名空间中执行命令 |
ip netns set NAME NETNSID | 给网络命名空间分配id |
ip netns identify [PID] | 查看进程的网络命名空间 |
ip netns monitor | 监控对网络命名空间的操作 |
ip netns pids NAME | 查找使用此网络命名空间并将其作为主要网络命名空间的进程。此命令会从 /proc 目录中遍历。 |
添加并列出network space,随后删除所有的network space。
root@cp:~# ip netns add test1
root@cp:~# ip netns add test2
root@cp:~# ip netns ls
test2
test1
root@cp:~# ip -all netns del
root@cp:~# ip netns ls
创建的网络命名空间是可以在 /var/run/netns 路径下看到。
root@cp:~# cd /var/run/netns/
root@cp:/var/run/netns# ls
test1 test2
使用 exec 命令在网络命名空间中执行命令,查看 test1 的网卡信息
root@cp:~# ip netns exec test1 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
网络命名空间除了网络是虚拟的以外&#xff0c;文件系统完全和当前系统共享&#xff0c;也就是说所有本地可以使用的命令都可以在网络命名空间中使用。
root&#64;cp:~# ip netns exec test1 ls
app backup.tar cp1 perf.data registry_latest.tar test test_0.1.tar test-bind ubuntu-test.tar
root&#64;cp:~# ip netns exec test1 pwd
/root
进入网络命名空间可以用 exec 执行 bash 即可。
root&#64;cp:~# ip netns exec test1 bash
root&#64;cp:~# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
–all 选项可以在所有网络命名空间中执行命令。
root&#64;cp:~# ip -all netns exec ip anetns: test2
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00netns: test1
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
使用 ip netns set NAME NETNSID 给网络命名空间分配ID。该ID仅在当前网络命名空间中有效&#xff0c;如果指定了关键字“ auto”&#xff0c;则将会自动选择一个可用的nsid。内核将在某些 netlink 消息中使用此ID&#xff0c;如果在内核需要时未分配ID&#xff0c;则它将由内核自动分配。注意 ID 分配后&#xff0c;将无法更改。
root&#64;cp:~# ip netns add cp
root&#64;cp:~# ip netns
cp
root&#64;cp:~# ip netns set cp 6
root&#64;cp:~# ip netns
cp (id: 6)
使用 ip netns monitor 监控网络命名空间的添加和删除事件&#xff0c;只能监控添加和删除。
root&#64;cp:~# ip netns del cp
root&#64;cp:~# ip netns add cp
另一个终端同步反馈的
root&#64;cp:~# ip netns monitor
delete cp
add cp
以下两个示例以 docker 容器为例&#xff0c;在没做一些设置前&#xff0c;使用 ip netns 命令是无法管理分配给 docker 容器的网络命名空间&#xff0c;至于如何使用 ip netns 命令管理分配给容器的网络命名空间&#xff0c;下面扩展中有介绍到。在做下面示例时请先做好以下设置。
root&#64;cp:~# docker run -itd --name test centos
7ec02643b32d1c53b39126f6d603b72a402597d938ddef35e7bdb4076763c68f
root&#64;cp:~# ip netns list # 查看为空
root&#64;cp:~#
root&#64;cp:~# ln -s /proc/11421/ns/net /var/run/netns/test
root&#64;cp:~# ip netns list
test (id: 0)
使用 ip netns identify 命令查看容器 test 的网络命名空间。使用 ip netns pids 命令查找使用该网络命名空间的进程。
root&#64;cp:~# ip netns identify 11421
test
root&#64;cp:~# ip netns pids test
11421
创建一对 veth pair 虚拟网络设备接口&#xff0c;然后将其分别分配给两个网络命名空间&#xff0c;去连接两个网络命名空间。
注&#xff1a;veth-pair 是一对的虚拟网络设备接口&#xff0c;它都是成对出现的&#xff0c;所以它常常充当着一个桥梁&#xff0c;我们可以用它实现 “网络命名空间之间的连接”、“Docker 容器之间的连接” 、“Docker 容器和网桥间的连接” 等等。
root&#64;cp:~# ip link add name net1 type veth peer name net2
root&#64;cp:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000link/ether 00:0c:29:a9:42:0e brd ff:ff:ff:ff:ff:ffinet 192.168.18.25/24 brd 192.168.18.255 scope global noprefixroute ens33valid_lft forever preferred_lft foreverinet6 fe80::c75c:21df:8db2:598e/64 scope link noprefixroute valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:2c:d7:37:17 brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:2cff:fed7:3717/64 scope link valid_lft forever preferred_lft forever
19: net2&#64;net1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000link/ether e2:3c:d5:80:93:3c brd ff:ff:ff:ff:ff:ff
20: net1&#64;net2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000link/ether f2:f1:b8:34:4a:9a brd ff:ff:ff:ff:ff:ff
将两个虚拟接口迁移到对应的网络命名空间里。
root&#64;cp:~# ip link set net1 netns test1
root&#64;cp:~# ip link set net2 netns test2
root&#64;cp:~# ip -all netns exec ip anetns: test2
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
19: net2&#64;if20: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000link/ether e2:3c:d5:80:93:3c brd ff:ff:ff:ff:ff:ff link-netnsid 0netns: test1
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
20: net1&#64;if19: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000link/ether f2:f1:b8:34:4a:9a brd ff:ff:ff:ff:ff:ff link-netnsid 1
给两块网卡设置ip并启动
root&#64;cp:~# ip netns exec test1 ip addr add local 192.168.100.1/24 dev net1
root&#64;cp:~# ip netns exec test2 ip addr add local 192.168.100.2/24 dev net2
root&#64;cp:~# ip netns exec test1 ifconfig net2 up
root&#64;cp:~# ip netns exec test2 ifconfig net2 up
root&#64;cp:~# ip -all netns exec ip anetns: test2
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
19: net2&#64;if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000link/ether e2:3c:d5:80:93:3c brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 192.168.100.2/24 scope global net2valid_lft forever preferred_lft foreverinet6 fe80::e03c:d5ff:fe80:933c/64 scope link valid_lft forever preferred_lft forevernetns: test1
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
20: net1&#64;if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000link/ether f2:f1:b8:34:4a:9a brd ff:ff:ff:ff:ff:ff link-netnsid 1inet 192.168.100.1/24 scope global net1valid_lft forever preferred_lft foreverinet6 fe80::f0f1:b8ff:fe34:4a9a/64 scope link valid_lft forever preferred_lft forever
ping 测试通信
root&#64;cp:~# ip netns exec test1 ping 192.168.100.2
PING 192.168.100.2 (192.168.100.2) 56(84) bytes of data.
64 bytes from 192.168.100.2: icmp_seq&#61;1 ttl&#61;64 time&#61;0.275 ms
64 bytes from 192.168.100.2: icmp_seq&#61;2 ttl&#61;64 time&#61;0.047 ms
64 bytes from 192.168.100.2: icmp_seq&#61;3 ttl&#61;64 time&#61;0.043 ms
^C
--- 192.168.100.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2008ms
rtt min/avg/max/mdev &#61; 0.043/0.121/0.275/0.109 ms
当 docker 容器被创建出来后&#xff0c;你会发现使用 ip netns 命令无法看到容器对应的网络命名空间。这是因为 ip netns 命令是从 /var/run/netns 文件夹中读取内容的&#xff0c;而 docker 容器的网络命名空间不是在 /var/run/netns 下&#xff0c;而是位于 /proc/[pid]/ns/net。想要使用 ip netns 命令去管理 docker 容器的网络命名空间&#xff0c;就需要将它的网络命名空间显示在 /var/run/netns 目录下&#xff0c;那就要先找到容器的网络命名空间在哪里&#xff0c;然后做一个软链接即可。
首先查询容器的PID。
root&#64;cp:~# docker inspect --format &#39;{{.State.Pid}}&#39; web
4775
然后创建软链接&#xff0c;建议指定在 /var/run/netns/ 中的名字&#xff0c;因为每个容器都是net。
root&#64;cp:~# ln -s /proc/4775/ns/net /var/run/netns/web
root&#64;cp:~# ip netns ls
web (id: 0)
test2 (id: 2)
test1 (id: 1)
此时就可以用 ip netns 命令去管理 docker 容器的网络命名空间了。