您好,欢迎来到华佗健康网。
搜索
您的当前位置:首页Docker网络原理分析

Docker网络原理分析

来源:华佗健康网
Docker网络原理分析

Docker网络原理分析

Docker使用linux的bridge和veth虚拟网络设备,以及network namespace对网络进行虚拟化。Bridge看其名字是网桥,但实际上它的功能和交换机(switch)相似。Veth则是一对网络接口,像是用一条网线连接起来的两块网卡。阅读这篇文章前,应该先了解linux的bridge和veth的原理和用法,熟悉brctl, ip, iptables三个重要命令的使用方法。

一、Docker 经典网络架构:

从上图可知,每个docker容器通过一对veth连入bridge br0。Veth 的一端在docker netns中,通常改名为eth0;另一端在default或global netns中,通常命名为vethXXXXXXXX。上图中将其命名为vnic11和vnic21。

Bridge br0自带一个网络接口,相当于主机的一张网卡,它的名字也叫br0。上图相当于一个bridge br0连接了三台机器:host,docker1,docker2,它们形成了一个的LAN。而主机的eth0则将主机连接到外部的交换机,和交换上的其它主机形成一个LAN。

现在配置网络的IP:

Host的eth0:将主机连接到外部交换机。Ip=192.168.1.181/24, 主机的网关为192.168.1.1 dev eth0。

Host的br0网络接口: 将主机连接到内部交换机br0。Ip=10.0.0.1/16。注意,当同时为主机的eth0和br0设置IP时,它俩不能处于同一网段。

Docker1的eth0:将docker1连接到交换机br0。Ip=10.0.0.100/16。Docker1 网关为10.0.0.1。

Docker2的eth0:将docker2连接到交换机br0。Ip=10.0.0.200/16。Docker2 网关为10.0.0.1。

这样docker1,docker2以及host所形成的LAN就配置好了,它的网段为10.0.0.0/16。现在,docker1、docker2以及主机,这三台

设备可以正常通信了。

那么,docker1和docker2如何才能访问host以外的世界呢?答案是NAT。也就是需要配置转发机制,在网络接口host:br0和host:eth0之间转发数据包。配置转发机制首先要开启linux的网络转发功能,然后要在iptables中配置SNAT源地址转换。

上面就是docker默认使用的网络模式(--net=bridge)。Docker daemon一启动,就会创建bridge,不过名字叫做docker0。并将网口docker0的IP配成了172.17.0.1/16。以后每启动一个容器,就自动为该容器创建veth pair,将一端连到bridge docker0,将另一端放入容器内,改名为eth0。容器内的eth0的ip配置为172.17.x.x/16,容器的网关配置为172.17.0.1。

下面,我们用命令一步一步创建该网络,以加深对docker网络原理的理解。

1.启动两个docker容器,不要让docker自动配置网络

docker run –itd --name=docker1 --net=none test/ubuntu:14 /bin/bash

docker run –itd --name=docker2 --net=none test/ubuntu:14 /bin/bash

2.找到容器的netns,将其连接到/var/run/netns/下,以便为其配

置网卡。

先找到docker容器的PID: docker1Pid=$(docker format=’{{.State.Pid}}’docker1)

docker2Pid=$(docker format=’{{.State.Pid}}’docker2)

再将docker容器的net namespace链接到/var/run/netns/: mkdir /var/run/netns #如果没有该目录,先创建。

ln –s /proc/$docker1Pid/ns/net /var/run/netns/docker1ns ln –s / proc/$docker1Pid/ns/net /var/run/netns/docker2ns 现在,就

inspect

–-inspect

–-

可以查看一下这两个net namespace中的连接情况:

ip netns exec docker1ns ip link list 3.创建网桥和虚拟网卡 brctl addbr br0

ip link add vnic11 type veth peer name vnic12 ip link add vnic21 type veth peer name vnic22 ip link list #查看所有link

将vnic11和vnic21 attach到网桥br0: brctl addif br0 vnic11 brctl addif br0 vnic21

4.把vnic12和vnic22分别放入docker1ns和docker2ns,并重命名

为eth0

ip link set vnic12 netns docker1ns ip link set vnic22 netns docker2ns

ip netns exec docker1ns ip link set vnic12 name eth0 ip netns exec docker2ns ip link set vnic22 name eth0 5.为网口br0, docker1ns:eth0, docker2ns:eth0配置IP ip addr add 10.0.0.1/16 dev br0

ip netns exec docker1ns ip addr add 10.0.0.100/16 dev eth0 ip netns exec docker1ns ip link set eth0 up

ip netns exec docker1ns ip route add default via 10.0.0.1 ip netns exec docker2ns ip addr add 10.0.0.200/16 dev eth0 ip netns exec docker2ns ip link set eth0 up

ip netns exec docker2ns ip route add default via 10.0.0.1 注意,必须先激活网口,才能配置网关。

6.启动所有网口 ip link set br0 up ip link set vnic11 up ip link set vnic21 up

至此,docker1,dockr2和主机可以相互通信了。 7.开启linux的转发功能: sysctl –w net.ipv4.ip_forward=1, 或者

echo 1 > /proc/sys/net/ipv4/ip_forward

这样,当从br0收到包后,若目的地址不是host,则选择合适的网络接口(如eth0)发出去。从eth0收到包后,也会按一样的规则做转发处理。

8.配置SNAT, 将从docker来的包的源地址改为192.168.1.181 iptables –t nat –A POSTROUTING –s 10.0.0.100 –j SNAT --to 192.168.1.181

iptables –t nat –A POSTROUTING –s 10.0.0.200 –j SNAT --to 192.168.1.181

至此,docker1和docker2就可以ping通host以外的世界了。可以尝试一下:

docker attach docker1

ping 192.168.1.185 #到你的LAN中的其它机器。

要想暂时离开(detach)docker容器,连续按Ctrl+p, Ctrl+q。 下次还可以attach。注意,不要用exit命令,exit会关闭容器,前面为容器所做的修改都会消失。

9.配置DNAT, 将docker容器内的某个端口对外开放,允许主机外的

程序访问docker容器内的服务:

iptables –t nat –A PREROUTING –d 192.169.1.181 –p tcp –-dport 8080 –j DNAT –-to 10.0.0.200:80

至此,有人通过tcp协议访问192.168.1.181:8080时192.168.1.181:8080,linux会将其映射到docker2的80端口,即10.0.0.200:80。

二、将docker容器加入本地网络(和主机在同一网段192.168.1.0/24)要将docker容器加入本地网络,即让docker容器

和host处于同一网段(192.168.1.0/24),需要把虚拟交换机(bridge br1)与外部交换级联,形成一个广播域。级联的方法是:把host:eth0直接attach 到bridge br1。这样一来,host:eth0就不是host的有效网口了,故需要删除host:eth0的ip,而要把host的ip设到网口br1上。另外,host的网关也要用dev br1。按照上述网络拓扑,IP设置如下:

host:eth0: 删除其IP,将其直接连接到网桥br1。

br1网口:设置为eth0原来的IP,即192.168.1.181/24。主机的网关还是192.168.1.1,但访问外部的网口要换为br1。

docker3:eth0:ip为192.168.1.185, 网关为192.168.1.1。 docker4:eth0:ip为192.168.1.186,网关为192.168.1.1。 下面,我们用命令一步一步创建该网络。

1.启动两个docker容器,不要让docker自动配置网络

docker run –itd --name=docker3 --net=none test/ubuntu:14 /bin/bash

docker run –itd --name=docker4 --net=none test/ubuntu:14 /bin/bash

2.找到容器的netns,将其连接到/var/run/netns/下,以便为其配

置网卡。

先找到docker容器的PID: docker3Pid=$(docker format=’{{.State.Pid}}’docker3)

docker4Pid=$(docker format=’{{.State.Pid}}’docker4)

再将docker容器的net namespace链接到/var/run/netns/: mkdir /var/run/netns #如果没有该目录,先创建。

ln –s /proc/$docker3Pid/ns/net /var/run/netns/docker3ns ln –s / proc/$docker4Pid/ns/net /var/run/netns/docker4ns 现在,就可以查看一下这两个net namespace中的连接情况:

inspect

–-inspect

–-

ip netns exec docker4ns ip link list 3.创建网桥和虚拟网卡 brctl addbr br1

ip link add vnic31 type veth peer name vnic32 ip link add vnic41 type veth peer name vnic42 ip link list #查看所有link

将vnic31和vnic41 attach到网桥br1: brctl addif br1 vnic31 brctl addif br1 vnic41

4.把vnic32和vnic42分别放入docker3ns和docker4ns,并重命名

为eth0

ip link set vnic32 netns docker3ns ip link set vnic42 netns docker4ns

ip netns exec docker3ns ip link set vnic32 name eth0 ip netns exec docker4ns ip link set vnic42 name eth0 5.为网口docker3ns:eth0, docker4ns:eth0配置IP和网关 ip netns exec docker3ns ip addr add 192.168.1.183/24 dev eth0

ip netns exec docker3ns ip link set eth0 up

ip netns exec docker3ns ip route add default via 192.168.1.1 ip netns exec docker4ns ip addr add 192.168.1.184/24 dev eth0

ip netns exec docker4ns ip link set eth0 up

ip netns exec docker4ns ip route add default via 192.168.1.1 注意,必须先激活网口,才能配置网关。 6.启动所有网口 ip link set br1 up ip link set vnic31 up ip link set vnic41 up

7.配置主机的IP和网关

需要删除eth0的IP,配置br1的IP,并把网关配置到网口br1。如果是远程操作,必须用一条命令完成,因为更换网口IP时会断网。

ip addr del 192.168.1.181/24 dev eth0; \\ ip addr add 192.168.1.181/24 dev br1; \\ ip route del default; \\

ip route add default via 192.168.1.1 dev br1; \\ brctl addif br1 eth0

上述命令执行完成后,可能需要重新登录到192.168.1.181。 至此,docker1,dockr2以及host都成为LAN上的一员了。 注意:如果host是一台VirtualBox VM,那么,必须将VM的虚拟

Adapter

Type

PCnet-Fast

III(Am79c973),Promiscuous Mode设为Allow All。否则,VM的虚拟网卡只会让带有自己的MAC地址的包通过,而docker3:eth0和docker4:eth0由于有自己的MAC,它们的包会被过滤掉。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo0.com 版权所有 湘ICP备2023021991号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务