Linux Network Namespace(网络名称空间)介绍、应用 及 详细的互通案例
- 1、Network Namespace 介绍
- 2、Network Namespace 之间的通信
-
- 2.1 使用 veth pair 实现不同网络名称空间的互通
- 2.2 使用 bridge 实现不同网络名称空间的互通
1、Network Namespace 介绍
1.1 基本概念
Network Namespace 是实现网络虚拟化的重要功能,它能创建多个隔离的网络空间,它们有独自的网络栈信息。不管是虚拟机还是容器,运行的时候仿佛自己就在独立的网络中。
Network Namespace 是 Linux 内核提供的功能,可以借助 IP 命令来完成各种操作。IP 命令来自于 iproute2 安装包,一般系统会默认安装。
[root@Tang ~]# yum info iproute
Installed Packages
Name : iproute
Arch : x86_64
Version : 4.11.0
Release : 14.el7
Size : 1.7 M
Repo : installed
From repo : anaconda
Summary : Advanced IP routing and network device configuration tools
URL : http://kernel.org/pub/linux/utils/net/iproute2/
License : GPLv2+ and Public Domain
Description : The iproute package contains networking utilities (ip and rtmon, for example)
: which are designed to use the advanced networking capabilities of the Linux
: kernel.
1.2 命令帮助 Network Namespace
IP 命令管理的功能很多, 和 Network Namespace 有关的操作都是在子命令 ip netns 下进行的,可以通过 ip netns help 查看所有操作的帮助信息。
[root@Tang ~]# ip netns help
Usage: ip netns list
ip netns add NAME
ip netns set NAME NETNSID
ip [-all] netns delete [NAME]
ip netns identify [PID]
ip netns pids NAME
ip [-all] netns exec [NAME] cmd ...
ip netns monitor
ip netns list-id
1.3 创建 Network Namespace 及后续相关命令操作
使用如下命令进行网络名称空间添加:
[root@Tang ~]# ip netns add neo
[root@Tang ~]# ip netns list
neo
ip netns 命令创建的 Network Namespace 会出现在 /var/run/netns/
目录下,如果需要管理其他不是 ip netns 创建的 Network Namespace,只要在这个目录下创建一个指向对应 Network Namespace 文件的链接就行。
[root@Tang ~]# ll /var/run/netns/
total 0
-r--r--r--. 1 root root 0 Nov 19 13:46 neo
有了自己创建的 Network Namespace,我们还需要看看它里面的具体配置。
对于每个 Network Namespace 来说,它会有自己独立的网卡、路由表、ARP 表、iptables 等和网络相关的资源。
1.3.1 ip netns exec 说明
ip 命令提供了 ip netns exec 子命令可以在对应的 Network Namespace 中执行命令。 比如,使用如下命令查看网络名称空间 neo 中查看:
[root@Tang ~]# ip netns exec neo ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
在使用 ip netns exec NAME 执行 bash 命令了之后,后面所有的命令都是在这个 Network Namespace 中执行的。此操作:
- 同一名称空间下的命令执行,不用每次都输入 ip netns exec NAME
- 无法清楚知道自己当前所在的 shell,容易混淆(使用 exit 退出)
- 但是通过修改 bash 的前缀信息可以区分不同 shell
[root@Tang ~]# ip netns exec neo bash # 进入到名称空间 neo 的 bash
[root@Tang ~]# ip addr list # 此后执行的命令都是在此名称空间下执行的
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[root@Tang ~]# exit # 退出此名称空间的 bash
exit
[root@Tang ~]# ip addr list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether e4:3a:6e:0a:9b:88 brd ff:ff:ff:ff:ff:ff
inet 172.16.141.252/24 brd 172.16.141.255 scope global noprefixroute enp1s0
[root@Tang ~]# ip netns exec neo /bin/bash --rcfile <(echo "PS1=\"namespace neo> \"")
namespace neo> ip addr list # shell 名称已修改
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
namespace neo> exit # 退出后失效,重新进入时,需要再次修改 shell 名称
exit
[root@Tang ~]# ip netns exec neo bash
[root@Tang ~]# ip addr list
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[root@Tang ~]# exit
exit
1.3.2 新创建名称空间启动 lo 接口
每个 namespace 在创建的时候会自动创建一个 lo 的 interface,它的作用和 linux 系统中默认看到的lo 一样,都是为了实现 loopback 通信。如果希望 lo 能工作,需要进行启动。
[root@Tang ~]# ip netns exec neo ip link set lo up
[root@Tang ~]# ip netns exec neo ip addr list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
2、Network Namespace 之间的通信
默认情况下,network namespace 是不能和主机网络,或者其他 network namespace 通信的。
2.1 使用 veth pair 实现不同网络名称空间的互通
有了不同 network namespace 之后,也就有了网络的隔离,但是如果它们之间没有办法通信,也没有实际用处。要把两个网络连接起来,linux 提供了 veth pair 。可以把 veth pair 当做是双向的 pipe(管道),从一个方向发送的网络数据,可以直接被另外一端接收到;或者也可以想象成两个 namespace 直接通过一个特殊的虚拟网卡连接起来,可以直接通信。
2.1.1 创建一个新的名称空间,进行试验
[root@Tang ~]# ip netns add tang
[root@Tang ~]# ip netns list
tang
neo
2.1.2 创建一对 veth pair
使用 ip link add type veth 来创建一对 veth pair 出来,需要记住的是 veth pair 无法单独存在,删除其中一个,另一个也会自动消失。如下:
[root@Tang ~]# ip link
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:a3:89:ef:df brd ff:ff:ff:ff:ff:ff
5: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether de:ee:db:c3:26:f1 brd ff:ff:ff:ff:ff:ff
6: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether a6:23:e6:80:cc:7f brd ff:ff:ff:ff:ff:ff
[root@Tang ~]# ip link del veth0 type veth
[root@Tang ~]# ip link
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:a3:89:ef:df brd ff:ff:ff:ff:ff:ff
创建 veth pair 时,可以指定名称,也可以使用其默认名称。
如果 pair 的一端接口处于 DOWN 状态,另一端能自动检测到这个信息,并把自己的状态设置为NO-CARRIER。
ip link 是有 iproute2 家族中的操作命令,关于此家族的详细命令解释,可参照以下博客链接。
Linux iproute2 命令家族(ip / ss)
2.1.2.1 创建 veth pair ,使用系统默认名称
[root@Tang ~]# ip link add type veth
[root@Tang ~]# ip link
5: veth0@veth1: <BROADCAST,MULTICAST