设为首页 收藏本站
查看: 1466|回复: 0

[经验分享] docker网络模式

[复制链接]

尚未签到

发表于 2018-5-27 13:38:50 | 显示全部楼层 |阅读模式
  docker 在早前的时候没有考虑跨主机的容器通信,这个特性直到 docker 1.9 才出现。在此之前,如果希望位于不同主机的容器能够通信,一般有几种方法:

  •   1、使用端口映射:直接把容器的服务端口映射到主机上,主机直接通过映射出来的端口通信
  •   2、把容器放到主机所在的网段:修改 docker 的 ip 分配网段和主机一致,还要修改主机的网络结构
  •   3、第三方项目:flannel,weave 或者 pipework 等,这些方案一般都是通过 SDN 搭建 overlay 网络达到容器通信的
  随着 docker 1.9 的发布,一个新的网络模型被开发出来。除了能更方便地按照需求来搭建自己的网络方案,这次发布还让 docker 具备了跨主机通信的功能。
  一、我们先简单的说一下早期的主机内部容器通信的四种网络模式:
     1 host模式
     众所周知,Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
例如,我们在10.10.101.105/24的机器上用host模式启动一个含有web应用的Docker容器,监听tcp80端口。当我们在容器中执行任何类似ifconfig命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用10.10.101.105:80即可,不用任何NAT转换,就如直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
     2 container模式
     在理解了host模式后,这个模式也就好理解了。这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
     3 none模式
     这个模式和前两个不同。在这种模式下,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
     4 bridge模式
     bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。
    DSC0000.jpg
     二、第三方的跨主机通信以pipwork和flannel为例
     2.1 pipwork

     pipework是由Docker的工程师Jérme Petazzoni开发的一个Docker网络配置工具,由200多行shell实现,方便易用。下面用三个场景来演示pipework的使用和工作原理。


  为了使本地网络中的机器和Docker容器更方便的通信,我们经常会有将Docker容器配置到和主机同一网段的需求。这个需求其实很容易实现,我们只要将Docker容器和主机的网卡桥接起来,再给Docker容器配上IP就可以了。
  下面我们来操作一下,我主机A地址为10.10.101.105/24,网关为10.10.101.254,需要给Docker容器的地址配置为10.10.101.150/24。在主机A上做如下操作:
