有需要参考网络基础知识的,参见https://www.cnblogs.com/shuiguizi/p/12518086.html

1,GRE:是一种协议封装的格式。注意是约束格式的,他的具体要求是这样的。

在GRE中,需要被传输和封装的报文称之为payload packet,而用于封装和传输的协议则成为delivery protocol。GRE在封装的时候,除了payload和delivery协议的header外,会生成一个GRE header。

GRE header + payload一起被delivery协议封装用于传输。

例如:要建立VPN的时候,需要建立隧道,那么此时就要求三大类协议:乘客协议,隧道协议,承载协议。

GRE是在路由器上进行封装解封装,能够封和解的路由器(即靠近源和目的的路由器)设怎么做到封和解的呢?

答:在这些路由器上有特殊的路由条目,如果是要被封装的数据则让他的下一跳时隔特殊的东东叫做Tunnel0(可以认为是隧道的起点),于是他负责封

到了目的路由器,同样是这个叫做tunnel的东东,会把附加的封装去除,得到真正的payload。

需要注意的是,GRE是点对点的,为什么这么说,

因为tunnel0是要配置的,会在tunnel0上配置tunnel的终点时谁(即目的ip),所以一个tunnel0只负责一条隧道。想要多播那就再建立隧道。

想要组播是不支持的,想要广播那就是向这个节点上的所有隧道(即所有tunnel0s);另外很多防火墙或者三层网络设备不支持GRE,即不能解析明白被封装的包是什么也就无从做过滤或者符再均衡之类的行为。

2,vxlan:

      他的封包特点有如下几点:

      1)不同于GRE是(第)三层外面套(第)三层,而是二层外面套四层,三层, 二层,所以这就说明封装后的包可以精准到达目的地的四层

          (注意,虽然是四层不能说就是一个用户态应用,着要看具体用什么实现的vtep,有的内核就支持那么就不用切换到用户态了,有的是硬件支持有的是软件支持)

          并且,因为封装的是二层网络,也就是已经细化到局域网了,所以才叫VxLAN

      2)也有一个类似tunnel0的东西,叫做VTEP(VxLAN Tunnel Endpoint)是用来做封装解封装的

      3)应用场景:因为封装的是二层包,所以应用的场景是宿主机A上的虚拟机m和另一个宿主机B上的虚拟机n之间的通信,因为可以将宿主机上的虚拟机们看作是类局域网。

                           在通信的时候,是有arp的,因为m并不知道n所属的主机地址到底是哪个,所以发arp问下宿主机们,m在谁那里。

      4)具体的工作过程

          (1)当一个VTEP启动的时候,他会通过IGMP协议加入一个组播组,于是此时A,B,C都在一个组中了,制定了VXLAN ID为100

          (2)然后A上的m虚拟机启动了,他具有的VXLAN就是100,同样n也是100,他们可以认为是在一个lan中(因为是一个二层的封装啊)

          (3)当m想要ping n的时候,发现他并不知道如何找到n,具体的说是不知道他的mac地址,还是因为是一个局域网中,所以于是封装并发送arp包,vtep在组中广播看看谁有n的mac地址 ,

               于是vtep B回复了n的mac,然后vtep A就开始封装包 :内层ip和mac是虚拟机n的地址,外层是vtep B的地址

          (4)最后,宿主机B上的vtep B程序获取到了这个四层包,然后解包,得到就是一个内部局域网的二层包,最后发送给寄宿在自己身上的虚拟机n。

              这里要说一下,这个包之所以能组播出去,正是IGMP协议的工作。

VxLAN包:
Virtual Extensible LAN,虚拟化可扩展局域网,基于IP网络,采用 MAC in UDP封装形式的二层VPN技术,一个简单拓扑和报文结构图来感性认识下

几个关键名词:
VNI:VXLAN Network Identifier,即虚拟出来的网络id
VTEP:VxLAN隧道的EndPoint,代表隧道的始端或者终端实体。负责对VxLAN报文进行封装/解封装,包括ARP请求报文和数据报文。VTEP可由硬件设备或软件去实现。

