博文大纲:web
- 1、Bridge模式(同一台Docker服务器上容器间的通讯)
- 2、部署consul服务实现Docker容器跨主机通讯
当你开始大规模使用Docker时,你会发现须要了解不少关于网络的知识。Docker做为目前最火的轻量级容器技术,有不少使人称道的功能,如Docker的镜像管理。然而,Docker一样有着不少不完善的地方,网络方面就是Docker比较薄弱的部分。所以,咱们有必要深刻了解Docker的网络知识,以知足更高的网络需求。本文首先介绍了Docker自身的4种网络工做方式,而后介绍一些自定义网络模式。docker
咱们安装Docker时,它会自动建立三个网络,bridge(建立容器默认链接到此网络)、 none 、host。数据库
- host:容器将不会虚拟出本身的网卡,配置本身的IP等,而是使用宿主机的IP和端口。
- None:该模式关闭了容器的网络功能,至关于一个回环网络。
- Bridge:此模式会为每个容器分配、设置IP等,并将容器链接到一个叫docker0的虚拟网桥,经过docker0网桥以及Iptables nat表配置与宿主机通讯。
[root@docker ~]# docker network ls #执行该命令查看docker建立的网络
关于上述提到的三个网络解释以下:编程
- Host:至关于Vmware中的桥接模式,与宿主机在同一个网络中,但没有独立的IP地址。众所周知,Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其余的Network Namespace隔离。一个Docker容器通常会分配一个独立的Network Namespace。但若是启动容器的时候使用host模式,那么这个容器将不会得到一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出本身的网卡,配置本身的IP等,而是使用宿主机的IP和端口。基于Host模式启动的容器,在容器内执行ifconfig时,看到的都是宿主机上的信息。该模式不够灵活,容易出现端口冲突问题。
- None:该模式将容器放置在它本身的网络栈中,可是并不进行任何配置。实际上,该模式关闭了容器的网络功能,相似于会换地址,在如下两种状况下是有用的:容器并不须要网络(例如只须要写磁盘卷的批处理任务)。
- overlay:顾名思义:覆盖,但它又不是覆盖,它的做用就是在容器原有的网络基础之上,再添加一块网卡,并为其分配一个IP地址,能够将全部的docker容器关联到同一个局域网中,适用于容器与容器是跨主机进行通讯的场景。
- Bridge:至关于Vmware中的NAT模式,容器使用独立的network Namespace,而且链接到docker0虚拟网卡(默认模式)。经过docker网桥以及IPtables nat表配置与宿主机通讯;Bridge模式是Docker默认的网络设置,此模式会为每个容器分配一个Network nameSpace、设置IP等,并将一个主机上的Docker容器链接到一个虚拟网桥docker0上。
在生产环境中,应用的最多的就是Bridge模式和overlay模式了。这篇博文将围绕着这两个模式进行介绍。bootstrap
当Docker server启动时,会在主机上建立一个名为docker0的虚拟网桥,此主机上启动的Docker容器就会链接到这个虚拟网桥上。虚拟网桥的工做方式和物理交换机相似,这样主机上的全部容器就经过交换机连在了一个二层网络中,通常Docker会使用172.17.0.0/16这个网段,并将这个网段分配给docker0网桥使用(在主机上使用ifconfig命令能够看到docker0),而后为容器分配一个同网段的IP地址。vim
单机环境下的网络拓扑以下(主机地址是10.10.0.186/24):浏览器
Docker 完成以上网络配置的过程大体是这样的:服务器
- 在主机上建立一对虚拟网卡veth pair设备。veth设备老是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另外一个设备出来。所以,veth设备经常使用来链接两个网络设备。
- Docker将veth pair设备的一端放在新建立的容器中,并命名为eth0。另外一端放在主机中,以veth65f9这样相似的名字命名,并将这个网络设备加入到docker0网桥中,能够经过brctl show命令查看。
- 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。
当全部的容器都是基于默认的docker0进行建立的,那么抛开防火墙、IPtables等相关的设置外,理论上,各个容器是能够相互通讯的,可是docker0这个网络是系统自带的,有些功能不可以实现,而且不够灵活。网络
其实咱们也是能够自定义建立网络的,而且能够指定其具体属于哪一个网段等。这是docker 0没法实现的,那么,若是各个容器,不是基于同一个网络(如Docker0)建立的话,那么?如何使它们互通呢?tcp
下面来一段配置,来看一下Bridge的工做模式。
实现的效果以下:
- 基于docker0(docker的驱动名称使bridge)网络建立2个容器,分别是box一、box2。
- 建立自定义网络,网络类型为bridge,名称为my_net1.基于此网络建立两个容器box3,box4(若不指定网段,会使用172.18.0.0/16这个网段,基于docker0增长一个网络位)
- 建立自定义网络,网络类型为bridge,名称为my_net2,指定网段为172.20.18.0/24,基于此网络建立两个容器box5(ip为172.20.18.6),box6(IP为172.20.18.8)。
- 配置实现box2可以和box3相互通讯,box4和box5能够相互通讯。
[root@docker ~]# docker run -itd --name box1 --network bridge busybox #建立一个容器box1,--network选项能够省略,默认就是bridge,这里只是为了展现命令 [root@docker ~]# docker run -itd --name box2 --network bridge busybox #同上,这里建立一个容器box2 [root@docker ~]# docker network create -d bridge my_net1 #建立一个桥接网络,名称为my_net1 [root@docker ~]# docker run -tid --name box3 --network my_net1 busybox #基于my_net1建立容器box3 [root@docker ~]# docker run -tid --name box4 --network my_net1 busybox #同上,建立box4 [root@docker ~]# docker network create -d bridge --subnet 172.20.18.0/24 my_net2 #建立一个桥接网络my_net2,并指定其网段 [root@docker ~]# docker run -tid --name box5 --network my_net2 --ip 172.20.18.6 busybox #基于my_net2网络,建立一个容器box5,而且指定其IP地址 [root@docker ~]# docker run -tid --name box6 --network my_net2 --ip 172.20.18.8 busybox #同上 [root@docker ~]# docker network connect my_net1 box2 #将box2链接到my_net1这个网络 [root@docker ~]# docker exec box2 ping box3 #进行ping测试,能够发现box2能够ping通box3了。 #而若是没有将box2链接到网络my_net1,是绝对不会ping通的。 PING box3 (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.069 ms 64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.076 ms [root@docker ~]# docker network connect my_net2 box4 #将box4链接到my_net2网络 #同box2和box3的ping测试,若没有将box4链接到box5所在的网络,是不可能ping通的。 [root@docker ~]# docker exec box5 ip a #查看box5的IP地址 .......................#省略部份内容 16: eth0@if17: <BROADCAST,MULTICAST,UP,LO500 qdisc noqueue link/ether 02:42:ac:14:12:06 brd ff:ff:ff:ff:ff:ff inet 172.20.18.6/24 brd 172.20.18.255 scope global eth0 #确认其IP valid_lft forever preferred_lft forever [root@docker ~]# docker exec box4 ping 172.20.18.6 #在box4容器上对box5的IP进行ping测试,能够ping通 PING box5 (172.20.18.6): 56 data bytes 64 bytes from 172.20.18.6: seq=0 ttl=64 time=0.090 ms 64 bytes from 172.20.18.6: seq=1 ttl=64 time=0.130 ms
通过以上配置,已经实现了最终的效果,须要注意的是,咱们彻底能够将建立的my_net一、my_net2网络驱动理解为一个交换机,而执行命令docker network connect my_net1 box2,则至关于将box2这个容器添加了一块网卡,而后链接到了my_net1这个交换机,而后这个容器就多了一块网卡,而且拥有my_net1这个交换机中IP地址。在上述的配置中,box2不但能够和box3进行通讯,也是能够和box4进行通讯的,由于它们都是链接在了my_net1这个“交换机”上。
注意:
- 容器之间可使用容器名进行通讯,但前提使用的是自定义的网络,如上面的my_net一、my_net2;
- 若是在建立自定义网络的同时,指定了该网络的网段,那么,使用此网络的容器也能够指定容器的IP地址,若没有指定该网络的网段,则不能够指定容器的IP地址。
consul:数据中心的含义,能够将其当作数据库来理解,相似于Redis等非关系型数据库,采用的是键-值对的方式,存放着各个容器的IP及端口信息。
我对consul服务的了解也不是太多,若想要详细了解此服务,仍是参考其余文档吧,若之后有机会,我会详细写下来consul这个服务。
consul的功能很强大,能够以群集的方式运行,而且具有健康监测等功能。
下面开始配置consul服务。
若须要安装部署Docker服务器,能够参考博文:Docker的安装详细配置 。
[root@docker ~]# docker pull progrium/consul #下载consul镜像 [root@docker ~]# docker run -d -p 8500:8500 -h consul --name consul --restart=always progrium/consul -server -bootstrap #运行consul容器,该服务的默认端口是8500,“-p”:表示将容器的8500端口映射到宿主机的8500端口 #“-h”:表示consul的主机名;“--name consul”表示为该容器名;“--restart=always”表示能够随着docker服务的启动而启动; #“-serve -bootstarp”:表示当在群集中,加上这两个选项可使其以master的身份出现 [root@docker ~]# netstat -anput | grep 8500 #肯定8500端口在监听 tcp6 0 0 :::8500 :::*
OK,至此,单节点的consul服务就完成了,如今切换至第二台Docker服务器。
[root@docker02 ~]# vim /usr/lib/systemd/system/docker.service #编辑docker主配置文件 ..............#省略部份内容,搜索“Start”定位到下面配置行,修改以下: ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.20.7:8500 --cluster-advertise=ens33:2376 #各项解释以下: #/var/run/docker.sock:Docker的一个编程接口 # “ -H tcp://0.0.0.0:2376 ” :使用本机的tcp2376端口; # “ --cluster-store=consul://192.168.20.7:8500”:指定运行着consul服务的第一台docker服务器IP及端口; # “ --cluster-advertise=ens33:2376”:从本机的ens33网卡经过2376端口搜集网络信息,存储在consul上 #修改完成后,保存退出便可。 [root@docker02 ~]# systemctl daemon-reload #从新加载配置文件 [root@docker02 ~]# systemctl restart docker #重启docker服务
便可看到用来测试的那两台docker服务器IP等相关信息,以下:
[root@docker02 ~]# docker network create -d overlay my_olay #建立一个名字为my_olay的voerlay网络
[root@docker03 ~]# docker network ls #查看docker03的网络,发现其不但有overlay网络, #并且其SCOPE(范围)是global(全局的) NETWORK ID NAME DRIVER SCOPE 8d5b00cf07ab bridge bridge local 17c053a80f5a host host local c428fc28bb11 my_olay overlay global 323935eaa5c3 none null local
其实,如今在第二台Docker服务器上基于刚刚建立的overlay网络运行一个容器,在第三台Docker服务器上也基于这个overlay网络运行一个容器,这两个在不一样主机上的容器是能够互通的,以下:
##################第二台Docker服务器上配置以下:########################### [root@docker02 ~]# docker run -tid --name web01 --network my_olay busybox #基于网络my_olay运行一个容器web01 [root@docker02 ~]# docker exec web01 ip a #查看其IP信息,发现其除了回环地址,还有两个IP 1: 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 8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff inet 10.0.0.2/24 brd 10.0.0.255 scope global eth0 #这个地址就是my_olay给的 valid_lft forever preferred_lft forever 11: eth1@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1 valid_lft forever preferred_lft forever ##################第三台Docker服务器上配置以下:########################### [root@docker03 ~]# docker run -tid --name web02 --network my_olay busybox #基于网络my_olay运行一个容器web02 [root@docker03 ~]# docker exec web02 ip a #查看web02的IP 1: 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 8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue link/ether 02:42:0a:00:00:03 brd ff:ff:ff:ff:ff:ff inet 10.0.0.3/24 brd 10.0.0.255 scope global eth0 #这个地址就是my_olay给的 valid_lft forever preferred_lft forever 11: eth1@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1 valid_lft forever preferred_lft forever #########在第二台Docker服务器上对第三台Docker服务器上的容器进行ping测试########## [root@docker02 ~]# docker exec web01 ping web02 #肯定能够ping通 PING web02 (10.0.0.3): 56 data bytes 64 bytes from 10.0.0.3: seq=0 ttl=64 time=1.091 ms 64 bytes from 10.0.0.3: seq=1 ttl=64 time=1.007 ms
———————— 本文至此结束,感谢阅读 ————————