安装pipework
git clone https://github.com/jpetazzo/pipework
cp ~/pipework/pipework /usr/local/bin/
启动Docker容器。
docker run -itd --name test1 ubuntu /bin/bash
配置容器网络,并连到网桥br0上。网关在IP地址后面加@指定。
若主机环境中存在dhcp服务器,也可以通过dhcp的方式获取IP
pipework br0 test1 dhcp
pipework br0 test1 10.10.101.150/24@10.10.101.254
将主机eth0桥接到br0上,并把eth0的IP配置在br0上。这里由于是远程操作,中间网络会断掉,所以放在一条命令中执行。
ip addr add 10.10.101.105/24 dev br0;
ip addr del 10.10.101.105/24 dev eth0;
brctl addif br0 eth0;
ip route del default;
ip route add default gw 10.10.101.254 dev br0
完成上述步骤后,我们发现Docker容器已经可以使用新的IP和主机网络里的机器相互通信了。
pipework工作原理分析
那么容器到底发生了哪些变化呢?我们docker attach到test1上,发现容器中多了一块eth1的网卡,并且配置了10.10.101.150/24的IP,而且默认路由也改为了10.10.101.254。这些都是pipework帮我们配置的。通过查看源代码,可以发现pipework br0 test1 10.10.101.150/24 @10.10.101.254是由以下命令完成的(这里只列出了具体执行操作的代码)。
创建br0网桥
若ovs开头,则创建OVS网桥 ovs-vsctl add-br ovs*
brctl addbr $IFNAME
创建veth pair,用于连接容器和br0
ip link add name $LOCALIFNAME mtu $MTU type veth peer name $GUESTIFNAME mtu $MTU
找到Docker容器test1在主机上的PID,创建容器网络命名空间的软连接
DOCKERPID=$(docker inspect --format='` `.`State`.`Pid `' $GUESTNAME)
ln -s /proc/$NSPID/ns/net /var/run/netns/$NSPID
将veth pair一端放入Docker容器中,并设置正确的名字eth1
ip link set $GUESTIFNAME netns $NSPID
ip netns exec $NSPID ip link set $GUESTIFNAME name $CONTAINER_IFNAME
将veth pair另一端加入网桥
若为OVS网桥则为 ovs-vsctl add-port $IFNAME $LOCAL_IFNAME ${VLAN:+"tag=$VLAN"}
brctl addif $IFNAME $LOCAL_IFNAME
为新增加的容器配置IP和路由
ip netns exec $NSPID ip addr add $IPADDR dev $CONTAINERIFNAME
ip netns exec $NSPID ip link set $CONTAINERIFNAME up
ip netns exec $NSPID ip route
delete default ip netns exec $NSPID ip route add $GATEWAY/32 dev $CONTAINER_IFNAME

  •   首先pipework检查是否存在br0网桥,若不存在,就自己创建。若以"ovs"开头,就会创建OpenVswitch网桥,以"br"开头,创建Linux bridge。
  •   创建veth pair设备,用于为容器提供网卡并连接到br0网桥。
  •   使用docker inspect找到容器在主机中的PID,然后通过PID将容器的网络命名空间链接到/var/run/netns/目录下。这么做的目的是,方便在主机上使用ip netns命令配置容器的网络。因为,在Docker容器中,我们没有权限配置网络环境。
  •   将之前创建的veth pair设备分别加入容器和网桥中。在容器中的名称默认为eth1,可以通过pipework的-i参数修改该名称。
  •   然后就是配置新网卡的IP。若在IP地址的后面加上网关地址,那么pipework会重新配置默认路由。这样容器通往外网的流量会经由新配置的eth1出去,而不是通过eth0和docker0。(若想完全抛弃自带的网络设置,在启动容器的时候可以指定--net=none)