结合报文格式解读一下:学过TCP/IP的我们都知道,协议栈可以分成5层,从最上层的应用出来的数据会经过协议栈一层层封装:应用层--->传输层TCP/UDP头--->三层(网络层)IP头--->二层(链路层)MAC头-->物理层,从物理网卡出去。

VxLAN是其在封装到二层的时候,由VTEP进行再一次的封装叫做VxLAN封装,即又增加了UDP头->IP头->MAC头,所以叫"MAC in UDP"。这就非常适用于容器的应用场景,一方面满足了网络隔离的要求(比如多租户等),另一方面VNI是个24-bit的值,即支持2^24个vxlan网络,远高于vlan。这样的好处是用一张图就能看出来:

水鬼子:其实里面还有很多知识点没有融会贯通,先记录这些,之后随着遇到问题,应该就会慢慢豁然开朗

==========================================================

linux 内核从3.7之后就内部集成了vxlan功能,所以可以使用linux内核提供的vxlan功能,经过配置创建vxlan网络。

而从Docker自Docker Engine 1.9之后,就自带overlay网络的驱动了,也才有了可以直接使用docker create network命令创建overlay类型的网络

在这里我们除了创建单纯的vxlan网络,我们可以手动模拟overlay驱动,利用namespace自己创建overlay网络,这里会遇到很多坑,但对于学习vxlan甚至是linux网络知识都很有帮助。

另外,受环境所限这里我只试验了点对点类型的vxlan网络,但对于理解vxlan往还是够用啦

大纲:

1,环境准备,
2,最基本的点对点vxlan网
3,多namespace下的点对点vxlan网
      3.1入坑
      3.2爬坑
      3.3结论

环境准备


0,在某两家云服务供应商上买了2台计算云,centos 7,这样的环境稍显复杂,因为计算云的机器都是绑定的VIP,其自身接口的ip都是小网ip,互相不认识的小网ip......

master节点                                                  minion节点
VIP:             188.x.x.113          ---中间网络------              106.y.y.3
IP(eth0):      172.21.0.3                                                   172.16.0.4
MAC(eth0):  52:54:00:6b:df:04                                        fa:16:3e:a8:1f:98

1,linux内核版本越高越好,如果不够,可以用如下命令进行升级

  rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
  yum --enablerepo=elrepo-kernel install kernel-ml-devel kernel-ml -y

2,  安装必要的工具,比如

ln -s /var/run/docker/netns/ /var/run/netns

最基本的点对点vxlan网


所谓点对点网络,表示每个vtep只有一个伙伴,它只与这个伙伴建立一个隧道。

【实操】

master:

//创建一个vxlan类型的接口作为vtep,vxlan id即VNI为200,指定隧道的另一端ip为minion的VIP,建立隧道的物理接口为eth0
ip link add vxlan20 type vxlan id 200 dstport 4789 remote 106.y.y.3 dev eth0
ip addr add 10.20.1.2/24 dev vxlan20
ip link set vxlan20 up

minion:

ip link add vxlan20 type vxlan id   remote 188.x.x.113 dstport  dev eth0

ip addr add 10.20.1.3/ dev vxlan20
ip link set vxlan20 up

【验证】#ping  10.20.1.3 OK的,抓包也可以看到经过vxlan封装的报文

【解析】

此种情况属于vtep之间的直接通信,arp包和icmp包都被vtep即vxlan20进行了vxlan封装。

这部分的实验是很有必要的,因为可以说明我的linux内核是支持vxlan。这很重要,因为在开始我使用的是namespace + veth pair方式搭建环境,但总是不通,查了好多资料都说是版本问题,所以我这才舍弃自己的虚拟机花钱购买了计算云,然后又是升级内核版本等等....

