跨主机通信
通过docker网络驱动:
- Overlay:基于vxlan封装实现docker原生overlay网络
- Macvlan:docker主机网卡接口逻辑上分为多个子接口,每个子接口标识一个vlan。容器接口直接连接docker主机
- 网卡接口:通过路由策略转发到另一台docker主机
通过第三方网络项目:
-
隧道方案:
- Flannel:支持UDP和VLAN封装传输方式
- Weave:支持UDP(sleeve模式)和VXLAN(优先fastdb模式)
- OpenvSwitch:支持VXLAN和GRE封装
-
路由方案:
- Calico:支持BGP协议和IPIP隧道。每台宿主机作为虚拟路由,通过BGP协议实现不同主机容器间通信。
直接路由方式(通过内核转发)
实验环境:
由于使用容器的ip进行路由,就需要避免不同主机上的容器使用了相同的ip,为此我们应该为不同的主机分配不同的子网来保证。
主机1的地址为:192.168.248.128
主机2的地址为:192.168.248.129
主机1上docker容器分配的子网:172.17.1.0/24
主机2上docker容器分配的子网:172.17.2.0/24
思路:
从container1发送container2的数据包,首先发往container1的网关docker0,然后通过查找主机1的路由表得知需要将数据包发往主机2,数据包达到主机2后再转发给主机2的docker0,最后到达container2 。
过程:
1、配置docker0的ip地址
主机一修改daemon.json文件,添加:
1 | { |
主机二同理,但是修改成2.252/24,然后重启docker
2、添加路由规则
主机一:
1 | route add -net 172.17.2.0 netmask 255.255.255.0 gw 192.168.248.128 |
主机二:
1 | route add -net 172.17.1.0 netmask 255.255.255.0 gw 192.168.248.129 |
3、配置路由转发
如果有iptables的话:
主机一:
1 | iptables -t nat -F POSTROUTING |
主机二:
1 | iptables -t nat -F POSTROUTING |
没有的话:
1 | echo 1 > /proc/sys/net/ipv4/ip_forward |
4、启动容器测试
主机一:
1 | docker run -it --name container1 centos /bin/bash |
主机二:
1 | docker run -it --name container2 centos /bin/bash |
通过Overlay网络
这块参照这位博主,万分感谢。
- 先提一下overlay网络
overlay在网络技术领域,指的是一种网络架构上叠加的虚拟化,其大体框架是对基础不进行大规模修改的条件下,实现应用在网络上的承载,并能与其他网络业务进行分离,并且以基于ip的基础网络技术为主。overlay技术是在现有的物理网络之上构建一个虚拟网络,上层应用只与虚拟网络相关。主要有三部分构成:
- 边缘设备:与虚拟机之间相连的设备
- 控制平面:主要负责虚拟隧道的建立维护以及主机可达性信息的通告
- 转发平面:承载overlay报文的物理网络
要想使用docker原生overlay网络,需要满足下列条件:
- docker运行在swarm
- 使用key-value存储的docker主机集群
使用键值存储搭建docker主机集群需要满足:
- 集群中主机连接到键值存储,docker支持consul、etcd和zookeeper等
- 集群中主机运行一个docker守护进程
- 集群中主机必须具有唯一的主机名,因为键值存储使用主机名来标识群成员
- 集群中Linux主机内核版本在3.12+,支持vxlan数据包处理,否则无法通行
(注:关于这块我在其他地方看的,也没做过测试,反正最好这样吧,如果有问题告诉我)
由于docker overlay网络需要一个key-value数据库用于保存网络状态信息,包括network、endpoint、ip等。consul、etcd和zookeeper都是。consul是一种键值数据库,我们这可以用它存储系统的状态信息。
实验环境:
server:192.168.248.129 kernel:4.4
client:192.168.248.130 kernel:4.4
1、安装consul(server上)
方式一:
1 | wget https://releases.hashicorp.com/consul/0.9.2/consul_0.9.2_linux_386.zip |
方式二:
1 | docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap |
2、启动consul(如果上一步用方法二就跳过)
1 | nohup consul agent -server -bootstrap -ui -data-dir /data/docker/consul \ |
注:-ui:consul的管理界面;-datadir:数据存储路径
3、各节点配置docker守护进程连接consul
server上:
1 | vim /lib/systemd/system/docker.service |
其中:
–cluster-store 指定 consul 的地址。
–cluster-advertise 告知 consul 自己的连接地址。
client上:
1 | vim /lib/systemd/system/docker.service |
4、放行防火墙
1 | firewall-cmd --add-port=8500/tcp --permanent |
5、打开web进行检查
6、创建一个overlay网络
1 | docker network create -d overlay ov_net |
此时详细查看这个网络的信息:
由于consul的自动发现,另一台主机会自动同步新建的网络。
7、使用overlay网络创建容器
server和client上:
1 | docker run -it --net=ov_net busybox |
此时我们可以查看容器内的网卡信息:
其中:eth0是和overlay进行通信,eth1是和主机的docker_gwbridge通信(docker_gwbridge为使用overlay网络的容器提供上外网的能力)
这里使用的是自动分配的ip,如果需要静态固定ip:
1 | 创建网络的时候: |
8、测试
通信过程:
1、docker为每一个overlay网络创建一个单独的命名空间,在这个命名空间里面创建一个br0的bridge。
2、在这个命名空间内创建网口并挂载到br0上,分别是vxlan0和一对veth pair端口(一端在br0上,另一端在container上)
3、vxlan0用于建立vxlan tunnel,vxlan端口的vni由docker-daemon创建时分配,只有具有相同的vni才能通信。
4、docker主机集群通过key/value存储共享数据,在7946端口上,相互之间通过gossip协议学
习各个宿主机上运行了哪些容器。守护进程根据这些数据来vxlan设备上生成静态MAC转发表。
5、vxlan设备根据MAC转发表,通过主机上的4789端口将数据发到目标节点。
6、根据流量包的vxlan隧道ID,将流量转发到对端宿主机的overlay网络的网络命名空间中。
7、宿主机的overlay网络的网络命名空间中的br0网桥,起到虚拟交换机的作用,在对端网络中,将流量根据MAC地址转发到对应容器内部。
查看namespace由于容器和overlay的网络的网络命名空间文件不在操作系统默认的/var/run/netns下,只能手动通过软连接的方式查看(此时要保证两个容器在运行):
1 | ln -s /var/run/docker/netns /var/run/netns |
在另外一台设备上进行查看会发现,都有一个2-9ff9fe9875的命名空间。
然后我们可以进入到这里面去查看相应的网桥和网口信息:
网桥上的插的网口:
然后查看vxlan接口的详细信息:
可以看见它的vni号为256
总结:
关于使用overlay通信存在着一下缺点:
1、由于vxlan网络与宿主机网络默认不再同一网络环境下,为了解决宿主机与容器的通信问题,docker为overlay网络中的容器额外增加了网卡eth1作为宿主机与容器通信的通道。这样在使用容器服务时,就必须根据访问性质的不同,选择不同的网卡地址,造成使用上的不便。
2、容器对外暴露服务仍然只能使用端口绑定的方式,外界无法简单地直接使用容器IP访问容器服务。
3、从上面的通信过程中来看,原生的overlay网络通信必须依赖docker守护进程及key/value存储来实现网络通信,约束较多,容器在启动后的一段时间内可能无法跨主机通信,这对一些比较敏感的应用来说是不可靠的。