以上就是pipework配置Docker网络的过程,这和Docker的bridge模式有着相似的步骤。事实上,Docker在实现上也采用了相同的底层机制。
通过源代码,可以看出,pipework通过封装Linux上的ip、brctl等命令,简化了在复杂场景下对容器连接的操作命令,为我们配置复杂的网络拓扑提供了一个强有力的工具。当然,如果想了解底层的操作,我们也可以直接使用这些Linux命令来完成工作,甚至可以根据自己的需求,添加额外的功能。
单主机Docker容器VLAN划分
pipework不仅可以使用Linux bridge连接Docker容器,还可以与OpenVswitch结合,实现Docker容器的VLAN划分。下面,就来简单演示一下,在单机环境下,如何实现Docker容器间的二层隔离。
为了演示隔离效果,我们将4个容器放在了同一个IP网段中。但实际他们是二层隔离的两个网络,有不同的广播域。
在主机A上创建4个Docker容器,test1、test2、test3、test4
docker run -itd --name test1 ubuntu /bin/bash
docker run -itd --name test2 ubuntu /bin/bash
docker run -itd --name test3 ubuntu /bin/bash
docker run -itd --name test4 ubuntu /bin/bash
将test1,test2划分到一个vlan中,vlan在mac地址后加@指定,此处mac地址省略。
pipework ovs0 test1 192.168.0.1/24 @100
pipework ovs0 test2 192.168.0.2/24 @100
将test3,test4划分到另一个vlan中
pipework ovs0 test3 192.168.0.3/24 @200
pipework ovs0 test4 192.168.0.4/24 @200
完成上述操作后,使用docker attach连到容器中,然后用ping命令测试连通性,发现test1和test2可以相互通信,但与test3和test4隔离。这样,一个简单的VLAN隔离容器网络就已经完成。
由于OpenVswitch本身支持VLAN功能,所以这里pipework所做的工作和之前介绍的基本一样,只不过将Linux bridge替换成了OpenVswitch,在将veth pair的一端加入ovs0网桥时,指定了tag。底层操作如下:
ovs-vsctl add-port ovs0 veth* tag=100
2.3 多主机Docker容器的VLAN划分
上面介绍完了单主机上VLAN的隔离,下面我们将情况延伸到多主机的情况。有了前面两个例子做铺垫,这个也就不难了。为了实现这个目的,我们把宿主机上的网卡桥接到各自的OVS网桥上,然后再为容器配置IP和VLAN就可以了。我们实验环境如下,主机A和B各有一块网卡eth0,IP地址分别为10.10.101.105/24、10.10.101.106/24。在主机A上创建两个容器test1、test2,分别在VLAN 100和VLAN 200上。在主机B上创建test3、test4,分别在VLAN 100和VLAN 200 上。最终,test1可以和test3通信,test2可以和test4通信。
在主机A上
创建Docker容器
docker run -itd --name test1 ubuntu /bin/bash
docker run -itd --name test2 ubuntu /bin/bash
划分VLAN
pipework ovs0 test1 192.168.0.1/24 @100
pipework ovs0 test2 192.168.0.2/24 @200
将eth0桥接到ovs0上
ip addr add 10.10.101.105/24 dev ovs0
ip addr del 10.10.101.105/24 dev eth0
ovs-vsctl add-port ovs0 eth0
ip route del default
ip route add default gw 10.10.101.254 dev ovs0
在主机B上
创建Docker容器
docker run -itd --name test3 ubuntu /bin/bash
docker run -itd --name test4 ubuntu /bin/bash
划分VLAN
pipework ovs0 test1 192.168.0.3/24 @100
pipework ovs0 test2 192.168.0.4/24 @200
将eth0桥接到ovs0上
ip addr add 10.10.101.106/24 dev ovs0
ip addr del 10.10.101.106/24 dev eth0
ovs-vsctl add-port ovs0 eth0
ip route del default
ip route add default gw 10.10.101.254 dev ovs0
完成上面的步骤后,主机A上的test1和主机B上的test3容器就划分到了一个VLAN中,并且与主机A上的test2和主机B上的test4隔离(主机eth0网卡需要设置为混杂模式,连接主机的交换机端口应设置为trunk模式,即允许VLAN 100和VLAN 200的包通过)。拓扑图如下所示(省去了Docker默认的eth0网卡和主机上的docker0网桥):
DSC0001.jpg
除此之外,pipework还支持使用macvlan设备、设置网卡MAC地址等功能。不过,pipework有一个缺陷,就是配置的容器在关掉重启后,之前的设置会丢失。
总结
通过上面的介绍,我相信大家对Docker的网络已经有了一定的了解。对于一个基本应用而言,Docker的网络模型已经很不错了。然而,随着云计算和微服务的兴起,我们不能永远停留在使用基本应用的级别上,我们需要性能更好且更灵活的网络功能。pipework正好满足了我们这样的需求,从上面的样例中,我们可以看到pipework的方便之处。但是,同时也应注意到,pipework并不是一套解决方案,它只是一个网络配置工具,我们可以利用它提供的强大功能,帮助我们构建自己的解决方案。



     2.2 flannel
         Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。

     在Kubernetes的网络模型中,假设了每个物理节点应该具备一段“属于同一个内网IP段内”的“专用的子网IP”。例如:

节点A:10.0.1.0/24
节点B:10.0.2.0/24
节点C:10.0.3.0/24
  
     但在默认的Docker配置中,每个节点上的Docker服务会分别负责所在节点容器的IP分配。这样导致的一个问题是,不同节点上容器可能获得相同的内外IP地址。并使这些容器之间能够之间通过IP地址相互找到,也就是相互ping通。

     Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得“同属一个内网”且”不重复的”IP地址,并让属于不同节点上的容器能够直接通过内网IP通信。
