容器网络最典型的基础模型 —— 两个不同的命名空间通过 bridge 通信 。
Docker 默认的 bridge 模式就是基于此原理,创建 docker0 bridge,容器 veth 对一端连接容器,一端连接 docker0,提供 NAT 功能让容器可以访问外网。
一个简单的结构如下👇:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| +---------------------+
| root NS | (宿主机 / default netns)
| bridge: br0(10.0.0.254/24)
| |
| veth0 ─────────┐ | <- veth0 在 root,master=br0
| │ |
| veth2 ─────────┴──┘ <- veth2 在 root,master=br0
+---------------------+
│
┌─────────────────┴─────────────────┐
│ │
veth0 <-> veth1 veth2 <-> veth3
(root, peer) (in ns1) (root, peer) (in ns2)
ns1 namespace ns2 namespace
┌───────────────┐ ┌───────────────┐
│ veth1 │ │ veth3 │
│ 10.0.0.1/24 │ │ 10.0.0.2/24 │
└───────────────┘ └───────────────┘
|
虚拟以太网设备,总是成对出现,类似管道两端
- 一端发送的数据会在另一端接收到
- 主要用途:连接不同网络命名空间,实现网络隔离环境间的通信
- 虚拟交换机,工作在数据链路层(二层)
- 可以连接多个网络接口,在它们之间转发数据帧
- Linux bridge 支持 STP、VLAN 等交换机构造特性
- 提供完全隔离的网络栈,包括接口、路由表、iptables 规则等
- 每个容器通常运行在独立的网络命名空间中
实现步骤如下:
(1)创建两个命名空间
1
2
| ip netns add ns1
ip netns add ns2
|
(2)创建两对 veth
每个命名空间各分配一个端口。
1
2
| ip link add veth0 type veth peer name veth1
ip link add veth2 type veth peer name veth3
|
现在有:
1
2
| veth0 <-> veth1
veth2 <-> veth3
|
(3)veth1 和 veth3 移入命名空间
1
2
| ip link set veth1 netns ns1
ip link set veth3 netns ns2
|
(4)创建 bridge(虚拟交换机)
1
2
| ip link add name br0 type bridge
ip link set br0 up
|
(5)把宿主机侧的 veth(veth0、veth2)加入 bridge
1
2
3
4
| ip link set veth0 master br0
ip link set veth2 master br0
ip link set veth0 up
ip link set veth2 up
|
(6)配置命名空间内部 IP
ns1:
1
2
| ip netns exec ns1 ip addr add 10.0.0.1/24 dev veth1
ip netns exec ns1 ip link set veth1 up
|
ns2:
1
2
| ip netns exec ns2 ip addr add 10.0.0.2/24 dev veth3
ip netns exec ns2 ip link set veth3 up
|
测试一下连通性:
1
| ip netns exec ns1 ping 10.0.0.2
|
如果一切正常,应该能 ping 通,因为这两个 namespace 的 " 网线 " 都插在同一个虚拟交换机 br0 上。
(7)让宿主机也能参与通信
给宿主机也分配 ip 在同一个网段:
1
| ip addr add 10.0.0.254/24 dev br0
|
然后:
1
| ip netns exec ns1 ping 10.0.0.254
|
也能通。这样,通过 veth pair + bridge + netns,可以模拟 Docker 那样是如何搭建一个多容器虚拟局域网。