Flannel 原理简析及安装
flannel是CoreOS提供用于解决Dokcer集群跨主机通讯的覆盖网络工具。它的主要思路是:预先留出一个网段,每个主机使用其中一部分,然后每个容器被分配不同的ip;让所有的容器认为大家在同一个直连的网络,底层通过UDP/VxLAN等进行报文的封装和转发。
flannel项目地址:https://github.com/coreos/flannel
flannel架构介绍
flannel默认使用8285端口作为UDP封装报文的端口,VxLan使用8472端口。

那么一条网络报文是怎么从一个容器发送到另外一个容器的呢?
- 容器直接使用目标容器的ip访问,默认通过容器内部的eth0发送出去。
- 报文通过veth pair被发送到vethXXX。
- vethXXX是直接连接到虚拟交换机- docker0的,报文通过虚拟- bridge docker0发送出去。
- 查找路由表,外部容器ip的报文都会转发到flannel0虚拟网卡,这是一个P2P的虚拟网卡,然后报文就被转发到监听在另一端的flanneld。
- flanneld通过- etcd维护了各个节点之间的路由表,把原来的报文- UDP封装一层,通过配置的- iface发送出去。
- 报文通过主机之间的网络找到目标主机。
- 报文继续往上,到传输层,交给监听在8285端口的flanneld程序处理。
- 数据被解包,然后发送给flannel0虚拟网卡。
- 查找路由表,发现对应容器的报文要交给docker0。
- docker0找到连到自己的容器,把报文发送过去。
flannel安装配置
环境准备
一共三台机器:一个etcd集群,三台机器安装flannel和Docker。
| 节点名称 | IP地址 | 软件环境 | 
|---|---|---|
| etcd1 | 192.168.2.210 | etcd、flannel、docker | 
| etcd2 | 192.168.2.211 | etcd、flannel、docker | 
| etcd3 | 192.168.2.212 | etcd、flannel、docker | 
安装etcd
关于etcd的安装使用已经在「etcd使用入门」和「通过静态发现方式部署etcd集群」中做了比较详细的讲解,如果你还不会安装etcd可先阅读下这两篇文章。这里就不再重复讲解了。
安装flannel
三个节点都需安装配置flannel,这里以etcd1节点为例。
flannel和etcd一样,直接从官方下载二进制执行文件就可以用了。当然,你也可以自己编译。
$ curl -L https://github.com/coreos/flannel/releases/download/v0.7.0/flannel-v0.7.0-linux-amd64.tar.gz -o flannel.tar.gz
$ mkdir -p /opt/flannel
$ tar xzf flannel.tar.gz -C /opt/flannel
解压后主要有flanneld、mk-docker-opts.sh这两个文件,其中flanneld为主要的执行文件,sh脚本用于生成Docker启动参数。
配置flannel
由于flannel需要依赖etcd来保证集群IP分配不冲突的问题,所以首先要在etcd中设置 flannel节点所使用的IP段。
$ etcdctl --endpoints "http://etcd1.hi-linux.com:2379" \
set /coreos.com/network/config '{"NetWork":"10.0.0.0/16", "SubnetMin": "10.0.1.0", "SubnetMax": "10.0.20.0"}'
{"NetWork":"10.0.0.0/16", "SubnetMin": "10.0.1.0", "SubnetMax": "10.0.20.0"}
flannel预设的backend type是udp,如果想要使用vxlan作为backend,可以加上backend参数:
$ etcdctl --endpoints "http://etcd1.hi-linux.com:2379" \
set /coreos.com/network/config '{"NetWork":"10.0.0.0/16", "Backend": {"Type": "vxlan"}}'
flannel backend为vxlan比起预设的udp性能相对好一些。
启动flannel
- 命令行方式运行
$ /opt/flannel/flanneld --etcd-endpoints="http://etcd1.hi-linux.com:2379" --ip-masq=true >> /var/log/flanneld.log 2>&1 &
- 后台服务方式运行
给flannel创建一个systemd服务,方便以后管理。创建flannel配置文件:
$ cat <<EOF | sudo tee /etc/systemd/system/flanneld.service
[Unit]
Description=Flanneld
Documentation=https://github.com/coreos/flannel
After=network.target
Before=docker.service
[Service]
User=root
ExecStart=/opt/flannel/flanneld \
--etcd-endpoints="http://etcd1.hi-linux.com:2379,http://etcd2.hi-linux.com:2379,http://etcd3.hi-linux.com:2379" \
--iface=192.168.2.210 \
--ip-masq
Restart=on-failure
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
注意:
--iface参数为要绑定的网卡的IP地址,请根据实际情况修改。
启动flannel服务
$ systemctl start flanneld
flannel启动过程解析
flannel服务需要先于Docker启动。flannel服务启动时主要做了以下几步的工作:
- 从etcd中获取network的配置信息。
- 划分subnet,并在etcd中进行注册。
- 将子网信息记录到/run/flannel/subnet.env中。
验证flannel网络
在etcd1节点上看etcd中的内容
$ etcdctl  --endpoints "http://etcd1.hi-linux.com:2379" ls /coreos.com/network/subnets
/coreos.com/network/subnets/10.0.2.0-24
查看flannel0的网络情况:
$ ifconfig flannel0
flannel0  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:10.0.2.0  P-t-P:10.0.2.0  Mask:255.255.0.0
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1472  Metric:1
          RX packets:85 errors:0 dropped:0 overruns:0 frame:0
          TX packets:75 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500
          RX bytes:7140 (7.1 KB)  TX bytes:6300 (6.3 KB)