DSC0002.png

     这张图的信息量很全,下面简单的解读一下。

     数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,这是个P2P的虚拟网卡,flanneld服务监听在网卡的另外一端。

     Flannel通过Etcd服务维护了一张节点间的路由表,在稍后的配置部分我们会介绍其中的内容。

     源主机的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一下的有docker0路由到达目标容器。

     这样整个数据包的传递就完成了,这里需要解释三个问题。

     三、docker自有的跨主机通信网络解决方案:macvlan、overlay network
     3.1 macvlan
  Macvlan工作原理

  •   Macvlan是Linux内核支持的网络接口。要求的Linux内部版本是v3.9–3.19和4.0+。
  •   通过为物理网卡创建Macvlan子接口,允许一块物理网卡拥有多个独立的MAC地址和IP地址。虚拟出来的子接口将直接暴露在底层物理网络中。从外界看来,就像是把网线分成多股,分别接到了不同的主机上一样。
  •   Macvlan有四种工作模式:Private、VEPA、Bridge和Passthru。最常用和默认的模式是Bridge模式。
  •   物理网卡收到包后,会根据收到包的目的MAC地址判断这个包需要交给哪个虚拟网卡。
DSC0003.jpg


  •   如果配合Network Namespace 使用,可以构建这样的网络:
DSC0004.jpg
  四种模式

  •   private mode:过滤掉所有来自其他 macvlan 接口的报文,因此不同 macvlan 接口之间无法互相通信
  •   vepa(Virtual Ethernet Port Aggregator) mode: 需要主接口连接的交换机支持 VEPA/802.1Qbg 特性。所有发送出去的报文都会经过交换机,交换机作为再发送到对应的目标地址(即使目标地址就是主机上的其他 macvlan 接口),也就是 hairpin mode 模式,这个模式用在交互机上需要做过滤、统计等功能的场景。
  •   bridge mode:通过虚拟的交换机讲主接口的所有 macvlan 接口连接在一起,这样的话,不同 macvlan 接口之间能够直接通信,不需要将报文发送到主机之外。这个模式下,主机外是看不到主机上 macvlan interface 之间通信的报文的。
  •   passthru mode:暂时没有搞清楚这个模式要解决的问题
环境准备
一共两台机器:两台机器都安装Docker且内核版本>3.9。
主机名IP地址软件环境dev-master-01192.168.2.210kernel>3.9,Dockerdev-node-01192.168.2.211kernel>3.9,Docker 启用网卡混杂模式
两台机器设置使用桥接模式,网卡混杂模式开启全部允许。
主机上配置的enp0s5网口或者创建的vlan网口,均需要开启混杂模式。如果不开启混杂模式会导致macvlan网络无法访问外界,具体在不使用vlan时,表现为无法ping通路由,无法ping通同一网络内其他主机。
设置混杂模式可以通过ip或ifconfig指令实现。
     通过ip指令设置enp0s5为混杂模式
$ ip link set enp0s5  promisc on
取消enp0s5的混杂模式
$ ip link set enp0s5  promisc off

  •   通过ifconfig指令
设置enp0s5为混杂模式
$ ifconfig enp0s5 promisc
取消enp0s5的混杂模式
$ ifconfig enp0s5 -promisc
验证网卡混杂模式是否设置成功
$ ifconfig enp0s5
enp0s5    Link encap:Ethernet  HWaddr 00:1c:42:97:53:2a
          inet addr:192.168.2.210  Bcast:192.168.2.255  Mask:255.255.255.0
          inet6 addr: fe80::21c:42ff:fe97:532a/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:1059321 errors:0 dropped:145 overruns:0 frame:0
          TX packets:15030 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:1000
          RX bytes:785317867 (785.3 MB)  TX bytes:1039141 (1.0 MB)
其中 UP BROADCAST RUNNING PROMISC MULTICAST的PROMISC 说明网卡enp0s5已经设置成混杂模式。
使用Macvlan构建Docker网络
两台主机上均使用enp0s5网卡创建一个192.168.2.0网段的macvlan网络。macvlan驱动实际上是利用的Linux macvlan内核驱动,这意味着这样子运行的容器,网络通讯将会直接送到下层vlan。这是目前最高网络效率的驱动。这里没有NAT,没有端口映射,通讯直接通过VLan送出。
     master主机
