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
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
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
docker run -itd --name bbox1 busybox
`

container-2

1
docker run -itd --name bbox2 busybox

原理

vxlan

容器内网卡和物理机上一veth-xxx是一对veth-pair,同时物理机的veth-xxx挂载在docker0这个bridge上。

容器内默认路由是给10.2.71.1

10.2.71.1是docker0

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

flannel并不会创建什么网桥,同一主机通过docker0连接,不同主机通过flanel1.1建立vxlan遂道连接。

host-gw

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

修改etcd

导入新配置

重启etcd

1
systemctl restart etcd

重启container-1和container-2上的flannel
查看路由表,发现生成了一条到container-2的明细路由

mtu变成了1500

重新修改docker.service

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

修改mtu为1500

重启docker

1
systemctl restart docker

测试连通性

面对 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