可以看到flannel0网卡的地址和etcd中存储的地址一样,这样flannel网络配置完成。
配置Docker
在各个节点安装好以后最后要更改Docker的启动参数,使其能够使用flannel进行IP分配,以及网络通讯。
flannel运行后会生成一个环境变量文件,包含了当前主机要使用flannel通讯的相关参数。
- 查看flannel分配的网络参数
$ cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.0.0.0/16
FLANNEL_SUBNET=10.0.2.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=true
- 创建Docker运行参数
使用flannel提供的脚本将subnet.env转写成Docker启动参数,创建好的启动参数位于/run/docker_opts.env文件中。
$ /opt/flannel/mk-docker-opts.sh -d /run/docker_opts.env -c
$ cat /run/docker_opts.env
DOCKER_OPTS=" --bip=10.0.2.1/24 --ip-masq=false --mtu=1472"
- 修改Docker启动参数
修改docker的启动参数,并使其启动后使用由flannel生成的配置参数,修改如下:
# 编辑 systemd service 配置文件
$ vim /lib/systemd/system/docker.service
# 在启动时增加flannel提供的启动参数
ExecStart=/usr/bin/dockerd $DOCKER_OPTS
# 指定这些启动参数所在的文件位置(这个配置是新增的,同样放在Service标签下)
EnvironmentFile=/run/docker_opts.env
然后重新加载systemd配置,并重启Docker即可
$ systemctl daemon-reload
$ systemctl restart docker
此时可以看到docker0的网卡ip地址已经处于flannel网卡网段之内。
$ ifconfig flannel0
flannel0  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:10.0.2.0  P-t-P:10.0.2.0  Mask:255.255.0.0
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1472  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
$ ifconfig docker0
docker0   Link encap:Ethernet  HWaddr 02:42:cf:87:3c:f7
          inet addr:10.0.2.1  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
