Docker多主机网络(flannel)

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

flannel
软件版本
docker:17.09
etcd:etcd-3.2.7-1
flannel:flannel-0.7.1-2
项目地址:https://github.com/coreos/flannel
项目地址:https://github.com/coreos/etcd

环境信息
container-1 192.168.2.110 etcd
container-2 192.168.2.112 docker
container-3 192.168.2.113 docker

flannel是core os开发出的docker多host的网络解决方案,flannel为每个宿主机分配一个subnet,每个宿主机上都有一个flannel的agent端,通过这个agent端可以进行根其他宿主机网络信息的共享,创建flannel网卡生成路由信息,建立vxlan遂道,各个宿主机的网络信息存储在etcd这个key-value软件中。

flannel的backend vlxan、host-gw、udp等。

安装

安装etcd

1
yum install etcd -y

配置etcd

1
cp /etc/etcd/etcd.conf /etc/etcd/etcd.conf.bak

vim /etc/etcd/etcd.conf

1
2
3
4
5
ETCD_NAME=default                                           #节点名称
ETCD_DATA_DIR="/var/lib/etcd/default.etcd" #数据存放位置
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001" #监听客户端地址
ETCD_ADVERTISE_CLIENT_URLS="http://etcd:2379,http://etcd:4001" #通知客户端地址

启动服务

1
systemctl start etcd

检查服务

导入网络配置key

先将配置信息写到文件 flannel-config.json 中,内容为:
[root@container-0 ~]# cat flannel-config.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{

"Network": "10.2.0.0/16",

"SubnetLen": 24,

"Backend": {

"Type": "vxlan"

}

}

Network 定义该网络的 IP 池为 10.2.0.0/16。

SubnetLen 指定每个主机分配到的 subnet 大小为 24 位,即10.2.X.0/24。

Backend 为 vxlan,即主机间通过 vxlan 通信,后面我们还会讨论host-gw。

将配置存入etcd

/docker-test/network/config 是此 etcd 数据项的 key,其 value 为 flannel-config.json 的内容。key 可以任意指定,这个 key 后面会作为 flanneld 的一个启动参数。执行 etcdctl get 确保设置成功。

测试get value

在container-1和container-2上执行

安装flannel

1
yum install flannel -y

配置flannel

1
cp  /etc/sysconfig/flanneld /etc/sysconfig/flanneld.bak

ip写etcd的ip

启动flannel

1
2
3
systemctl enable flannel
systemctl start flannel

验证可以看见flannel网卡已经出来了

配置docker使用flannel

1
cat /run/flannel/subnet.env  

将flannel_subnet和flannel_mtu写入docker.service
编辑docker.service

1
vim /usr/lib/systemd/system/docker.service

bip和mtu为上图cat /run/flannel/subnet.env的配置项。
重启docker

1
2
systemctl daemon-reload
systemctl restart docker

docker会10.2.71.1配置到docker0上,同时生成一条路由

同主机的docker使用docker0进行通信,跨主机的使用flannel1.1转发

1
ps -ef|grep docker

测试连通性

flannel不会创建新的网络,会使用默认的bridge网络
启动容器
container-1

1
2
3
docker run -itd --name bbox1 busybox  
````
container-2

docker run -itd –name bbox2 busybox

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_11.png)

![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_12.png)

![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_13.png)

### 原理
#### vxlan
容器内网卡和物理机上一veth-xxx是一对veth-pair,同时物理机的veth-xxx挂载在docker0这个bridge上。
![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_14.png)

容器内默认路由是给10.2.71.1
![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_15.png)

10.2.71.1是docker0
![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_16.png)

查看host路由,是10.2.0.0/16这个subnet的包会交给flannel1.1,,flannel1.1封装成udp包通过ens3,发送出去。container-2 收到包解封装,发现数据包目的地址为 10.2.36.2,根据路由表将数据包发送给 flannel1..1,并通过 docker0 到达 bbox2。

![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_17.png)


![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_18.png)

![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_19.png)

flannel并不会创建什么网桥,同一主机通过docker0连接,不同主机通过flanel1.1建立vxlan遂道连接。
![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_20.png)

#### host-gw
flannel支持的backend;
VXLAN: 使用Linux的VxLan;默认的VNI 是 1 ;默认的UDP端口是 8472;
host-gw: 创建IP路由的方式, 不会对数据进行封装;
UDP: 使用UDP 8285 端口;
AliVPC: 不能用于生产;
Alloc: 不能用于生产;
AWS VPC: 不能用于生产;
GCE: 不能用于生产;


修改etcd
![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_21.png)
导入新配置
![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_22.png)
重启etcd

systemctl restart etcd

1
2
3
4
5
6
7
8
重启container-1和container-2上的flannel  
查看路由表,发现生成了一条到container-2的明细路由
![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_23.png)

mtu变成了1500
![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_24.png)

重新修改docker.service

vim /usr/lib/systemd/system/docker.service

1
2
3
修改mtu为1500  

重启docker

systemctl restart docker

测试连通性  
![](https://image-1251900790.cos.ap-chengdu.myqcloud.com/image/flnnel_25.png)

面对 host-gw 和 vxlan 这两种 backend 做个简单比较。    
host-gw 把每个主机都配置成网关,主机知道其他主机的 subnet 和转发地址。vxlan 则在主机间建立隧道,不同主机的容器都在一个大的网段内(比如 10.2.0.0/16)。  

虽然 vxlan 与 host-gw 使用不同的机制建立主机之间连接,但对于容器则无需任何改变,bbox1 仍然可以与 bbox2 通信。  

由于 vxlan 需要对数据进行额外打包和拆包,性能会稍逊于 host-gw。  

IPAM:  
flannel为每个主机自动分配独立的subnet,用户只需要指定一个大的地址段,每个host从这个地址段里面在细分。  

网络隔离:    
flannel都用的vxlan的vni1没有实现网络隔离。
flannel 为每个主机分配了独立的 subnet,但 flannel.1 将这些 subnet 连接起来了,相互之间可以路由。本质上,flannel 将各主机上相互独立的 docker0 容器网络组成了一个互通的大网络,实现了容器跨主机通信。flannel 没有提供隔离。  



http://ibash.cc/frontend/article/58/  
http://www.cnblogs.com/CloudMan6/p/7270551.html