Docker多主机网络(weave)

此文档为翻阅cloudman的每天5分钟玩转docker技术的读书笔记。

weave
软件版本
docker:17.09
weave:2.1.3
项目文 档:https://www.weave.works/docs/net/latest/overview/
项目地址:https://github.com/weaveworks/weave
环境信息
container-1 192.168.111.161
container-2 192.168.111.162

概述

weave是weaveworks开发的容器网络解决方案,weave会创建一个大的二层网络,来将各个host上的容器连接起来,容器与容器之间可以直接通信,无须nat和端口映射,weave还提供dns服务,使容器可以直接通过hostname访问。weave不需要依赖k\v服务,而是在每个主机上运行一个weave容器路由器。来根据不同的主机交换路由信息。

注意点:
1、一个Weave网络是由一定数量的Weave节点构成的。每个Weave路由器运行在不同的宿主机上。

2、Weave网络中的每个节点都有一个名字,默认是Weave网卡的地址。还有一个人类便于识别的名称,默认是主机名,也可以在Weave启动的时候指定一个名称。

3、Weave路由器节点之间会建立TCP连接,通过TCP连接,进行心跳检测和交换路由信息。通过配置可以让这条链接进行加密处理。

4、Weave路由器节点之间也会建立UDP连接,通过UDP连接,进行网络数据包的封装。同样也可以将UDP链接进行加密处理。

Weave路由器节点之间的连接(TCP连接或者UDP连接)可以穿透防火墙,意味着,Weave网络可用于跨数据中心的Docker通信。

5、Weave网络会在每个宿主机上创建一个网桥,每个容器通过veth pair连接到这个Weave 网桥。容器里面的veth网卡会获取到Weave网络分配给的IP地址和子网掩码。

6、Weave网络在不同宿主机之间路由数据的方法有两种:fast data path模式(完全工作在内核态),sleeve模式,在这种模式中,发往非本地容器的数据会被内核捕获,然后交给用户态的Weave网络路由器处理,通过UDP发送到其他的Weave节点路由器,然后注入到内核空间,最后再转发到本地的容器中。

7、Weave网络路由器会学习其他节点特定的MAC地址,然后将已知的信息和拓扑结合起来。

8、Weave网络可以在partially connected路由数据,通过拓扑交换。比如下图中:节点1 直接连接着 节点2和节点3,如果节点1 先要发送数据到 节点4或者节点5 ,那么先必须发送到节点3。

Weave 网络如何了解网络拓扑?
官网地址:https://www.weave.works/docs/net/latest/concepts/network-topology/

Peers之间的拓扑交流

连接到Weave网络的节点会捕获其他Peers节点的拓扑信息。Weave节点会将自己已知的拓扑,和改变的内容传递给其他节点,以便于所有的Weave Peers了解整过网络拓扑。

Weave节点之间的通信建立在TCP上的,有两种方法:

基于STP(生成树)的广播方法
基于邻居Gossip方法(八卦算法)
以下情况,拓扑信息会发送:

当一个连接新加入进来的时候,如果远程节点似乎是新加入到Weave网络中的,那么会发送整个网络拓扑,并且增量更新,广播节点两端的连接。
当一个连接被标记为已经建立,则意味着远端可以从本端接受UDP报文,然后广播一个包含本端信息的数据包。
当一个连接断开,一个包含本端信息的报文被广播。
周期性的定时器,整个拓扑信息被gossip给邻居,这是为了拓扑敏感的随机分布系统。这是为了防止由于频繁的拓扑变化,造成广播路由表过时,而使前面提到的广播没有到达所有的peers。
如果Peers更新拓扑信息之后,发现有一个Peer已经离线,那么就会清除掉这个Peer相关的所有的信息。

拓扑过期怎么办?

将拓扑变化信息广播给所有peers不是立即发生的。这就意味着,很有可能一个节点有过期的网络拓扑视图。

如果目的peer的数据包仍然可达,那么过期的拓扑可能会导致一次低效的路由选择。

如果过期的拓扑中目的peer不可达,那么数据包会被丢弃,对于很多协议(如TCP),数据发送会在稍后重新尝试,在这期间拓扑信息应当被正确更新。

weave安装

container-1和container-2上
安装weave