创建macvlan网络
$ docker network create -d macvlan --subnet 192.168.2.0/24 --gateway 192.168.2.1 -o parent=enp0s5 -o macvlan_mode=bridge macnet0ab39da89dd66238a1e9c75edbb70afa9b09d13dc5f1a041f5dd46c369856225
macvlan是kernel的模块名。
192.168.2.0/24是宿主机所在网络的网段。
192.168.2.1是网关。
enp0s5是宿主机接入192.168.2.0/24的网络设备。
查看macvlan是否创建成功
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
e13c13e22f73        bridge              bridge              locala56cfbac20ed        docker_gwbridge     bridge              local0b703c3d9cb8        host                host                localabdb4b9f751c        none                null                local0ab39da89dd6        macnet              macvlan             local856b6dbf7e83        weave               weavemesh           local
创建两个使用macvlan容器
创建容器c1
$ docker run -id --net macnet --ip 192.168.2.220 --name c1 busybox sh6120c05c90ae75658f6703a269da453a4c516686144cc53dad027af7410cc93c# 查看容器IP$ docker exec c1 ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever30: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:c0:a8:02:dc brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.220/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c0ff:fea8:2dc/64 scope link
       valid_lft forever preferred_lft forever# 查看容器route$ docker exec c1  route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth0192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
创建容器c2
$ docker run -id --net macnet --ip 192.168.2.221 --name c2 busybox sh
f8bcf7a103ac483fd46ee27ac675b23255bf64ad49c7e70be8785737add1ce06# 查看容器IP$ docker exec c2 ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever31: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:c0:a8:02:dd brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.221/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c0ff:fea8:2dd/64 scope link
       valid_lft forever preferred_lft forever# 查看容器route$ docker exec c2  route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth0192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0

  •   node主机
创建macvlan网络
$ docker network create -d macvlan --subnet 192.168.2.0/24 --gateway 192.168.2.1 -o parent=enp0s5 -o macvlan_mode=bridge macnetad869482ddc115acf6ee004a500ce7c28386e976c4bb5eccdffaaa1afbcd07e1
macvlan是kernel的模块名。
192.168.2.0/24是宿主机所在网络的网段。
192.168.2.1是网关。
enp0s5是宿主机接入192.168.2.0/24的网络设备。
查看macvlan是否创建成功
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
e13c13e22f73        bridge              bridge              locala56cfbac20ed        docker_gwbridge     bridge              local0b703c3d9cb8        host                host                local2b2067e669d4        macnet              macvlan             localabdb4b9f751c        none                null                local856b6dbf7e83        weave               weavemesh           local
创建两个使用macvlan容器
创建容器c3
$ docker run -id --net macnet --ip 192.168.2.222 --name c3 busybox sh8b6a83f73af9dd54ef24be80bf946f0e10959e48ead12a09514d3c59a287927c# 查看容器IP$ docker exec c3 ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever18: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:c0:a8:02:ca brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.222/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c0ff:fea8:2ca/64 scope link
       valid_lft forever preferred_lft forever# 查看容器route$ docker exec c3  route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth0192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
创建容器c4
$ docker run -id --net macnet --ip 192.168.2.223 --name c4 busybox sh
c7be679190467564023aec1fd908bb7418a55f41ab548d59d77cabf187dc665c# 查看容器IP$ docker exec c4 ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever20: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:c0:a8:02:df brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.223/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c0ff:fea8:2df/64 scope link
       valid_lft forever preferred_lft forever# 查看容器route$ docker exec c4  route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth0192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
测试网络连通情况
DSC0005.jpg

所有测试在master主机上进行。

  •   ping网关
$ docker exec c1 ping -c 3 192.168.2.1PING 192.168.2.1 (192.168.2.1): 56 data bytes64 bytes from 192.168.2.1: seq=0 ttl=255 time=1.594 ms64 bytes from 192.168.2.1: seq=1 ttl=255 time=0.659 ms64 bytes from 192.168.2.1: seq=2 ttl=255 time=0.753 ms
--- 192.168.2.1 ping statistics ---3 packets transmitted, 3 packets received, 0% packet lossround-trip min/avg/max = 0.659/1.002/1.594 ms
测试结果:通

  •   使用容器名ping本主机容器
