linux虚拟网络技术-docker网络底层原理

linux虚拟网络技术-docker网络底层原理

网络技术
linux网络虚拟化技术
linux实际是通过网络设备去操作和使用网卡的。
系统安装了一个网卡之后会为其生成一个网络设备实例。eth0
虚拟设备:Veth,bridge,802.1.q VLAN device,TAP

linux veth
Veth是成对出现的虚拟网络设备,发送到Veth一端虚拟设备的请求会从另一端虚拟设备中发出。
在容器中,通过veth连接不同网络namespace。

创建两个虚拟网络
sudo ip netns add ns1
sudo ip netns add ns2

创建一对veth
sudo ip link add veth0 type veth peer name veth1

分别将两个veth移动到两个namespace中
sudo ip link set veth0 netns ns1
sudo ip link set veth1 netns ns2

查看
sudo ip netns exec ns1 ip link

1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
6: veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 0a:2e:25:bf:e9:d5 brd ff:ff:ff:ff:ff:ff

配置每个veth的网络地址和namespace的路由
sudo ip netns exec ns1 ifconfig veth0 172.18.0.2/24 up
sudo ip netns exec ns2 ifconfig veth1 172.18.0.3/24 up
sudo ip netns exec ns1 route add default dev veth0
sudo ip netns exec ns2 route add default dev veth1

测试
sudo ip netns exec ns1 ping -c 1 172.18.0.3

linux bridge
可以理解为是现实世界的交换机,可以连接不同的网络设备,当请求到达bridge设备时,可以通过报文中的mac地址进行广播或转发。

创建一个bridge设备,来连接namespace中的网络设备和宿主机上的网络。

安装软件
sudo apt-get install bridge-utils

sudo ip netns add ns5
sudo ip link add veth6 type veth peer name veth5

sudo ip link set veth5 setns ns5

sudo brctl addbr br5

sudo brctl addif br5 eth0
sudo brctl addif br5 veth6

linux路由表
内核模块,定义路由表来决定在某个网络namespace中包的流向,从而定义请求会到哪个网络设备上。

sudo ip link add veth10 type veth peer name veth11

sudo ip link set veth10 up

sudo brctl addbr br10
sudo ip link set br10 up

sudo ip netns add ns11
sudo ip link set veth11 netns ns11
sudo ip netns exec ns11 ifconfig veth11 172.18.0.22/24 up

docker如何实现外部访问容器内部?原理篇
linux iptables
iptables是对linux内核的netfilter模块进行操作和展示的工具。
用于管理包流动和转送。
iptables定义了一套链式处理的结构。
在网络包传输的各个阶段可以使用不同的策略对包进行加工,传送或丢弃。
容器化通常使用:MASQUERADE和DNAT,用于容器和宿主机外部的网络通信。

MASQUERADE
可以将请求包中的源地址转换成一个网络设备的地址。

比如:namespace中的网络设备的地址:172.18.0.2
这个地址虽然在宿主机上可以路由到br0的网桥上。
但是到达宿主机外部之后,是不知道如何路由到这个ip地址的
如果请求外部地址的话,需要先通过MASQUERADE策略将这个ip转换成宿主机出口网卡IP

打开ip转发
sudo sysctl -w net.ipv4.conf.all.forwarding=1

对namespace中发出的包添加网络地址转化
sudo iptables -t nat -A POSTROUTING -s 172.18.0.0/24 -o eth0 -j MASQUERADE

这样在namespace中请求宿主机外部地址时,将namespace中源地址转换成宿主机的地址作为源地址,就可以在namespace中访问宿主机外的网络了。

DNAT
iptables中的DNAT也是做网络地址转换的。
它是更换目标地址。
经常用于将内部网络地址的端口映射到外部去。
sudo iptables -t nat -A PREROUTING -p tcp -m tcp –dport 80 -j DNAT –to-destination 172.18.0.2:80

上面的例子
namespace如果需要提供服务给宿主机之外的应用去请求,外部无法访问172.18.0.2地址。
通过DNAT策略,将宿主机的80端口的TCP请求转发到namespace中的地址172.18.0.2:80
从而实现外部应用调用。

go语言网络库如何实现?

net库

github.com/vishvananda/netlink库
操作网络接口,路由表等配置的库
使用它相当于使用ip命令

github.com/vishvananda/netns库
实现了ip netns exec进入容器的net namespace中执行网络配置

发表评论