1
2
curl -L git.io/weave -o /usr/local/bin/weave
chmod a+x /usr/local/bin/weave

在container-1上启动weave
在 host1 中执行 weave launch 命令,weave的组件都是以容器启动的,weave 会从 docker hub 下载最新的 image 并启动容器。

10.32.0.0/12是weave网络使用的默认subnet,如果需要改变(所有host都要改)

1
weave launch --ipalloc-range 10.2.0.0/16

weave 运行了三个容器:
weave 是主程序,负责建立 weave 网络,收发数据 ,提供 DNS 服务等。
weavevolumes容器提供卷存储
weavedb容器提供数据存储

创建了一个linux bridge桥

和weave网络

container-2
执行

1
weave launch 192.168.111.161

这里指定的container-1的地址,这样container-2和container-1才会加入到同一个网络,也可以写多个地址,格式为 ip_addr ip_addr.

两个host要互通,首先要确认建立了集群

测试
在container-1上执行
特别说明:声明环境变量的作用是告诉后续的docker命令都发给weave proxy进行处理。
声明环境变量

1
2
eval $(weave env)
docker run -itd --name bbox1 busybox

如果要恢复之前的环境,可执行

1
eval $(weave env --restore)

在container-2上执行

1
2
eval $(weave env)
docker run -itd --name bbox2 busybox

bbox1 ping bbox2

原理

单台host架构图

bbox1和bbox2的地址为10.32.0.1/12、10.44.0.0/12, 子网掩码都是12位的,实际上这3个ip都位于 weave网络的10.32.0.0/12,通过container-1和container-2上的vxlan的遂道连接在一起。

查看bbox1的网络接口

bbox1有两个网络接口eth0和ethwe,eth0桥接的是默认docker0网络。ethwe和宿主机weave网卡有关ethwe@if39表示ethwe对应编号39的interface。

在宿主机ip a看见了39的interface,vethwepl19152和ethwe是一对veth-pair,同时vethwep19152还挂载在weave 桥上。

同时挂载的还有vethwe-bridge,ip -d link查看

vethwe-bridge和vethwe-datapath是一对veth-pair,但vethwe-datapath的父设备是datapath,其中datapath是个openvswitch网桥,vxlan-6784是一个vxlan-interface,其父设备也是datapath,weave主机间是通过vxlan建立的遂道通信,等于说,veth-pair vethwe-bridge和vethwe-datapath将linux-bridge的weave桥和datapath连接在一起,其中,weave桥负责容器接入weave网络,datapath负责主机间建立vxlan隧道并收发数据。

多host时网络架构图

1、当在container-1上的bbox1 ping container-2上bbox2时

2、将数据包给ethwe

2、ethwe和vethwep是veth-pair,所以数据包到了宿主机的weave桥上,然后给vethwe-bridge,然后通过veph-pair的另外一端vethwe-datapath到datapath,通过vxlan发送给container-2。
3、container-2的vxlan接口收到报文后会给datapath然后通过vethwe-datapath到weave桥收到报文后,根据目的IP地址将数据包转发给bbox2。

weave网络隔离

默认weave使用一个大的subnet(10.32.0.0/12)所有主机容器都从这个地址空间分配ip,因为是同一个subnet,容器可以直接通信,如果要隔离,可以通过环境变量WEAVE_CIDR=net:xxx.xxx.xxx/24指定网段,但需要注意的是这个网段也不是随便写的,要在10.32.0.0/12这个大子网范围内。

1
docker run -itd -e WEAVE_CIDR=net:xxx.xxx.xxx.xxx/24 image_name

weave与外网连接
宿主机访问weave网络的容器
因为weave默认是一个私有的vxlan网络,默认与外部网络隔离,要想host访问,需要将host加入weave。

10.32.0.2会被分配到weave网桥上

此时就可以ping通了

如果其他主机想访问这台host上的容器,只需要添加一条默认路由将下一跳指向host的地址。
container-2访问container-1上的bbox1
只需要在container-2上添加

1
ip route add 10.32.0.0/12 via 192.168.111.161

IPAM
默认weave使用一个大的subnet(10.32.0.0/12)所有主机容器都从这个地址空间分配ip一个大二层。

参考链接

http://ibash.cc/frontend/article/59/