$ docker exec c1 ping -c3 c1
PING c1 (192.168.2.220): 56 data bytes64 bytes from 192.168.2.220: seq=0 ttl=64 time=0.053 ms64 bytes from 192.168.2.220: seq=1 ttl=64 time=0.073 ms64 bytes from 192.168.2.220: seq=2 ttl=64 time=0.048 ms
--- c1 ping statistics ---3 packets transmitted, 3 packets received, 0% packet lossround-trip min/avg/max = 0.048/0.058/0.073 ms
测试结果:通

  •   ping本主机容器
$ docker exec c1 ping -c3 192.168.2.220PING 192.168.2.220 (192.168.2.220): 56 data bytes64 bytes from 192.168.2.220: seq=0 ttl=64 time=0.069 ms64 bytes from 192.168.2.220: seq=1 ttl=64 time=0.172 ms64 bytes from 192.168.2.220: seq=2 ttl=64 time=0.079 ms
--- 192.168.2.220 ping statistics ---3 packets transmitted, 3 packets received, 0% packet lossround-trip min/avg/max = 0.069/0.106/0.172 ms
测试结果:通

  •   ping另一主机容器
$ docker exec c1 ping -c2  192.168.2.222PING 192.168.2.222 (192.168.2.222): 56 data bytes64 bytes from 192.168.2.222: seq=0 ttl=255 time=0.788 ms64 bytes from 192.168.2.222: seq=1 ttl=255 time=0.383 ms
--- 192.168.2.222 ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 0.383/0.585/0.788 ms
测试结果:通

  •   使用容器名ping另一主机容器:
$ docker exec c1 ping -c2 c3
ping: bad address 'c3'
测试结果:不通

  •   本主机ping本主机容器: 不通
$ ping -c 2 192.168.2.220PING 192.168.2.220 (192.168.2.220) 56(84) bytes of data.From 192.168.2.210 icmp_seq=1 Destination Host UnreachableFrom 192.168.2.210 icmp_seq=2 Destination Host Unreachable--- 192.168.2.220 ping statistics ---2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1000ms
测试结果:不通

  •   本主机ping另一主机容器
$ ping -c 2 192.168.2.222PING 192.168.2.222 (192.168.2.222) 56(84) bytes of data.64 bytes from 192.168.2.222: icmp_seq=1 ttl=255 time=0.308 ms64 bytes from 192.168.2.222: icmp_seq=2 ttl=255 time=0.343 ms
--- 192.168.2.222 ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.308/0.325/0.343/0.025 ms
测试结果:通

  •   本主机上容器到另一台宿主IP
$ docker exec c2 ping -c 2 192.168.2.211PING 192.168.2.211 (192.168.2.211): 56 data bytes64 bytes from 192.168.2.211: seq=0 ttl=64 time=0.494 ms64 bytes from 192.168.2.211: seq=1 ttl=64 time=0.495 ms
--- 192.168.2.211 ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 0.494/0.494/0.495 ms
使用Macvlan+VLAN构建Docker网络
VLAN简介
VLAN(Virtual Local Area Network)又称虚拟局域网,是指在局域网的基础上,采用网络管理软件构建的可跨越不同网段、不同网络的端到端的逻辑网络。
一个VLAN组成一个逻辑子网,即一个逻辑广播域,它可以覆盖多个网络设备,允许处于不同地理位置的网络用户加入到一个逻辑子网中。使用VLAN功能后,能够将网络分割成多个广播域。
Linux支持在物理网卡上创建vlan子接口。每个vlan子接口属于不同的二层域,所有的vlan子接口拥有相同的MAC地址。这点是和Macvlan子接口不同的地方。

  •   master主机
创建VLAN
# 为物理网卡enp0s5创建Macvlan子接口
$ ip link add link enp0s5 name enp0s5.200 type vlan id 200# 将MACVLAN设备加入到容器的network space
$ ip link list enp0s5.20033: ip enp0s5.200@enp0s5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:1c:42:97:53:2a brd ff:ff:ff:ff:ff:ff
# 启用enp0s5.200$ ip link set enp0s5.200 up$ ip link list enp0s5.20033: enp0s5.200@enp0s5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 00:1c:42:97:53:2a brd ff:ff:ff:ff:ff:ff
# 设置enp0s5.200为混杂模式
$ ip link set enp0s5.200  promisc on$ ifconfig enp0s5.200enp0s5.200 Link encap:Ethernet  HWaddr 00:1c:42:97:53:2a
          inet6 addr: fe80::21c:42ff:fe97:532a/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:648 (648.0 B)
设置macvlan的ip和网关
$ ip addr add 192.168.200.10/24 dev enp0s5.200# 删除原默认路由,否则下面加默认路由时会报错。$ ip route del default
$ ip route add default via 192.168.200.1 dev enp0s5.200
创建Docker macvlan网络
$ docker network create -d macvlan --subnet=192.168.200.0/24 --gateway=192.168.200.1 -o parent=enp0s5.200 -o macvlan_mode=bridge macvlan200b2fb555bbcdc1f0b724cc9e76b154630e632184566b9e8bb314cde825ad9ff9d
# 查看macvlan是否创建成功
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE6dc2160d4026        bridge              bridge              locala56cfbac20ed        docker_gwbridge     bridge              local0b703c3d9cb8        host                host                local9282605b5107        macnet              macvlan             locald129db56fcc1        macvlan200          macvlan             localabdb4b9f751c        none                null                local856b6dbf7e83        weave               weavemesh           local
创建两个使用macvlan容器
创建容器c5
$ docker run --net=macvlan200 --ip=192.168.200.100 -id --name c5 busybox sh28ee719d4784696eff10805f1f9d992b245b7b886b031c1781dbaf4037bbb231
创建容器c6
$ docker run --net=macvlan200 --ip=192.168.200.101 -id --name c6 busybox sh7bd2a36e24846b383ab3aca6b9b48227600aed7352956c2c974db1ceb97efb54

  •   node主机
创建Vlan
# 为物理网卡enp0s5创建Macvlan子接口
$ ip link add link enp0s5 name enp0s5.200 type vlan id 200# 将MACVLAN设备加入到容器的network space
$ ip link list enp0s5.20024: enp0s5.200@enp0s5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:1c:42:67:23:07 brd ff:ff:ff:ff:ff:ff
# 启用enp0s5.200$ ip link set enp0s5.200 up$ ip link list enp0s5.20024: enp0s5.200@enp0s5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 00:1c:42:67:23:07 brd ff:ff:ff:ff:ff:ff
# 设置enp0s5.200为混杂模式
$ ip link set enp0s5.200  promisc on$ ifconfig enp0s5.200enp0s5.200 Link encap:Ethernet  HWaddr 00:1c:42:67:23:07
          inet6 addr: fe80::21c:42ff:fe67:2307/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:648 (648.0 B)
设置macvlan的ip和网关
$ ip addr add 192.168.200.11/24 dev enp0s5.200# 删除原默认路由,否则下面加默认路由时会报错。$ ip route del default
$ ip route add default via 192.168.200.1 dev enp0s5.200
创建Docker macvlan网络
$ docker network create -d macvlan --subnet=192.168.200.0/24 --gateway=192.168.200.1 -o parent=enp0s5.200 -o macvlan_mode=bridge macvlan200b2fb555bbcdc1f0b724cc9e76b154630e632184566b9e8bb314cde825ad9ff9d
# 查看macvlan是否创建成功
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE4886f72179a8        bridge              bridge              local0b703c3d9cb8        host                host                local149f5dcc20b3        macnet              macvlan             local8ee3174430ab        macvlan200          macvlan             localabdb4b9f751c        none                null                localbce1daa0a925        weave               weavemesh           local
创建两个使用macvlan容器
创建容器c7
$ docker run --net=macvlan200 --ip=192.168.200.102 -id --name c7 busybox sh28ee719d4784696eff10805f1f9d992b245b7b886b031c1781dbaf4037bbb231
创建容器c8
$ docker run --net=macvlan200 --ip=192.168.200.103 -id --name c8 busybox sh7bd2a36e24846b383ab3aca6b9b48227600aed7352956c2c974db1ceb97efb54
测试网络连通情况
所有测试在master主机上进行。

  •   ping网关
$ docker exec c5 ping -c2 192.168.200.1
测试结果:不通

  •   ping本地macvlannet地址
$ docker exec c5 ping -c2 192.168.200.10PING 192.168.200.10 (192.168.200.10): 56 data bytes--- 192.168.200.10 ping statistics ---2 packets transmitted, 0 packets received, 100% packet loss
测试结果:不通

  •   ping另一个主机的macvlannet地址
$ docker exec c5 ping -c2 192.168.200.11PING 192.168.200.11 (192.168.200.11): 56 data bytes64 bytes from 192.168.200.11: seq=0 ttl=64 time=0.535 ms64 bytes from 192.168.200.11: seq=1 ttl=64 time=0.368 ms
--- 192.168.200.11 ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 0.368/0.451/0.535 ms
测试结果:通

  •   ping本主机容器
$ docker exec c5 ping -c2 192.168.200.100PING 192.168.200.100 (192.168.200.100): 56 data bytes64 bytes from 192.168.200.100: seq=0 ttl=64 time=0.091 ms64 bytes from 192.168.200.100: seq=1 ttl=64 time=0.046 ms
--- 192.168.200.100 ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 0.046/0.068/0.091 ms
测试结果:通

  •   ping另一主机容器
$ docker exec c5 ping -c2 192.168.200.102PING 192.168.200.102 (192.168.200.102): 56 data bytes64 bytes from 192.168.200.102: seq=0 ttl=64 time=0.815 ms64 bytes from 192.168.200.102: seq=1 ttl=64 time=1.051 ms
--- 192.168.200.102 ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 0.815/0.933/1.051 ms
测试结果:通

  •   使用容器名ping本主机容器
$ docker exec c5 ping -c2 c6
PING c6 (192.168.200.101): 56 data bytes64 bytes from 192.168.200.101: seq=0 ttl=64 time=0.152 ms64 bytes from 192.168.200.101: seq=1 ttl=64 time=0.108 ms
--- c6 ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 0.108/0.130/0.152 ms
测试结果:通

  •   使用容器名ping另一主机容器
$ docker exec c5 ping -c2 c7
ping: bad address 'c7'
测试结果:不通

  •   ping跨网络主机
$ docker exec c5 ping -c2 192.168.200.102PING 192.168.200.102 (192.168.200.102): 56 data bytes64 bytes from 192.168.200.102: seq=0 ttl=64 time=0.518 ms64 bytes from 192.168.200.102: seq=1 ttl=64 time=0.458 ms
--- 192.168.200.102 ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 0.458/0.488/0.518 ms
测试结果:通

  •   本主机ping本主机容器
$ ping 192.168.200.100 -c2PING 192.168.200.100 (192.168.200.100) 56(84) bytes of data.From 192.168.200.10 icmp_seq=1 Destination Host UnreachableFrom 192.168.200.10 icmp_seq=2 Destination Host Unreachable--- 192.168.200.100 ping statistics ---2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1006mspipe 2
测试结果:不通

  •   本主机ping另一主机容器
$ ping 192.168.200.102 -c2
PING 192.168.200.102 (192.168.200.102) 56(84) bytes of data.64 bytes from 192.168.200.102: icmp_seq=1 ttl=64 time=0.625 ms64 bytes from 192.168.200.102: icmp_seq=2 ttl=64 time=0.319 ms
--- 192.168.200.102 ping statistics ---2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.319/0.472/0.625/0.153 ms
测试结果:通
一些问题

  • macvlan网络在创建时要指定parent.其中parent仅能使用一次,即eth0在创建一个macvlan网络时使用了,则在创建另一个的时候就无法再使用了。
  • 两种模式下都有测试网络不通的情况,不知道是不是虚拟机网络环境问题。理论上应该是通的。待在真实环境验证后才得知。
  

   3.2 overlay network
  见:http://www.tuicool.com/articles/eURfqu      
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-481838-1-1.html 上篇帖子: Docker 监控实战 下篇帖子: 建立私有docker
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表