到此节点etcd1的flannel安装配置完成了,其它两节点按以上方法配置完成就行了。
测试flannel
三台机器都配置好了之后,我们在三台机器上分别开启一个docker容器,测试它们的网络是否可相互联通的。
etcd1
$ docker run -it  busybox sh
# 查看容器IP
$ cat /etc/hosts10.0.2.2	9de86bfde6cc
etcd2
$ docker run -it  busybox sh
# 查看容器IP
$ cat /etc/hosts10.0.5.2	9ddd4a4e455b
etcd3
$ docker run -it  busybox sh
# 查看容器IP
$ cat /etc/hosts10.0.6.2	cbb0d891f353
- 从不同宿主机容器到三台宿主机
/ # ping -c3 192.168.2.210
PING 192.168.2.210 (192.168.2.210): 56 data bytes
64 bytes from 192.168.2.210: seq=0 ttl=64 time=0.089 ms
64 bytes from 192.168.2.210: seq=1 ttl=64 time=0.065 ms
/ # ping -c5 192.168.2.211
PING 192.168.2.211 (192.168.2.211): 56 data bytes
64 bytes from 192.168.2.211: seq=0 ttl=63 time=1.712 ms
64 bytes from 192.168.2.211: seq=1 ttl=63 time=0.356 ms
64 bytes from 192.168.2.211: seq=2 ttl=63 time=2.201 ms
/ # ping -c3 192.168.2.212
PING 192.168.2.212 (192.168.2.212): 56 data bytes
64 bytes from 192.168.2.212: seq=0 ttl=63 time=0.467 ms
64 bytes from 192.168.2.212: seq=1 ttl=63 time=0.477 ms
64 bytes from 192.168.2.212: seq=2 ttl=63 time=0.532 ms
- 从容器到到跨宿主机容器
/ # ping -c3  10.0.5.2
PING 10.0.5.2 (10.0.5.2): 56 data bytes
64 bytes from 10.0.5.2: seq=0 ttl=60 time=0.692 ms
64 bytes from 10.0.5.2: seq=1 ttl=60 time=0.565 ms
64 bytes from 10.0.5.2: seq=2 ttl=60 time=1.135 ms
/ # ping -c3  10.0.6.2
PING 10.0.6.2 (10.0.6.2): 56 data bytes
64 bytes from 10.0.6.2: seq=0 ttl=60 time=0.678 ms
64 bytes from 10.0.6.2: seq=1 ttl=60 time=0.907 ms
64 bytes from 10.0.6.2: seq=2 ttl=60 time=1.272 ms
/ # ping -c3 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=60 time=0.644 ms
64 bytes from 10.0.2.2: seq=1 ttl=60 time=0.915 ms
64 bytes from 10.0.2.2: seq=2 ttl=60 time=1.032 ms
测试容器到到跨宿主机容器遇到一个坑,开始怎么都不通,后找到原因是宿主机iptables给阻挡掉了。附:Ubuntu一键清除iptables规则脚本
$ cat clear_iptables_rule.sh
#!/bin/bash
iptables -F
iptables -X
iptables -Z
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
参考文档
http://www.google.com
http://t.cn/RcnGQ02
http://t.cn/RXVHGpI
http://t.cn/RXfavPG
http://t.cn/RXfEThA
http://t.cn/RXfEmS8
http://t.cn/R5Xgfnx
Flannel 原理简析及安装的更多相关文章
- [转载] Thrift原理简析(JAVA)
		转载自http://shift-alt-ctrl.iteye.com/blog/1987416 Apache Thrift是一个跨语言的服务框架,本质上为RPC,同时具有序列化.发序列化机制:当我们开 ... 
- Java Android 注解(Annotation) 及几个常用开源项目注解原理简析
		不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义. ... 
- PHP的错误报错级别设置原理简析
		原理简析 摘录php.ini文件的默认配置(php5.4): ; Common Values: ; E_ALL (Show all errors, warnings and notices inclu ... 
- Java Annotation 及几个常用开源项目注解原理简析
		PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 一.Annotation 示 ... 
- Spring系列.@EnableRedisHttpSession原理简析
		在集群系统中,经常会需要将Session进行共享.不然会出现这样一个问题:用户在系统A上登陆以后,假如后续的一些操作被负载均衡到系统B上面,系统B发现本机上没有这个用户的Session,会强制让用户重 ... 
- SIFT特征原理简析(HELU版)
		SIFT(Scale-Invariant Feature Transform)是一种具有尺度不变性和光照不变性的特征描述子,也同时是一套特征提取的理论,首次由D. G. Lowe于2004年以< ... 
- 基于IdentityServer4的OIDC实现单点登录(SSO)原理简析
		写着前面 IdentityServer4的学习断断续续,兜兜转转,走了不少弯路,也花了不少时间.可能是因为没有阅读源码,也没有特别系统的学习资料,相关文章很多园子里的大佬都有涉及,有系列文章,比如: ... 
- cgroup原理简析:vfs文件系统
		要了解cgroup实现原理,必须先了解下vfs(虚拟文件系统).因为cgroup通过vfs向用户层提供接口,用户层通过挂载,创建目录,读写文件的方式与cgroup交互.因为是介绍cgroup的文章,因 ... 
- DHCP工作原理简析
		引言 DHCP是网络体系结构中应用层的一个重要协议,它可以帮助我们对要连接到互联网的计算机进行IP地址等信息的配置.本文从DHCP的原理出发,就DHCP的工作过程 进行详细的探讨. 主要报文 发现报文 ... 
随机推荐
- 利用iptables做端口转发
			需求背景: A与C不在同一网段无法直接访问,而A和B,C和B可以互通.现需要A借助B访问C的3306端口. 解决方案: 利用iptables配置规则,实现端口转发. 具体操作: 在B上开启端口转发功能 ... 
- window.showModelessDialog传值
			参数传递:1. 要想对话框传递参数,是通过vArguments来进行传递的.类型不限制,对于字符串类型,最大为4096个字符.也可以传递对象,例如:------------------------ ... 
- android x86 固件定制
			测试提了几个bug 1.系统语言默认设置成中文,否则时间控件显示的内容有问题 2.关闭10分钟不操作自动休眠功能 3.默认关闭虚拟键盘,目的在文本控件点击后,虚拟键盘就会在右下角显示出来,导致物理键盘 ... 
- ANR日志分析
			2018年06月27日 16:28:13 Hello__code 阅读数 3427更多 分类专栏: bug记录 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出 ... 
- mysql 添加时间自动添加更新时间自动更新
			在数据库使用中经常使用到时间字段.常用的有创建时间和更新时间.然而在使用中想要创建时间在创建的时候自动设置为当前时间,更新时间在更新时自动更新为当前时间. 创建表 stu CREATE TABLE ` ... 
- canvas笔记备忘
			备忘 1. canvas标签的宽和高设置是标签属性设置, 不是 css 属性设置. 如果用 css 属性设置大小, canvas 会被拉伸. 标签属性例如: class, id, style, wid ... 
- 使用PhantomJS报warnings.warn('Selenium support for PhantomJS has been deprecated, please use headless '解决方法
			selenium已经放弃PhantomJS了,建议使用火狐或者谷歌无界面浏览器.使用无界面浏览器Selenium+Headless Firefox Selenium+Headless Firefox和 ... 
- Python统计数据库中的数据量【含MySQL、Oracle】
			Python程序文件如下: # -*- coding: utf-8 # File : start.py # Author : baoshan import json import pymysql im ... 
- Java12新特性 -- 默认生成类数据共享(CDS)归档文件
			默认生成类数据共享(CDS)归档文件 同一个物理机/虚拟机上启动多个JVM时,如果每个虚拟机都单独装载自己需要的所有类,启动成本和内 存占用是比较高的.所以Java团队引入了类数据共享机制 (Clas ... 
- Maven 常用工具类整理
			目录 1.Apache Commons 1.1.字符串处理 1.2.集合操作 1.3.IO操作 1.4.编解码操作 2.Google Guava 2.1.多场景使用 2.2.guava-retryin ... 
