Linux 复现Docker NAT网络
docker 网络的构成分为宿主机docker0网桥和为容器创建的veth 对构成。这个默认网络命名空间就是我们登陆后日常使用的命名空间
使用ifconfig
命令查看到的就是默认网络命名空间,docker0就是网桥,容器会把docker0当成路由,将流量发往docker0这个虚拟网桥上,然后docker0会走本地路由表发到你路由表上下一跳地址,如果当前层已经是物理机了就是路由器,如果你用的是虚拟机则就是你虚拟机的虚拟网桥,然后就是套娃
启动一个容器,我们再来看宿主机网络设备。从下图可以看到当我们启动redis容器后,本机网络设备新增了一个虚拟以太网设备veth9733c,容器redis02 ip为172.17.0.2,这个没有在本地网络设备中显示出来(在下文会讲这个地址在哪里出现),容器redis02进程id
命名空间
然后就是耳熟能详的词了——命名空间,docker 是利用linux命名空间实现的资源隔离。而容器redis02的ip地址也是存在于命名空间,linux veth类型网络设备总是成对出现,而这里只有一个veth设备是因为另一个peer在redis02的命名空间中.进入redis02网络命名空间的方法也很简单,就是利用redis02的进程id(pid). 使用nsenter -n --target 1281
进入。到这里docker 的nat网络就已经实现了,网关路由docker0, nat中的网络设备docker以bridge网络模式创建的容器
复现docker nat网络
用到的命令行工具:ip
,ifconfig
-
创建网桥:
ip link add dev br0 type bridge
ifconfig br0 172.20.0.1 netmask 255.255.255.0 broadcast 172.20.255.255
ip link set br0 up
-
创建网络命名空间
初始化netns
ip netns add one
将系统默认命名空间绑定到ip netns以供ip 命令操作
ln -s /proc/1/ns/net /var/run/netns/default
-
进入一个新的网络命名空间
unshare -n -f /usr/bin/zsh
-
在新网络命名空间中创建veth设备
创建一个veth 设备对,eth0放在当前命名空间, veth01放系统默认网络命名空间
ip link add dev eth0 type veth peer name veth01 netns default
将veth01连接到虚拟网桥br0,后面这个设备就会把br0当路由
ip netns exec default ip link set veth01 master br0
ifconfig eth0 172.20.0.2
ip link set eth0 up
ip netns exec default ip link set veth01 up
效果
命令空间内
命名空间外
在命名空间中使用redis-server /etc/redis/redis.conf --daemonize no
跑一个redis看看效果,可以看到宿主机6379是没有被监听的,但是通过命名空间创建的虚拟以太网设备的ip地址可以进去