直到这种最简单方式的情况下发现是OK的,我才意识到,我解决问题的方向早就偏了....

多namespace下的点对点vxlan网


【配置】

master:

ip link add vxlan20 type vxlan id 100 remote 106.y.y.3 dstport 4789 dev eth0

ip link add br-vx2 type bridge   //创建网桥

ip link add veth20 type veth peer name veth21  //创建一对veth pair

//br-vx网桥左手一只vxlan10接口,右手一只veth10接口,然后将网桥up起来
ip link set vxlan20 master br-vx2
ip link set vxlan20 up

ip link set dev veth20 master br-vx2
ip link set dev veth20 up

ip link set br-vx2 up

//创建一个新的namespace名叫ns100,将之前创建的veth pair中的另一端veth11,添加到该ns100中,并添加ip以及up起来
ip netns add ns200

ip link set dev veth11 netns ns200
ip netns exec ns200 ip addr add 10.20.0.20/24 dev veth21
ip netns exec ns200 ip link set dev veth21 up
ip netns exec ns200 ip link set lo up

minion:

ip link add vxlan20 type vxlan id 200 remote 188.x.x.113 dstport 4789 dev eth0
ip link add br-vx2 type bridge
ip link add veth20 type veth peer name veth21

ip link set vxlan20 master br-vx2
ip link set vxlan20 up
ip link set dev veth20 master br-vx2
ip link set dev veth20 up
ip link set br-vx2 up

ip netns add ns200
ip link set dev veth21 netns ns200
ip netns exec ns200 ip addr add 10.20.0.21/24 dev veth21
ip netns exec ns200 ip link set veth21 up
ip netns exec ns200 ip link set lo up

入坑>>>>>>>>>

【操作】:为什么不通能,为什么?

#ip netns exec ns200  ping 10.20.0.21 -c 3
PING 10.20.0.21 (10.20.0.21) 56(84) bytes of data.

--- 10.20.0.21 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2030ms

爬坑>>>>>>>>

【解析round1】

根据目前学到的理论,我们知道数据的方向会如下图中红色箭头所示,于是我开始一步一步抓包

1,vxlan20接口抓包如下,arp有发出去且有收到应答,但是icmp包却有去无回

2,再次检查收发包情况,对比执行ping前后得到如下

[root@master ~]# netstat  -i
Kernel Interface table
Iface             MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
br-vx2           1450      341      0      0 0             0      0      0      0 BMRU
veth20           1500      998      0      0 0           278      0      0      0 BMRU
vxlan20          1450      279      0      0 0           204      0      0      0 BMRU

执行完ping操作, 即从ns200的veth21接口会发出来3个icmp包 + 1个arp包
[root@master ~]# netstat  -i
Kernel Interface table
Iface             MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
br-vx2           1450      346      0      0 0             0      0      0      0 BMRU
veth20           1500     1002      0      0 0           279      0      0      0 BMRU
vxlan20          1450      280      0      0 0           205      0      0      0 BMRU

解析:
veth20:接收4个包,其中3个icmp + 1个arp,发送1个arp请求
br-vx2:接收5个包 发送0个包
vxlan20:接收1个包,发送1个包,均为arp包,一个请求一个应答

水鬼子:不知道这里你有没有和我一样有个疑问,看过linux转发原理都知道,桥的一个接口接收到包之后会转发给桥上的其他接口,那么上面的发送接收到底表示什么含义呢,比如vxlan20接收的1个包是指接收来自veth20的转发,还是来自外网的应答?还有tcpdump这个工具,它到底抓的是哪个方向的数据包,他和netstat统计时打点的地方一样的么?接下来我会一步一步验证,非常繁琐,写下来只是为了给自己的记录,大家可以略过此段直接看结论。


0,预备知识:
http://ebtables.netfilter.org/br_fw_ia/br_fw_ia.html
很好的文章,看看在linu bridge中,ebtables和iptables都扮演了什么角色,这里截取核心的部分,如下图:

说明:
       蓝色:ebtbales, 绿色:ibtables
       桥上的接口收到数据后,进行bridge decision,如果目的地是给自己,上送走filter表的input链;否则桥内部洪泛,洪泛之前要走ebtables:filter的forward表,iptables:mangle表的forward表和filter表的forward表。

操作1:br-vx2接口是用来和上层协议栈交互的,掐断上报的路,看看什么结果
[root@master ~]# ebtables  -L
Bridge table: filter
Bridge chain: INPUT, entries: 1, policy: ACCEPT
-j DROP       //上送的数据都drop掉,即阻断上送的路

再ping,得到如下:
[root@master ~]# netstat  -i
Kernel Interface table
Iface             MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
br-vx2           1450      346      0      0 0             0      0      0      0 BMRU
veth20           1500     1006      0      0 0           280      0      0      0 BMRU
vxlan20          1450      281      0      0 0           206      0      0      0 BMRU

小小结1:br-vx2确实表示用于上报,这个和网桥同名的接口可以看做是通向内核协议栈的接口。

操作2:我删除ebtables中的配置,然后ping一个未知的ip,让其得不到arp应答

#  ip netns exec ns200  ping 10.20.0.22 -c 3
PING 10.20.0.22 (10.20.0.22) 56(84) bytes of data.

[root@master ~]# tcpdump -i br-vx2 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-vx2, link-type EN10MB (Ethernet), capture size 262144 bytes
20:02:41.886373 ARP, Request who-has 10.20.0.22 tell 10.20.0.20, length 28
20:02:42.931276 ARP, Request who-has 10.20.0.22 tell 10.20.0.20, length 28
20:02:43.955364 ARP, Request who-has 10.20.0.22 tell 10.20.0.20, length 28

br-vx2           1450      349      0      0 0             0      0      0      0 BMRU
vxlan20          1450      281      0      0 0           209      0      0      0 BMRU

解析:为什么是ping -c 3的时候br-vx2 接收到5个包呢?其中3(icmp)+1(arp请求)是veth20通过桥内部转发给我的,那一个是什么?我猜测是接收过来的arp应答
           为了验证这个结论,经过上述操作发现netstat的数据中,br-vx2只增加了3个(arp请求)

小小结:反向证明上面多出的1个包是arp应答。另外netstat统计时,RX-OK表示的是接口收到的数据包,这个数据包既可以是请求也可以是应答,只要是我接收到的。


小结:
结合上述实验加上我又看了linux的bridge部分的源码,以及netstat工具的源码,可以得到如下结论:
1,每一个bridge都有一个同名接口,可以将该接口看做是内核协议栈对外(网桥)的出入口。
2,netstat -i命令统计的数据是驱动层面的,将驱动中记录的数据提取出来进行显示,rx表示ingress,rx表示egress
---数据本来就在那里,我去取
3,tcpdump -i x是应用层面的,根据指令在不同模块上注册socket,数据在流动过程中发现有tcpdump的注册则deliver一份给他
4,二者的区别,netstat的统计更底层,所以当你发现netstat的统计数据和tcpdump不同的时候,就可以大概猜出来数据是在哪里被丢掉的。

【解析round2】:
在上面的例子可以看出来arp可以接收到应答,但是icmp报文为什么就不行呢?有两条线索
1,tcpdump -i vxlan20有看到请求发出来
2,netstat -i 发现,数据没有从vxlan10接口真的出去
那么数据肯定再这中间被drop掉了,然后看看这中间经历了什么,没错,就是iptables和ebtables一共经历了6个链,那好,我一个一个表查,通过向链里添加匹配条件来跟踪数据包都走到哪里。
最终,我发现原来这里给drop掉了

[root@master ~]# iptables -LFORWARD -v
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0            icmp --  any    any     anywhere             10.20.0.21     ----这个是我后加的匹配条件,原先是没有的

开始ping

[root@master ~]# iptables -LFORWARD -v
Chain FORWARD (policy DROP 3 packets, 252 bytes)  ----是的,被drop掉了
 pkts bytes target     prot opt in     out     source               destination         
    3   252            icmp --  any    any     anywhere             10.20.0.21          
  986 82824 DOCKER-USER  all  --  any    any     anywhere             anywhere            
  986 82824 DOCKER-ISOLATION-STAGE-1  all  --  any    any     anywhere             anywhere            
    0     0 ACCEPT     all  --  any    docker0  anywhere             anywhere             ctstate RELATED,ESTABLISHED
    0     0 DOCKER     all  --  any    docker0  anywhere             anywhere            
    0     0 ACCEPT     all  --  docker0 !docker0  anywhere             anywhere            
    0     0 ACCEPT     all  --  docker0 docker0  anywhere             anywhere            
    0     0 ACCEPT     all  --  any    docker_gwbridge  anywhere             anywhere             ctstate RELATED,ESTABLISHED
    0     0 DOCKER     all  --  any    docker_gwbridge  anywhere             anywhere

结论>>>>>>>>

仔细看,filter表的FORWARD链,除了docker相关的链匹配上了(这两个链直接return的,这里就不展示了)但都是什么也没做,也就是说走的是缺省策略?
excuse me?DROP?是的,该链的缺省策略时DROP,想死的心都有了,马上改

[root@master ~]# iptables -P FORWARD ACCEPT
[root@minion ~]# iptables -P FORWARD ACCEPT
[root@master ~]# ip netns exec ns200 ping 10.20.0.21 -c 3
PING 10.20.0.21 (10.20.0.21) 56(84) bytes of data.
64 bytes from 10.20.0.21: icmp_seq=1 ttl=64 time=16.5 ms
64 bytes from 10.20.0.21: icmp_seq=2 ttl=64 time=8.49 ms
64 bytes from 10.20.0.21: icmp_seq=3 ttl=64 time=8.43 ms

--- 10.20.0.21 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 8.438/11.156/16.534/3.802 ms
[root@master ~]#

注:频繁操作网桥,要设置如下命令,即让网桥的记忆为0,否则会因为有记忆让配置的策略暂时不生效(缺省5分钟才生效)
]# brctl setageing br-vx2 0

水鬼子:网上说在试验前要关闭防火墙,然后我就用如下命令关闭了,还关闭了selinux,但是事实证明iptables还是生效的,也许这里面又什么原理等待我去研究,但是已经管不了那么多了TOT

[root@master ~]# systemctl stop firewalld.service
[root@master ~]# systemctl disable firewalld.service
[root@master ~]# firewall-cmd --state
not running

-------------------------------end---------------------------------------------------

【爬坑系列】之vxlan网络实现的更多相关文章

  1. 【爬坑系列】之kubernetes环境搭建:二进制安装与镜像安装

    准备: 网上教如何编译与安装kubernetes的教程很多,需要提前准备的也很多,比如关闭selinux,防火墙啦....但有一点一定要注意,编译kubernetes源码时要求有2G内存,这个可是实打 ...

  2. 【爬坑系列】之docker的overlay网络配置(未完,待续)

    理论知识储备: 想了解vxlan网络的知识:https://www.cnblogs.com/shuiguizi/p/10923841.html 想了解docker网络的原理知识:https://www ...

  3. 【爬坑系列】之解读kubernetes的认证原理&实践

    对于访问kube-apiserver模块的请求来说,如果是使用http协议,则会顺利进入模块内部得到自己想要的:但是如果是用的是https,则能否进入模块内部获得想要的资源,他会首先要进行https自 ...

  4. ssh登录,爬坑系列

    最近在实验室弄ssh登录,结果被虐了,要注意以下: 1.主机名不能包括   -     _    !  等非法字符. 2.如果hadoop格式化时,报:“SHUTDOWN_MSG: Shutting ...

  5. 爬坑系列----Redis查询key报空指针异常,而redis中确实存在该key

    现象: 1.在A方法中根据key查询一个list,可以获取到相应的值 2.在B方法中同样调用此方法,传入相同的key,查询不到值,为null,报空指针异常 起初我也一脸懵逼,到现在虽然解决了,还是不知 ...

  6. SpringBoot爬坑系列

    1.日志篇 现象 由于日志配置采用原来SpringMVC项目中的log4j.properties 文件,日志采用springboot自带的jar包会出现打印不出日志的情况. 解决 引入原日志包 < ...

  7. AngularJs (二) 搭建Deployd 服务爬坑

    Deployd 爬坑 按照书上的教程,介绍Deployd 这个东东,首先进入其deployd.com/网页,发现这个东东着实厉害. THE SIMPLEST WAY TO BUILD AN API 按 ...

  8. 微信小程序爬坑日记

    新公司上手小程序.30天,从入门到现在,还没放弃... 虽然小程序发布出来快一年了,爬坑的兄弟们大多把坑都踩平了.而我一直停留在"Hello World"的学习阶段.一来没项目,只 ...

  9. 入坑第二式 golang入坑系列

    史前必读: 这是入坑系列的第二式,如果错过了第一式,可以去gitbook( https://andy-zhangtao.gitbooks.io/golang/content/ )点个回放,看个重播.因 ...

随机推荐

  1. codechef Taxi Driver

    题意: 给N个点求任意两个点的“距离”总和: A,B的“距离”定义为:min(|ax-bx|,|ay-by|) (n<200000) 好题! 解析: 看着没思路 先是公式化简:让 ax=sx+s ...

  2. CodeForces 582A【multiset使用样例】

    题意: 给一些无序的数字,求解一个矩阵,使得矩阵的每一个元素都是行和列标志数的gcd,输出行标志数. 首先对数字进行排序.复杂度n*log(n^2). 这题的证明有官方的英文题解==在这直接贴英文题解 ...

  3. hdu6109(并查集+set/倍增)

    题目 http://acm.hdu.edu.cn/showproblem.php?pid=6109 分析 对于相同的条件,明显直接并查集 对于不同的条件,可以用set来保存,并查集合并的时候也要对se ...

  4. easyUI排序问题

    使用easyUI时,需要在点击页面的某一列进行desc或asc排序,那么在jsp中可以把该列js的sortable 设置true. 加在某字段上时,该字段点击时页面会出现一小三角图案 ,此时easyU ...

  5. 从头开始学Android之(一)——— Android架构

    从事Android开发已经两年多了,最近项目上特别清闲,刚开始时在闲暇的时候都不知道干嘛,整天混日子.有一天突然有个以前同学找到我,说要我帮忙做一个Android的需求,就是在后台截屏(涉及到服务以及 ...

  6. 【转载】《Unix网络编程》思维导图

    参考这篇文章,很不错: http://www.cnblogs.com/qiaoconglovelife/p/5734768.html

  7. hibernate4中HHH000273的错误

    今天配置hibernate4.发现报 17:55:06,815 INFO AbstractPoolBackedDataSource:522 - Initializing c3p0 pool... co ...

  8. XxPay支付系统-boot版本 使用

    https://segmentfault.com/a/1190000016987391?utm_source=tag-newest 有三个版本: spring boot 版本: spring clou ...

  9. 使用正則表達式的格式化与高亮显示json字符串

    使用正則表達式的格式化与高亮显示json字符串 json字符串非常实用,有时候一些后台接口返回的信息是字符串格式的,可读性非常差,这个时候要是有个能够格式化并高亮显示json串的方法那就好多了,以下看 ...

  10. Random产生随机数问题

    昨天在开发时发现这个问题,在同一个for循环内,通过Random多次产生随机数得到的随机数竟是一样的!以前还真没发现这个问题. 以下是简化的代码,如果将random定义在for循环外面则不会有问题(猜 ...