Docker跨主机网络(overlay)的实现
一、Docker跨主机通信
Docker跨主机网络方案包括:
docker原生的overlay和macvlan。
第三方方案:常用的包括flannel、weave和calico。
docker通过libnetwork以及CNM将上述各种方案与docker集成在一起。
libnetwork是docker容器网络库,最核心的内容是其定义的ContainerNetworkModel(CNM),这个模型对容器网络进行了抽象,由以下三类组件组成:
1.1Sandbox
Sandbox是容器的网络栈,包含容器的interface、路由表和DNS设置。LinuxNetworkNamespace是Sandbox的标准实现。Sandbox可以包含来自不同Network的Endpoint。也就是说Sandbox将一个容器与另一个容器通过Namespace进行隔离,一个容器包含一个sandbox,每一个sandbox可以有多个Endpoint隶属于不同的网络。
1.2Endpoint
Endpoint的作用是将Sandbox接入Network。Endpoint的典型实现是vethpair。一个Endpoint只能属于一个网络,也只能属于一个Sandbox。
1.3Network
Network包含一组Endpoint,同一Network的Endpoint可以直接通信。Network的实现可以是LinuxBridge、VLAN等。
图片截至CLOUDMAN博客。
libnetwork下包含上述原生的driver以及其他第三方driver。
none、bridge网络前面已经介绍。bridge就是网桥,虚拟交换机,通过veth连接其与sandbox。
二、Dockeroverlay网络
2.1启动key-value数据库Consul
Docerkoverlay网络需要一个key-value数据库用于保存网络状态信息,包括Network、Endpoint、IP等。Consul、Etcd和ZooKeeper都是Docker支持的key-vlaue软件。
consul是一种key-value数据库,可以用它存储系统的状态信息等,当然这里我们并不需要写代码,只需要安装consul,之后docker会自动进行状态存储等。最简单的安装consul数据库的方法是直接使用docker运行consul容器。
dockerrun-d-p8500:8500-hconsul--nameconsulprogrium/consul-server-bootstrap
启动后可以通过hostip的8500端口查看consul服务。
为了让consul发现各个docker主机节点,需要在各个节点上进行配置。修改各个节点dockerdaemon的配置文件/etc/systemd/system/docker.service。在ExecStart最后添加
--cluster-store=consul://
:8500--cluster-advertise=ens3:2376
其中表示运行consul容器的节点IP。ens3为当前节点的ip地址对应的网卡,也可以直接填写ip地址。
以上是单机版consul的安装方法,建议采用集群模式,集群模式安装方式见https://www.consul.io/intro/getting-started/join.html。
2.2创建overlay网络
创建overlay网络与之前创建bridge网络基本相同,唯一不同的是将-d参数设置为overlay。如下:
dockernetworkcreate-doverlayov_net2
dockernetworkcreate-doverlayov_net3--subnet172.19.0.0/24--gateway172.19.0.1
只需要在一个节点中进行上述创建过程,其他节点自动会识别到该网络,原因正是在于consul的服务发现功能。
之后创建容器的时候只需要指定--network参数为ov_net2即可。
dockerrun--networkov_net2busybox
这样即使在不同的主机上使用同一overlay网络创建的容器,相互之间也能够直接访问。
2.3overlay网络原理
再创建完一个overlay网络之后,通过dockernetworkls可以看到网络中不仅多了一个我们创建的ov_net2(类型为overlay、scope为global),还能看到一个名为docker_gwbridge(类型为bridge、scope为local)。这其实就是overlay网络的工作原理所在。
通过brctlshow可以看出,每创建一个网络类型为overlay的容器,则docker_gwbridge下都会挂载一个vethxxx,这说明确实overlay容器是通过此网桥进行对外连接的。
简单的说overlay网络数据还是从bridge网络docker_gwbridge出去的,但是由于consul的作用(记录了overlay网络的endpoint、sandbox、network等信息),使得docker知道了此网络是overlay类型的,这样此overlay网络下的不同主机之间就能够相互访问,但其实出口还是在docker_gwbridge网桥。
none、bridge网络前面已经介绍。bridge就是网桥,虚拟交换机,通过veth连接其与sandbox。
三,让外网能否访问容器的端口映射方法:
[root@localhost~]#ss-lnt
//查看一下套接字(IP地址和端口)
1)手动指定端口映射关系
[root@localhost~]#dockerpullnginx
[root@localhost~]#dockerpullbusybox
[root@localhost~]#dockerrun-itdnginx:latest //不加任何参数开启一台nginx虚拟机 [root@localhost~]#dockerps //查看容器信息
[root@localhost~]#dockerinspectvigorous_shannon //查看容器详细信息(现在看IP)
[root@localhost~]#curl172.17.0.2
[root@localhost~]#dockerrun-itd--nameweb1-p90:80nginx:latest //开启一台虚拟机指定链接端口
第二台访问
[root@localhost~]#curl192.168.1.11:90
2)从宿主机随机映射端口到容器。
[root@localhost~]#dockerrun-itd--nameweb2-p80nginx:latest //开启一台虚拟机随机链接端口 [root@localhost~]#dockerps
[root@localhost~]#curl192.168.1.11:32768
3)从宿主机随机映射端口到容器,容器内所有暴露端口,都会一一映射。
[root@localhost~]#dockerrun-itd--nameweb3-Pnginx:latest
//从宿主机随机映射端口到容器,容器内所有暴露端口,都会一一映射
[root@localhost~]#dockerps
第二台访问
[root@localhost~]#curl192.168.1.11:32769
四,Join容器:container(共享网络协议栈)
容器和容器之间。
[root@localhost~]#dockerrun-itd--nameweb5busybox:latest //基于busybox开启一台虚拟机 [root@localhost~]#dockerinspectweb5
[root@localhost~]#dockerrun-itd--nameweb6--networkcontainer:web5busybox:latest //开启另一台虚拟机 [root@localhost~]#dockerexec-itweb6/bin/sh //进入web6 /#ipa
/#echo123456>/tmp/index.html /#httpd-h/tmp/ //模拟开启httpd服务 [root@localhost~]#dockerexec-itweb5/bin/sh //进入web5 /#ipa
#wget-O--q127.0.0.1 //这时会发现,两个容器的IP地址一样。
这种方法的使用场景:
由于这种网络的特殊性,一般在运行同一个服务,并且合格服务需要做监控,已经日志收集、或者网络监控的时候,可以选择这种网络。
五,docker的跨主机网络解决方案
overlay的解决方案
实验环境:
docker01 | docker02 | docker03 |
---|---|---|
1.11 | 1.12 | 1.20 |
暂时不考虑防火墙和selinux安全问题。
将3台dockerhost防火墙和selinux全部关闭,并且分别更改主机名称。
[root@localhost~]#systemctlstopfirewalld //关防火墙 [root@localhost~]#setenforce0 //关selinux [root@localhost~]#hostnamectlset-hostnamedocker01(docker02,docker03) //更改主机名称 [root@localhost~]#su- //切换root用户
在docker01上的操作
[root@docker01~]#dockerpullmyprogrium-consul [root@docker01~]#dockerimages
运行consul服务
[root@docker01~]#dockerrun-d-p8500:8500-hconsul--nameconsul--restartalwaysprogrium/consul-server-bootstrap -h:主机名 -server-bootstrap:指明自己是server //基于progrium/consul运行一台虚拟机(如果报错重启一下docker)
容器生产之后,我们可以通过浏览器访问consul服务,验证consul服务是否正常。访问dockerHost加映射端口。
[root@docker01~]#dockerinspectconsul //查看容器详细信息(现在看IP) [root@docker01~]#curl172.17.0.7
浏览器查看
修改docker02和docker03的docker配置文件
[root@docker02~]#vim/usr/lib/systemd/system/docker.service#13行添加 ExecStart=/usr/bin/dockerd-Hunix:///var/run/docker.sock-Htcp://0.0.0.0:2376--cluster-store=consul://192.168.1.11:8500--cluster-advertise=ens33:2376 //把本机的/var/run/docker.sock通过ens33:2376,存到192.168.1.11:8500的consul服务上 [root@docker02~]#systemctldaemon-reload [root@docker02~]#systemctlrestartdocker
返回浏览器consul服务界面,找到KEY/NALUE--->DOCKER---->NODES
在docker02上自定义一个网络
[root@docker02~]#dockernetworkcreate-doverlayov_net1 //创建一个overlay网络 [root@docker02~]#dockernetworkls //查看网络
在docker03上查看一下网络,可以看到也生成了ov_net1网络
[root@docker03~]#dockernetworkls
浏览器查看一下
修改docker01的docker配置文件,在docker01上查看一下网络,可以看到也生成了ov_net1网络
[root@docker01~]#vim/usr/lib/systemd/system/docker.service#13行添加 ExecStart=/usr/bin/dockerd-Hunix:///var/run/docker.sock-Htcp://0.0.0.0:2376--cluster-store=consul://192.168.1.11:8500--cluster-advertise=ens33:2376 //把本机的/var/run/docker.sock通过ens33:2376,存到192.168.1.11:8500的consul服务上 [root@docker02~]#systemctldaemon-reload [root@docker02~]#systemctlrestartdocker //重启docker [root@docker03~]#dockernetworkls //查看网络
Docker三台各自基于网络ov_net1运行一台虚拟机测试三台是否能互相ping通
[root@docker01~]#dockerrun-itd--namet1--networkov_net1busybox [root@docker02~]#dockerrun-itd--namet2--networkov_net1busybox [root@docker03~]#dockerrun-itd--namet3--networkov_net1busybox [root@docker01~]#dockerexec-itt1/bin/sh [root@docker02~]#dockerexec-itt2/bin/sh [root@docker03~]#dockerexec-itt3/bin/sh
/#ping10.0.0.2
/#ping10.0.0.3
/#ping10.0.0.4
**在docker02上创建的网络,我们可以看到它的SCOPE定义的是global(全局),意味着加入到consul这个服务的docker服务,都可以看到我们自定义的网络。
同理如果是用此网络创建的容器,会有两张网卡。
默认这张网-卡的网段是10.0.0.0网段,如果想要docker01也可能看到这个网络,那么也只需在docker01的docker配置文件添加相应内容即可。
同理,因为是自定义网络,符合自定义网络的特性,可以直接通过docker容器的名称相互通信,当然也可以在自定义网络的时候,指定它的网段,那么使用此网络的容器也可以指定IP地址。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。