码迷,mamicode.com
首页 > 其他好文 > 详细

Docker 之容器间通信配置

时间:2020-08-05 10:39:19      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:通信   adc   比较   关闭   上启   大致   ifconf   主机   进入   

当你开始大规模使用Docker时,你会发现需要了解很多关于网络的知识。Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理。然而,Docker同样有着很多不完善的地方,网络方面就是Docker比较薄弱的部分。因此,我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

我们安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host

  • host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
  • None:该模式关闭了容器的网络功能,相当于一个回环网络。
  • Bridge:此模式会为每一个容器分配、设置IP等,并将容器连接到一个叫docker0的虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。
[root@docker03 ~]# docker network ls            # 执行该命令查看docker创建的网络
NETWORK ID          NAME                DRIVER              SCOPE
ec6c04260126        bridge              bridge              local
26342588dbd3        host                host                local
a1ab061af018        none                null                local

三个网络解释如下:
None:该模式将容器放置在它自己的网络栈中,但是并不进行任何配置。实际上,该模式关闭了容器的网络功能,类似于会换地址,在以下两种情况下是有用的:容器并不需要网络(例如只需要写磁盘卷的批处理任务)
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时,看到的都是宿主机上的信息。该模式不够灵活,容易出现端口冲突问题
Bridge:相当于Vmware中的NAT模式,容器使用独立的network Namespace,并且连接到docker0虚拟网卡(默认模式)。通过docker网桥以及IPtables nat表配置与宿主机通信;Bridge模式是Docker默认的网络设置,此模式会为每一个容器分配一个Network nameSpace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥docker0上
overlay:顾名思义:覆盖,但它又不是覆盖,它的作用就是在容器原有的网络基础之上,再添加一块网卡,并为其分配一个IP地址,可以将所有的docker容器关联到同一个局域网中,适用于容器与容器是跨主机进行通信的场景。

在生产环境中,应用的最多的就是Bridge模式和overlay模式了。

一、Bridge模式
当Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器就会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中,一般Docker会使用172.17.0.0/16这个网段,并将这个网段分配给docker0网桥使用(在主机上使用ifconfig命令可以看到docker0),然后为容器分配一个同网段的IP地址。
单机环境下的网络拓扑如下(主机地址是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)创建的话,那么?如何使它们互通呢?

实现的效果如下:

  • 基于docker0(docker的驱动名称使bridge)网络创建2个容器,分别是box1、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@docker03 ~]# docker run -itd --name test1 --network bridge busybox
#创建一个容器box1,--network选项可以省略,默认就是bridge,这里只是为了展示命令
[root@docker03 ~]# docker run -itd --name test2 --network bridge busybox          # 同上
[root@docker03 ~]# docker network create -d bridge my_net1             #创建一个桥接网络,名称为my_net1
[root@docker03 ~]# docker run -itd --name test3 --network my_net1 busybox                #基于my_net1创建容器test3
[root@docker03 ~]# docker run -itd --name test4 --network my_net1 busybox                # 同上
[root@docker03 ~]# docker network create -d bridge --subnet 172.20.18.0/24 my_net2               # 创建一个桥接网络my_net2,并指定其网段
[root@docker03 ~]# docker run -itd --name test5 --network my_net2 --ip 172.20.18.5 busybox       #基于my_net2网络,创建一个容器test5,并且指定其IP地址
[root@docker03 ~]# docker run -itd --name test6 --network my_net2 --ip 172.20.18.6 busybox
[root@docker03 ~]# docker network connect my_net1 test2          #将test2连接到my_net1这个网络
[root@docker03 ~]# docker exec test2 ping test3           #进行ping测试,可以发现test2 可以ping通test3了。
#而如果没有将box2连接到网络my_net1,是绝对不会ping通
PING test3 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.121 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.059 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.061 ms
[root@docker03 ~]# docker network connect my_net2 test4    # 将test4连接到my_net2网络
#同box2和box3的ping测试,若没有将box4连接到box5所在的网络,是不可能ping通的。
[root@docker03 ~]# docker exec test5 ip a         # 查看test5 的IP
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    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
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:14:12:05 brd ff:ff:ff:ff:ff:ff
    inet 172.20.18.5/24 brd 172.20.18.255 scope global eth0          # 确定其IP
       valid_lft forever preferred_lft forever
[root@docker03 ~]# docker exec test4 ping test5     # 可以ping通
PING test5 (172.20.18.5): 56 data bytes
64 bytes from 172.20.18.5: seq=0 ttl=64 time=0.112 ms
64 bytes from 172.20.18.5: seq=1 ttl=64 time=0.065 ms
64 bytes from 172.20.18.5: seq=2 ttl=64 time=0.058 ms

经过以上配置,已经实现了最终的效果,需要注意的是,我们完全可以将创建的my_net1、my_net2网络驱动理解为一个交换机,而执行命令docker network connect my_net1 test2,则相当于将test2这个容器添加了一块网卡,然后连接到了my_net1这个交换机,然后这个容器就多了一块网卡,并且拥有my_net1这个交换机中IP地址。在上述的配置中,test2不但可以和test3进行通信,也是可以和test4进行通信的,因为它们都是连接在了my_net1这个“交换机”上。

注意:

  • 容器之间可以使用容器名进行通信,但前提使用的是自定义的网络,如上面的my_net1、my_net2;
  • 如果在创建自定义网络的同时,指定了该网络的网段,那么,使用此网络的容器也可以指定容器的IP地址,若没有指定该网络的网段,则不可以指定容器的IP地址。

Docker 之容器间通信配置

标签:通信   adc   比较   关闭   上启   大致   ifconf   主机   进入   

原文地址:https://blog.51cto.com/14227204/2516716

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!