经过一个星期的加班到9点,终于将docker的网络部分小小的总结了一下,小编在这之前也发布过关于docker的内容,本来想就此结束,但是总感觉少了些什么,只会docker的命令,仿佛不能深入的理解docker强大之处,所以小编决定在补充一下关于docker的网络部分,包括docker的网络模式、容器通信、以及相应的实战操作。虽然这部分有些难以理解,但是细细研读之后,一定会有所收获。
1.docker的网络模式
安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络,也就是在不使用--network参数时)、 none 、host。还有以后一种自定义模式,自定义模式有三种:bridge、overlay、macvlan。
我们可以使用一下命令,查看本机容器间通信的几种方式:
docker network ls
我们可以在docker run的时候使用--net= none/ host/ bridge来设置容器具体使用哪种模式。
(1)默认网络通信模式bridge网桥
默认情况下docker运行容器时,宿主机会创建一个bridge网桥,是一个名叫docker 0的虚拟网桥 ,默认docker 0 IP为172.17.0.1,网桥再给容器分配虚拟子网IP,并且以网桥IP作为网关。在不指定网络的情况下,容器之间的通信都是通过bridge网桥进行通信。然后网桥在与宿主机镜像进行IP转换,端口映射等通信。
这种bridge网桥与容器,与宿主机之间的通信,有点类似与三层路由交换:
(2) host宿主机模式
如果容器指定网络模式为host,容器不会有自己的network namespace,而是和宿主机共用一个network网络及IP,容器不会有虚拟出自己的网卡、IP等,当然除了网络通信这一块和宿主机绑定了,其余的容器内容还是和宿主机安全隔离了。这种在做容器迁移时,很不方便,不推荐使用。
(3) none模式
容器指定网络模式-net为none时,docker容器不再拥有自己的network namespace,但是所有网络配置都得自行配置,如IP、网卡等,这种方式很麻烦。(关闭了容器的网络功能)
这里补充两个docker服务运行时参数
-b BRIDGE or--bridge=BRIDGE ——指定容器挂载的网桥;
--fixed-cidr=10.200.55.64/26 #定制容器的IP地址范围
2.单机间的容器通信
单机间的通信,就是同一宿主机中的不同容器之间的通信,容器之间可通过 IP,Docker DNS Server 和joined 容器三种方式通信。
(1)IP通信
两个容器要能通信,必须要有属于同一个网络的网卡。满足这个条件后,容器就可以通过 IP 交互了。这也是默认的方式,我们在使用--net= bridge,docker虚拟出来的一个docker0网桥,会给每一个容器在docker0网桥的网段中分配一个IP,这样同主机中的容器的IP是同一网段的自然可以通过IP相互访问。
演示:
[[email protected] ~]# ifconfig
这里看到我的这台机器中的docker0的网桥的地址为172.17.0.1,这台机器中启动的所有的docker的容器的IP都是这个网段的。
[[email protected] ~]# docker ps #查看正在运行的docker容器
我这里有两个一个是registry一个是MySQL。
[[email protected] ~]# docker inspect 28b2c91d4be4|grep -i ipaddress #查看容器的IP
[[email protected] ~]# docker inspect 5708c1dcbdd7|grep -i ipaddress #查看容器的IP
可以发现这两个容器的IP地址果然都是172.17.0.1网段的。
(2)docker DNS server
通过 IP 访问容器虽然满足了通信的需求,但还是不够灵活。因为我们在部署服务之前可能不能确定IP。比如:现在部署一个Nginx web服务,但是每次容器启动分配的IP地址都会改变,我们无法通过固定的IIP地址去访问web服务,这样每次访问时都要查看IP,非常麻烦,对于这个问题,可以通过 docker 自带的 DNS 服务解决。
从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过"容器名"通信。方法很简单,只要在启动时用 --name 为容器命名就可以了。
演示:
#下面在同主机启动两个Ubuntu系统并指定--name:
[[email protected] ~]#docker run -it --network=brideg2 --name box1 ubuntu:net /bin/bash
[[email protected] ~]#docker run -it --name --network= brideg2 box2 ubuntu:net /bin/bash
我们发现使用--name,的容器名称可以ping通其他容器。
注意:使用 docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是无法使用 DNS 的。
(3) joined 容器
joined 容器是另一种实现容器间通信的方式。它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined 容器之间可以通过 127.0.0.1 直接通信。
演示:
#启动一个http服务
[[email protected] ~]# docker run -dit --name my-apache-app -p 8099:80 -v "/http":/usr/local/apache2/htdocs/ httpd
#创建一个Ubuntu容器容器并通过 --network=container: my-apache-app指定 jointed 容器为 my-apache-app
[[email protected] ~]# docker run -it --network=container:my-apache-app ubuntu:net /bin/bash
#使用命令去访问my-apache-app容器中的web页面
[email protected]:/# curl 127.0.0.1
此时我们发现访问成功!原因是:我们分别查看着两个容器的IP:
Ubuntu:
http:
我们发现两个容器的网卡 mac 地址与 IP 完全一样,它们共享了相同的网络栈。所以Ubuntu容器可以使用127.0.0.1直接访问http容器的web服务。
(4) 补充
docker run 命令的参数介绍:
-h 运行容器时指定主机名,这样我们可以使用主机名去与容器通信。
--link=容器名 别名 ,这样使用--link连接的容器间就可以使用主机名进行通信。
-p host_port:container_port 端口映射,容器的服务端口映射到宿主机。
-P container_port 端口映射,映射到宿主机的任意空闲端口。
容器的访问控制
容器访问外部网络:两种方法:
- sysctl -w net.ipv4.ip_forward=1 (设置宿主机的开启数据转发)
- 启动Docker服务的时候设定--ip-forward=true,docker会自动打开宿主机系统的转发服务
外部访问容器:这里很简单,通过docker run -h hostname -p 端口映射,来实现外部访问容器。
3.跨主机间的容器通信
(1)Docker网桥实现跨主机容器连接
在同一宿主机下docker容器之间是可以相同连通的。这是因为默认的docker容器在同一宿主机下,所有容器分配的IP处于同一个地址段的,相互之间可以ping通;当我们使用ifconfig命令查看IP时会发现,其中有一个docker0的网桥,docker容器通过docker0 网桥实现同一主机间中,容器的IP地址分配和访问,这就保证了所有的容器在同一地址段。
虽然这些IP地址在同一宿主机中是处于同一网段并且相互之间可以通信,但是如果在不同宿主机之间,如果网桥的网段不同,容器之间还是不可能实现跨住进的通信,那么我们可以将每个主机下的容器的网段都处于同一网段,这样,就可以实现跨主机的访问啦,这也是Docker容器默认跨主机之间的连接方法的第一种:网桥实现。
上图就是网桥方式实现跨主机的连接,但是缺点也很明显,宿主机和容器的IP处于同一网段,如果在局域网下,IP地址是有限的,那么一个容器占据一个IP地址,IP地址很快就会被用光,这就是个不友好的现象,所以这种方式仅仅只用来学习测试使用。
实战操作:
实验环境:
主机名 | IP | Gateway | Netmask | |
---|---|---|---|---|
Host1 | 192.168.130.130 | 192.168.130.2 | 255.255.255.0 | |
Host2 | 192.168.130.131 | 192.168.130.2 | 255.255.255.0 |
① 下载网桥管理工具
yum install -y bridge-utils
② 分别在docker主机上建立网桥
Host1: $ sudo brctl addbr br0
Host2: $ sudo brctl addbr br0
③ 为网桥分配一个同网段IP
Host1: $ sudo ifconfig br0 192.168.130.10 netmask 255.255.255.0
Host2: $ sudo ifconfig br0 192.168.130.20 netmask 255.255.255.0
④ 桥接本地网卡
Host1: $ brctl addif br0 eth0
Host2: $ brctl addif br0 eth0
⑤ 修改docker配置文件
$ Host1 vim /etc/default/docker
$ Host2 vim /etc/default/docker
改成:Host1: DOCKER_OPTS=” -b=br0 –fixed-cidr=‘192.168.130.64/26“
Host2: DOCKER_OPTS=” -b=br1 –fixed-cidr=‘192.168.130.128/26“
这里的:
-b :用来指定容器连接的网桥的名字。
--fixed-cidr :用来限定容器分配的IP地址的范围。
⑥重启docker
$ Host1 systemctl daemon-reload
$ Host1 systemctl restart docker
$ Host2 systemctl daemon-reload
$ Host2 systemctl restart docker
⑦ 测试
这里在host1和host2中各启动一个容器,然后相互ping对方容器IP,如果可以ping桶表示配置成功。
(2)Open vSwitch 实现跨主机容器通信
Open vSwitch是一个高质量、多层虚拟交换机。使用Apache2.0许可协议,旨在通过编程扩展,使庞大的网络自动化(配置、管理、维护),同时还支持标准的管理接口和协议。
实战操作:
实验环境:
主机名 | IP | Gateway | Netmask | |
---|---|---|---|---|
Host1 | 192.168.130.130 | 192.168.130.2 | 255.255.255.0 | |
Host2 | 192.168.130.131 | 192.168.130.2 | 255.255.255.0 |
虚拟机网段:
主机名 | 网段 |
---|---|
Host1 | 192.168.1.1 |
Host2 | 192.168.2.1 |
操作步骤:
- 在虚拟机中建立ovs网桥
- 添加gre连接
- 配置docker容器虚拟网桥接
- 为虚拟网桥添加ovs接口
- 添加不同Docker容器网段路由
① 安装Open vSwitch并启动[[email protected] Host1~]#yum install -y openvswitch.x86_64
[[email protected] Host1~]#systemctl start openvswitch
② 安装网桥
[[email protected] Host1~]# yum install -y bridge-utils
③ 建立ovs网桥并添加GRE接口
[[email protected] Host1~]# ovs-vsctl add-br obr0
[[email protected] Host1~]# ovs-vsctl add-port obr0 gre0
④ 设置远程的网桥连接
[[email protected] Host1~]#ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.130.131
#查看osv网桥配置
[[email protected] Host1~]#ovs-vsctl show
⑤ 设置docker的虚拟网桥
[[email protected] Host1~]#brctl addbr br0
[[email protected] Host1~]#ifconfig br0 192.168.1.1 netmask 255.255.255.0
[[email protected] Host1~]#brctl addif br0 obr0
[[email protected] Host1~]#brctl show
⑥ 设置路由规则
[[email protected] Host1~]#ip route add 192.168.2.0/24 via 192.168.130.131 dev ens33
同理host2也需要按照上述方式配置。最后两个容器之间就可以通信。
(3)Weave实现跨主机容器通信
Weave是由weaveworks公司开发的解决Docker跨主机网络的解决方案,它能够创建一个虚拟网络,用于连接部署在多台主机上的Docker容器,这样容器就像被接入了同一个网络交换机,那些使用网络的应用程序不必去配置端口映射和链接等信息。
外部设备能够访问Weave网络上的应用程序容器所提供的服务,同时已有的内部系统也能够暴露到应用程序容器上。Weave能够穿透防火墙并运行在部分连接的网络上,另外,Weave的通信支持加密,所以用户可以从一个不受信任的网络连接到主机。
原理:
Weave会在主机上创建一个网桥,每一个容器通过 veth pair 连接到该网桥上,同时网桥上有个 Weave router 的容器与之连接,该router会通过连接在网桥上的接口来抓取网络包(该接口工作在Promiscuous模式)。
在每一个部署Docker的主机(可能是物理机也可能是虚拟机)上都部署有一个W(即Weave router),它本身也可以一个容器的形式部署。Weave run的时候就可以给每个veth的容器端分配一个ip和相应的掩码。veth的网桥这端就是Weave router容器,并在Weave launch的时候分配好ip和掩码。
Weave网络是由这些weave routers组成的对等端点(peer)构成,每个对等的一端都有自己的名字,其中包括一个可读性好的名字用于表示状态和日志的输出,一个唯一标识符用于运行中相互区别,即使重启Docker主机名字也保持不变,这些名字默认是mac地址。
每个部署了Weave router的主机都需要将TCP和UDP的6783端口的防火墙设置打开,保证Weave router之间控制面流量和数据面流量的通过。控制面由weave routers之间建立的TCP连接构成,通过它进行握手和拓扑关系信息的交换通信。 这个通信可以被配置为加密通信。而数据面由Weave routers之间建立的UDP连接构成,这些连接大部分都会加密。这些连接都是全双工的,并且可以穿越防火墙。
实战操作:
实验环境:
主机名 | IP | Gateway | Netmask | |
---|---|---|---|---|
Host1 | 192.168.130.130 | 192.168.130.2 | 255.255.255.0 | |
Host2 | 192.168.130.131 | 192.168.130.2 | 255.255.255.0 |
① 下载复制weave二进制执行文件
[[email protected] Host1~]#git clone https://github.com/weaveworks/weave
[[email protected] Host1~]#cp -p /root/weave/weave /usr/bin/
[[email protected] Host1~]#cd /usr/bin/
#查看weave版本
[[email protected] Host1~]#weave version
② 启动weave服务
[[email protected] Host1~]# weave launch --no-detect-tls #注意第一次启动会在docker中拉取相应的镜像
③ 运行一个容器
[[email protected] Host1~]#docker run -it ubuntu:net /bin/bash
然后Ctrl+p+q退出容器,并且让容器后台运行
④ 进入容器
[[email protected] Host1~]#weave attach 192.168.2.1/24 c45932ef7da4
注意:这里的192.168.2.1/24 是默认的给当前容器分配的一个weaveIP
之后再host2宿主机中也执行以上的命令,并且在“weave attach 192.168.2.1/24 容器ID” 这里分配一相同网段的不同IP。
此时通过这个ethwe中的IP,去相同ping对方容器,这里就可以相同访问:
原文地址:https://blog.51cto.com/14048416/2384509