一 简介
- Flannel是一种基于overlay(二层,数据链路层)网络的跨主机容器网络解决方案,也就是将TCP数据包封装在另一种网络包里面进行路由转发和通信,
- Flannel是CoreOS开发,专门用于docker多机互联的一个工具,让集群中的不同节点主机创建的容器都具有全集群唯一的虚拟ip地址
- Flannel使用go语言编写
二 Flannel实现原理
2.1原理说明
- Flannel为每个host分配一个subnet,容器从这个subnet中分配IP,这些IP可以在host间路由,容器间无需使用nat和端口映射即可实现跨主机通信
- 每个subnet都是从一个更大的IP池中划分的,flannel会在每个主机上运行一个叫flanneld的agent,其职责就是从池子中分配subnet
- Flannel使用etcd存放网络配置、已分配 的subnet、host的IP等信息
- Flannel数据包在主机间转发是由backend实现的,目前已经支持UDP、VxLAN、host-gw、AWS VPC和GCE路由等多种backend
2.2 Flannel网络结构图
多了一层封装,进行流量劫持
2.3 数据转发流程
1.容器直接使用目标容器的ip访问,默认通过容器内部的eth0发送出去。 2.报文通过veth pair被发送到vethXXX。 3.vethXXX是直接连接到虚拟交换机docker0的,报文通过虚拟bridge docker0发送出去。 4.查找路由表,外部容器ip的报文都会转发到flannel0虚拟网卡,这是一个P2P的虚拟网卡,然后报文就被转发到监听在另一端的flanneld。 5.flanneld通过etcd维护了各个节点之间的路由表,把原来的报文UDP封装一层,通过配置的iface发送出去。 6.报文通过主机之间的网络找到目标主机。 7.报文继续往上,到传输层,交给监听在8285端口的flanneld程序处理。 8.数据被解包,然后发送给flannel0虚拟网卡。 9.查找路由表,发现对应容器的报文要交给docker0。 10.docker0找到连到自己的容器,把报文发送过去。
三 Flannel安装配置
3.1 环境准备
删掉节点的所有容器 [root@7-5 ~]# docker ps -aq|xargs docker rm [root@7-6 ~]# docker ps -aq|xargs docker rm
3.2 安装etcd
在7-5上安装etcd #上传etcd包
[root@7-5 ~]# tar -xf etcd-v3.3.10-linux-amd64.tar.gz
[root@7-5 ~]# cd etcd-v3.3.10-linux-amd64/
[root@7-5 etcd-v3.3.10-linux-amd64]# ll
总用量 34296
drwxr-xr-x 11 6810230 users 4096 10月 11 2018 Documentation
-rwxr-xr-x 1 6810230 users 19237536 10月 11 2018 etcd
-rwxr-xr-x 1 6810230 users 15817472 10月 11 2018 etcdctl
-rw-r--r-- 1 6810230 users 38864 10月 11 2018 README-etcdctl.md
-rw-r--r-- 1 6810230 users 7262 10月 11 2018 README.md
-rw-r--r-- 1 6810230 users 7855 10月 11 2018 READMEv2-etcdctl.md
[root@7-5 etcd-v3.3.10-linux-amd64]# cp etcd /usr/bin/
[root@7-5 etcd-v3.3.10-linux-amd64]# cp etcdctl /usr/bin/
[root@7-5 etcd-v3.3.10-linux-amd64]# etcd --name etcd-131 -data-dir /var/lib/etcd --advertise-client-urls http://192.168.100.5:2379,http://127.0.0.1:2379 --listen-client-urls http://192.168.100.5:2379,http://127.0.0.1:2379 & #放后台运行
2021-08-24 18:44:03.848697 I | etcdmain: etcd Version: 3.3.10
2021-08-24 18:44:03.849033 I | etcdmain: Git SHA: 27fc7e2
2021-08-24 18:44:03.849045 I | etcdmain: Go Version: go1.10.4
2021-08-24 18:44:03.849055 I | etcdmain: Go OS/Arch: linux/amd64
。。。。。。
–name: etc取名 –data-dir: 定义数据路径 –advertise-client-urls: 建议使用的客户端通信url,该值用于etcd代理或etcd成员与etcd节点通信,即服务的url。 –listen-client-urls: 监听的用于客户端通信的url,对外提供服务的地址,客户端会连接到这里和 etcd 交互,同样可以监听多个。
[root@7-5 ~]# ps -ef|grep etcd
root 2393 1528 0 8月24 pts/0 00:01:40 etcd --name etcd-131 -data-dir /var/lib/etcd --advertise-client-urls http://192.168.100.5:2379,http://127.0.0.1:2379 --listen-client-urls http://192.168.100.5:2379,http://127.0.0.1:2379
etcdctl 是一个客户端连接工具
[root@7-5 ~]# etcdctl member list
8e9e05c52164694d: name=etcd-131 peerURLs=http://localhost:2380 clientURLs=http://127.0.0.1:2379,http://192.168.100.5:2379 isLeader=true
使用etcdctl连接ectd数据库,检查etcd的连通性
[root@7-5 ~]# etcdctl --endpoints http://127.0.0.1:2379 member list
8e9e05c52164694d: name=etcd-131 peerURLs=http://localhost:2380 clientURLs=http://127.0.0.1:2379,http://192.168.100.5:2379 isLeader=true
查看etcdctl版本
[root@7-5 ~]# etcdctl --version
etcdctl version: 3.3.10
API version: 2
3.3 安装Flannel
#上传flannel包
[root@7-6 ~]# tar -xf flannel-v0.11.0-linux-amd64.tar.gz
[root@7-6 ~]# mv flanneld /usr/bin/
[root@7-6 ~]# mv mk-docker-opts.sh /usr/bin/
[root@7-6 ~]# etcdctl set /coreos.com/network/config '{"Network": "10.0.0.0/16", "SubnetLen": 24, "SubnetMin": "10.0.1.0","SubnetMax": "10.0.20.0", "Backend": {"Type": "vxlan"}}' #添加flannel网络配置信息到etcd:是一个键值对
Network: 用于指定Flannel地址池 SubnetLen: 用于指定分配给单个宿主机的docker0的ip段的子网掩码的长度 SubnetMin: 用于指定最小能够分配的ip段 SudbnetMax: 用于指定最大能够分配的ip段,在上面的示例中,表示每个宿主机可以分配一个24位掩码长度的子网,可以分配的子网从10.0.1.0/24到10.0.20.0/24,也就意味着在这个网段中,最多只能有20台宿主机 Backend: 用于指定数据包以什么方式转发,默认为udp模式,host-gw模式性能最好,但不能跨宿主机网络
[root@7-5 ~]# etcdctl get /coreos.com/network/config
{"Network": "10.0.0.0/16", "SubnetLen": 24, "SubnetMin": "10.0.1.0","SubnetMax": "10.0.20.0", "Backend": {"Type": "vxlan"}}
3.4 启动Flannel
[root@7-5 ~]# /usr/bin/flanneld --etcd-endpoints="http://192.168.100.5:2379" --iface=192.168.100.5 --etcd-prefix=/coreos.com/network &
[root@7-5 ~]# ip a
[root@7-5 ~]# ps -ef |grep flan
root 42288 2404 0 22:45 pts/1 00:00:00 /usr/bin/flanneld --etcd-endpoints=http://192.168.100.5:2379 --iface=192.168.100.5 --etcd-prefix=/coreos.com/network
root 42326 2404 0 22:45 pts/1 00:00:00 grep --color=auto flan
可以使用flannel提供的脚本将subnet.env转写成Docker启动参数,创建好的启动参数默认生成在/run/docker_opts.env文件中:
[root@7-5 ~]# mk-docker-opts.sh
[root@7-5 ~]# cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.0.0.0/16
FLANNEL_SUBNET=10.0.2.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false
[root@7-5 ~]# cat /run/docker_opts.env
DOCKER_OPT_BIP="--bip=10.0.2.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=true"
DOCKER_OPT_MTU="--mtu=1450"
DOCKER_OPTS=" --bip=10.0.2.1/24 --ip-masq=true --mtu=1450"
[root@7-5 ~]# [root@7-5 ~]# vim /usr/lib/systemd/system/docker.service
需要把这个文件加到docker的启动项
EnvironmentFile=/run/docker_opts.env
ExecStart=/usr/bin/dockerd $DOCKER_OPTS -H fd:// --containerd=/run/containerd/containerd.sock
[root@7-5 ~]# systemctl daemon-reload
[root@7-5 ~]# systemctl restart docker #启动docker
[root@7-5 ~]# ip a
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:76:2c:58:e1 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.1/24 brd 10.0.2.255 scope global docker0
valid_lft forever preferred_lft forever
[root@7-5 run]# etcdctl ls /coreos.com/network/
/coreos.com/network/config
/coreos.com/network/subnets
3.5 验证Flannel网络
查看etcd中的数据:
[root@7-5 run]# etcdctl ls /coreos.com/network/subnets
/coreos.com/network/subnets/10.0.2.0-24
3.6 配置Docker
Docker安装完成以后,需要修改其启动参数以使其能够使用flannel进行IP分配,以及网络通讯 在Flannel运行之后,会生成一个环境变量文件,包含了当前主机要使用flannel通讯的相关参数,如下:
docker-server2相同操作配置flannel,不用安装etcd
[root@7-6 ~]# tar -xf flannel-v0.11.0-linux-amd64.tar.gz
[root@7-6 ~]# mv flanneld /usr/bin/
[root@7-6 ~]# mv mk-docker-opts.sh /usr/bin/
[root@7-6 ~]# /usr/bin/flanneld --etcd-endpoints="http://192.168.100.5:2379" --iface=192.168.100.6 --etcd-prefix=/coreos.com/network &
[1] 52601
。。。。。。
[root@7-6 ~]# mk-docker-opts.sh -c
[root@7-6 ~]# cat /run/docker_opts.env
DOCKER_OPTS=" --bip=10.0.19.1/24 --ip-masq=true --mtu=1450"
[root@7-6 ~]# vim /usr/lib/systemd/system/docker.service
EnvironmentFile=/run/docker_opts.env
ExecStart=/usr/bin/dockerd $DOCKER_OPTS -H fd:// --containerd=/run/containerd/containerd.sock
[root@7-6 ~]# systemctl daemon-reload
[root@7-6 ~]# systemctl restart docker
[root@7-6 ~]# ip a
[root@7-5 ~]# etcdctl ls /coreos.com/network/subnets
/coreos.com/network/subnets/10.0.2.0-24
/coreos.com/network/subnets/10.0.19.0-24
3.7 验证容器互通
[root@7-5 ~]# docker load < busybox.tar
5b8c72934dfc: Loading layer 1.455MB/1.455MB
Loaded image: busybox:latest
[root@7-5 ~]# docker run -it busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
link/ether 02:42:0a:00:14:02 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.2/24 brd 10.0.2.255 scope global eth0
valid_lft forever preferred_lft forever
[root@7-6 ~]# docker load < busybox.tar
5b8c72934dfc: Loading layer 1.455MB/1.455MB
Loaded image: busybox:latest
[root@7-6 ~]# docker run -it busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
link/ether 02:42:0a:00:13:02 brd ff:ff:ff:ff:ff:ff
inet 10.0.19.2/24 brd 10.0.19.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ping 10.0.2.2
PING 10.0.2.2 (10.0.2.2): 56 data bytes
64 bytes from 10.0.2.2: seq=0 ttl=62 time=4.058 ms
64 bytes from 10.0.2.2: seq=1 ttl=62 time=1.058 ms
^C
--- 10.0.2.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 1.058/2.558/4.058 ms
两主机的容器可以互通 此时的网络数据包流向如图: 1、在docker-server1的busybox容器中查看路由表
/ # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.2.1 0.0.0.0 UG 0 0 0 eth0
10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
2、回到docker-server1真机上,查看路由条目
[root@7-5 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.19.0 10.0.2.0 255.255.255.0 UG 0 0 0 flannel.1
10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
192.168.100.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33
3、查看arp列表
[root@7-5 ~]# arp -e
Address HWtype HWaddress Flags Mask Iface
192.168.100.253 ether 00:50:56:c0:00:02 C ens33
192.168.100.4 ether 00:0c:29:62:ba:ac C ens33
10.0.19.0 ether 0a:cf:98:8e:01:41 CM flannel.1
10.0.2.2 ether 02:42:0a:00:14:02 C docker0
C: arp的缓存条目 CM: arp的静态条目
4、查看mac地址ce:2a:b6:dd:d6:3a的数据流向
[root@7-5 ~]# bridge fdb show
01:00:5e:00:00:01 dev ens33 self permanent
33:33:00:00:00:01 dev ens33 self permanent
33:33:ff:28:7d:49 dev ens33 self permanent
33:33:ff:05:a2:7d dev ens33 self permanent
01:00:5e:00:00:01 dev ens37 self permanent
33:33:00:00:00:01 dev docker0 self permanent
01:00:5e:00:00:01 dev docker0 self permanent
33:33:ff:12:23:29 dev docker0 self permanent
02:42:24:12:23:29 dev docker0 master docker0 permanent
02:42:24:12:23:29 dev docker0 vlan 1 master docker0 permanent
0a:cf:98:8e:01:41 dev flannel.1 dst 192.168.100.4 self permanent
62:51:63:81:46:e4 dev veth12c7ca5 vlan 1 master docker0 permanent
62:51:63:81:46:e4 dev veth12c7ca5 master docker0 permanent
33:33:00:00:00:01 dev veth12c7ca5 self permanent
01:00:5e:00:00:01 dev veth12c7ca5 self permanent
33:33:ff:81:46:e4 dev veth12c7ca5 self permanent
3.8 配置backend为host-gw
(1) host-gw
- host-gw bakcend 是flannel的另一个backend。
- 与vxlan不同的是,host-gw不会封装数据包,而是在主机的路由表中创建到其他主机的subnet的路由条目,从而实现网络跨主机通信
- 需要说明的是,host-gw跨主机通信,或者说跨主机通信需要物理路由的支持,性能最好
(2) calico calico网络: - bgp转发:相当于host-gw转发,不能夸网段转发
- ipip转发:相当于vxlan转发模式
calico的优势: - 同时开启了两种转发模式,但是flannel只能开启其中一种转发模式
- 自动判断,如果宿主机跨网段,就是用ipip的方式转发,如果没有跨网段,就使用bgp方式转发
- 有流量策略管理,控制流量
|