What & Why
我们平时使用的 network interface 和 路由规则等是在整个操作系统共享的, 当然我们有些场景并想这样.
当这些共享的东西很多时, 我们想要分类和隔离, 让他们之间尽可能少的互相影响.
在 Linux 中, Network Namespace 正是我们需要的. 它提供了一个完全独立的网络协议栈, 包括了 network interface / IPv4 / IPv4 / 路由表 / iptables 等, 这个特性也是许多虚拟化和容器化技术的基础.
如何使用 Network Namespace
那么如果使用 Network Namespace 呢? 使用 ip 工具集.
查看帮助:ip netns help
Usage: ip netns list
ip netns add NAME
ip netns delete NAME
ip netns identify PID
ip netns pids NAME
ip netns exec NAME cmd ...
ip netns monitor
创建:ip netns add nstest1
在某 namespace 中执行命令:ip netns exec nstest1 <cmd>
或者, 进入 namespace 的 bash shellip netns exec nstest1 bash
创建之后, 通过 ip 命令可以看到里边只有一个 lo 设备:ip netns exec nstest1 ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
ip netns exec nstest1 ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
设备是可以转移到不同 namespace 的, 不过有些则不可以.
ethtool -k docker0 | grep netns |
如上, 如果 netns-local: on
则说明是不可转移的.
如何通信 & Veth Pair
创建了一些 Network Namespace, 理所当然的, 我们需要他们之间能够互相通信.
Linux 引入了 Veth Pair 来解决这个问题, 顾名思义, veth 是成对出现的, 好比一对用网线连着的网卡, 用来连接两个 namespace.
接下来我们来实际操作一下.
创建 veth pair:$ ip link add vethtest0 type veth peer name vethtest1
$ sudo ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
...
5: vethtest1@vethtest0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether ba:97:41:e5:5e:4b brd ff:ff:ff:ff:ff:ff
6: vethtest0@vethtest1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether de:56:07:73:83:f1 brd ff:ff:ff:ff:ff:ff
如上, 我们可看到当前 namespace 中已经创建了两个 veth .
如果我们要让 root namespace 和 nstest1 namespace 之间能够通信, 我们需要把 veth pair 中的一个放到 nstest1 中:
ip link set vethtest1 netns nstest1 |
可以看到 vethtest1 已经被移至其他 nstest1 namespace, 但是 index id 是保留的.
# |
分配 IP 给 vethtest1 :
-> % sudo ip netns exec nstest1 ip addr add 10.1.2.1/24 dev vethtest1 |
分配 IP 给 vethtest0 :
-> % sudo ip addr add 10.1.2.2/24 dev vethtest0 |
启动 veth:
-> % sudo ip netns exec nstest1 ip link set dev vethtest1 up |
现在可以互相通信了.
-> % ping 10.1.2.1 |
以上就是 Linux Network Namespace 和 Veth Pair 的概要, 也是了解 Docker 和 Kubernetes 的网络实现时需要的基础知识.