七天用Go写个docker(网络篇)
0.docker 网络实现#
docker 网络分为两部分,一部分是 docker 与宿主机之间的通信,另一部分是 docker 与外部网络之间的通信。docker 与宿主机之间的通信是通过 veth 和 bridge 虚拟网络接口实现的,而与外部网络通信是通过 iptables 流量转发实现的。
1. veth 和 bridge#
veth 是一个虚拟的网络设备,它都是成对出现的,你可以把它理解成马里奥里面的水管,马里奥从一个水管进去,会从另一个水管里面出来,在这里,马里奥就是流量,这两个水管就是一对 veth,我们看下实际操作
先创建两个网络 namespace
ip netns add ns1 ip netns add ns2
创建一对 Veth
ip link add veth1 type veth peer name veth2
为网络 ns1 和 ns2 设置 veth
ip link set veth1 netns ns1 ip link set veth2 netns ns2
设置 veth1、veth2 的网络地址
ip netns exec ns1 ifconfig veth1 172.15.0.1/24 up ip netns exec ns2 ifconfig veth2 172.15.0.2/24 up
将 ns1 的流量默认从 veth1 中流出
default 代表 0.0.0.0/0 即在 ns1 中的流量都经过 veth1 的网络设备流出
ip netns exec ns1 route add default dev veth1
通过上面 5 步,我们就将一头水管(veth1)安在了 ns1 上,另一头水管(veth2)安在了 ns2 上,并且设置了 ns1 的流量从 veth1 中流出,这样从 ns1 里面流出的流量都会经过 veth1 流向 veth2, 也就是流到 ns2 上。这样就实现了 ns1 和 ns2 的网络互通。
测试一下,我们在 ns1 中去 ping ns2 的 ip 地址看是否可以 ping 通
可以看到,已经完全可以 ping 通了,证明通过 veth 我们已经将这两个隔离的 namespace 的网络打通了。
bridge#
bridge 也就是网桥,它是一个非常简单的玩意,你可以把它理解成一个交换机,只不过它只有两个口,并且是一个虚拟的网络设备。
- 创建一个网桥
brctl addbr br0
- 挂载网络设备
brctl addif br0 eth0 brctl addif br0 veth1
- 配置路由规则我们将网桥 br0 一端挂在了 eth0 网卡上,另一端挂在了 veth1 上这样流量就能从宿主机流到我们的隔离的 ns1 上
# 将宿主机上的某个网段请求路由到br0的网桥上 route add –net 172.15.0.2/24 dev br0
2. iptables#
解决了容器的 namesepace 与宿主机之间的通信,我们看下如何解决 ns 与外部网络的通信,我们知道,ns 的 ip 地址是我们自己定义的,这样当 ns 去访问外部网络时,外部网络是不认识这个请求包里面的源地址的,而外部网络也没办法去访问我们 ns 里面的 ip 地址,因为它只认识我们宿主机的 ip 地址。这时我们就需要用到 iptables 了。
2.1 MASQUERADE#
iptables 中的 MASQUERADE 功能可以帮助我们更改请求包的源地址,这样当 ns 请求外部网络时,我们把源地址改成我们宿主机的是不是就可以了,看下实际配置:
- 打开 ip 转发
sysctl -w net.ipv4.conf.all.forwarding=1
- 对 ns1 中发出的包添加地址转换(更换源地址)
iptables -t nat -A POSTROUTING -s 172.15.0.0/24 -o eth0 -j MASQUERADE
2.2 DNAT#
iptables 中的 DNAT 功能可以修改我们请求包的目的地址,并将请求转发到我们目的地址上面,这样当外部网络访问我们宿主机的某个端口时,我们将该包的目标地址改成我们 ns 的地址,直接转发到我们 ns 里面是不是就可以了,看下实际配置:
将宿主机上 80 端口的请求转发到 ns1 的 ip 上
iptables -t nat -A POSTROUTING -p tcp —dport 80 -j DNAT —to destination 172.15.0.1:80
附言#
以上内容都是我自己的理解,如果理解的有偏差欢迎大家一起留言讨论,针对
iptables
我后续会出一系列教程教大家如何使用这个神器,后续文章都会首发于我微信公众号,欢迎大家关注
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: