前言Docker目前支持以下五种网络模式:bridge:此时docker引擎会创建一个vethpair,一端连接容器实例,命名为eth0,以及另一端连接到指定的网桥中(例如docker0),同一主机上的容器实例可以相互通信,因为它们连接到同一个网桥。创建容器时会自动创建一条SNAT规则,用于容器与外界通信时使用。如果用户使用-p或-Peport,相应的端口映射规则也会被创建。主机:与主机共享网络。此时容器不使用网络的命名空间。宿主机的所有设备,比如Dbus,都会暴露给容器,存在安全隐患。none:不设置网络,表示容器中没有配置网卡,用户可以手动配置。container:用容器实例指定共享网络network:使用自定义网络,可以用dockernetworkcreate创建,默认支持多种网络驱动,用户可以自由创建bridgenetworks或overlaynetworks。默认为桥接模式,网络地址为172.16.0.0/16。同一主机上的容器实例可以通信,但不能跨主机通信。本文后续部分将介绍如何使用gre隧道技术实现跨主机通信。环境配置本文使用两台主机A和B进行仿真实验。这两台主机实际上是ubuntu14.04操作系统的virtalbox虚拟机。两者都配备了两张网卡。网卡配置如下:Networketh1:hostonly网卡,分配的ip地址为192.168.56.0/24,连接到同一主机的网卡只能相互通信。主机A网络:eth0:172.16.1.24(公司内网IP,可与外网互通)eth1:192.168.56.4B主机网络:eth0:172.16.1.178(公司内网IP,可与外网互通)eth1:192.168.56.5两台主机需要安装以下软件包:Docker,实验中使用的最新版本1.11,快速安装:curl-sSLhttps://get.docker.com/|shOpenvswitch,安装方法:sudoapt-getinstallopenvswitch-switchbridge-utils,或者没有安装,使用ovs-vsctl。Docker配置两台宿主机的容器可以互通,网络不重叠,所以设置不同的网络:A:10.103.100.0/24B:10.103.200.0/24,使用灵雀云镜像加速拉取镜像。***主机配置文件/etc/default/docker如下:DOCKER_OPTS="$DOCKER_OPTS--registry-mirror=http://houchaohann.m.alauda.cn--bip=10.103.100.1/24--fixed-cidr=10.103.100.0/24”B主机配置文件/etc/default/docker如下:DOCKER_OPTS="$DOCKER_OPTS--registry-mirror=http://houchaohann.m.alauda.cn--bip=10.103.200.1/24--fixed-cidr=10.103.200.0/24"分别重启主机A和B的Docker服务:sudoservicedockerrestart此时主机A的docker0网桥地址为10.103.100.1,地址主机B的docker0网桥的地址是10.103.200.1。很明显,在主机A上ping10.103.200.1不通。同理,主机B无法ping通主机A的网桥。隧道配置在主机A上创建网桥(使用ovs-vsctl,不要使用brctl):sudoovs-vsctladd-brdocker_tunnel将gre0接口加入网桥docker_tunnel,创建GRE隧道加入网桥并配置远程IP,注意:我们在eth1上建立隧道,所以我们需要使用eth1IP地址:sudoovs-vsctladd-portdocker_tunnelgre0--setInterfacegre0type=greoptions:remote_ip=192.168.56.5此时:fgp@ubuntu-4:~$sudoovs-vsctlshow2189345f-d4fb-4915-ab97-4c65a8d9ffe0Bridgedocker_tunnelPort"gre0"Interface"gre0"type:greoptions:{remote_ip="192.168.56.5"}Portdocker_tunnelInterfacedocker_tunneltype:internalovs_version:"2.0.2"把docker_tunnel加入到docker0网桥中:sudobrctladdifdocker0docker_tunnel增加路由:sudoiprouteadd10.103.200.0/24via192.168.56.5deveth1此时路由表:fgp@ubuntu-4:~$sudoroute-nKernelIProutingtableDestinationGatewayGenmaskFlagsMetricRefUseIface0.0.0.0172.16.1.10.0.0.0UG000eth010.103.100.00.0.0.0255.255.255.0U000docker010.103.200.0192.168.56.5255.255.255.0UG000eth1172.16.1.00。0.0.0255.255.255.0U000eth0192.168.56.00.0.0.0255.255.255.0U000eth1验证A主机是否可以与B通信:fgp@ubuntu-4:~$ping-c2-w110.103.200.1PING10.103.200.1(10.103.200.1)56(84)bytesofdata.64bytesfrom10.103.200.1:icmp_seq=1ttl=64time=0.339ms---10.103.200.1pingstatistics---1packetstransmitted,1received,0%packetloss,time0msrttmin/avg/max/mdev=0.339/0.339/0.339/0.000ms同样在主机B上执行同样的步骤:sudoovs-vsctladd-brdocker_tunnelsudoovs-vsctladd-portdocker_tunnelgre0--setInterfacegre0type1=81=greiptions:remote_.56.4sudobrctladdifdocker0docker_tunnelsudoiprouteadd10.103.100.0/24via192.168.56.4deveth1验证主机B是否可以与A通信:fgp@ubuntu-5:~$ping-c2-w110.103.100.1PING10.103.100.1(10.110.10084)bytesofdata.64bytesfrom10.103.100.1:icmp_seq=1ttl=64time=0.336ms64bytesfrom10.103.100.1:icmp_seq=2ttl=64time=0.409ms---10.103.100.1pingstatistics---2packetstransmitted,2timemincetived/0%max/mdev=0.336/0.372/0.409/0.041ms验证docker容器跨主机通信主机创建ubuntu14.04容器:dockerrun-t-i--rm--namefrom-A--hostnamefrom-Aubuntu:14.0容器中的4bash内部检查ip地址:#from-Aifconfigeth0|grep'inetaddr'|cut-d':'-f2|cut-d''-f1#10.103.100.2B主机创建ubuntu14.04容器:dockerrun-t-i--rm--namefrom-A--hostnamefrom-Bubuntu:14.04bash查看容器内地址:#from-Bifconfigeth0|grep'inetaddr'|cut-d':'-f2|cut-d''-f1#10.103.200.2在A容器实例上pingB容器实例:#from-Aping10.103.200.2输出:root@from-A:/#ping-c2-w110.103.200.2PING10.103.200.2(10.103.200.2)56(84)bytesofdata.64bytesfrom10.103.200.2:icmp_seq=1ttl=62time=0.510ms---10.103.200.2pingstatistics---1packetstransmitted,1received,0%packetloss,time0msrttmin/avg/max/mdev=0.510/0.510/0.510/0.000ms我们发现主机A上的容器成功ping通了主机B上的容器,实现了跨主机通信!使用docker-swarm实现跨主机容器通信。Docker的覆盖网络驱动程序支持跨主机通信。这个实现是基于libnetwork和docker的libkv库中内置的VXLAN实现。使用overlay网络需要K-VStore。目前支持的K-Vstore包括etcd、Consul、Zookeeper。本来想直接用docker启动consul,后来发现dockerdaemon依赖consul,只能先跟着consul了。先去官方下载安装包:下载地址,解压后只有一个二进制文件,直接运行即可:nohup./consulagent-dev-advertise172.16.1.24-client0.0.0.0&注意:这个服务是在机器A上运行,172.16.1.24必须配置为可以连接外网的IP地址,否则后面启动Swarm容器时内部无法通信!然后修改A、B服务的daemon配置文件/etc/default/docker:DOCKER_OPTS="--cluster-store=consul://172.16.1.24:8500--cluster-advertise=eth0:2375"DOCKER_OPTS="$DOCKER_OPTS--registry-mirror=http://houchaohann.m.alauda.cn-Htcp://0.0.0.0:2375-Hunix:///var/run/docker.sock》重启docker服务:sudoservicedockerrestart执行dockerinfo必须包含以下信息:Clusterstore:consul://172.16.1.24:8500Clusteradvertise:172.16.1.24:2375然后我们需要部署一个DockerSwarm集群。详情请参考手动部署docker-swarm集群。***创建overlay网络:dockernetworkcreate--driveroverlay--subnet10.103.240.0/24test其中--dirver指定为overlay,并指定我们需要的子网地址,名称为test,可以查看我们创建的内容通过dockernetworkls是否网络成功:fgp@ubuntu-5:~$dockernetworkls|greptest7eef808f272btestoverlay现在覆盖网络就创建好了。我们测试它是否支持跨主机通信。首先我们创建一个ubuntu容器,命名为ubuntu-1,使用刚刚创建的网络:dockerrun-t-i-d--nettest--nameubuntu-1ubuntu:14.04然后我们创建***为ubuntu容器,为了保证没有和ubuntu-1调度在同一个host上,我们需要使用dockerswarm的filter来指定affinity,如下:dockerrun-t-i-d--nettest--nameubuntu-2-eaffinity:container!=~ubuntu-1ubuntu:14.04运行dockerps:dockerpsfgp@ubuntu-5:~$dockerpsCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMESba5018dfe26eubuntu:14.04"/bin/bash"2minutesagoUpLessthanasecondubuntu-5/ubuntu-1bedd266cddaaubuntu:14.04"/bin/bash"14hoursagoUp41secondsubuntu-4/ubuntu-2由Itcanbeseen两个ubuntu容器运行在不同的主机上,满足我们的测试要求。分别获取ubuntu-1和ubuntu-2的ip地址:fgp@ubuntu-5:~$dockerinspect-f''ubuntu-110.103.240.2fgp@ubuntu-5:~$dockerinspect-f''ubuntu-210.103.240.3可见ubuntu-1的ip地址是10.103.240.2,ubuntu-2的ip地址是10.103.240.3。我们在ubuntu-1上pingubuntu-2地址:fgp@ubuntu-5:~$dockerexec-t-iubuntu-1ping-c210.103.240.3PING10.103.240.3(10.103.240.3)56(84)bytesofdata.64bytesfrom10.103.240.3:icmp_seq=1ttl=64time=0.559ms64bytesfrom10.103.240.3:icmp_seq=661bytes=2timettl=---10.103.240.3pingstatistics---2packetstransmitted,2received,0%packetloss,time999msrttmin/avg/max/59/mdev/mdev=0.50.610/0.661/0.051ms原来不在同一台主机上的ubuntu-1和ubuntu-2可以正常通信!【本文为专栏作家“付广平”的原创文章。如需转载请通过get联系】点此查看该作者更多好文
