设为首页 收藏本站
查看: 1055|回复: 0

[经验分享] mainred

[复制链接]

尚未签到

发表于 2018-1-6 13:48:27 | 显示全部楼层 |阅读模式
  转自:https://ieevee.com/tech/2017/08/12/k8s-flannel-src.html


  • 1 VXLAN

    • 1.1 VXLAN协议
    • 1.2 VXLAN配置

  • 2 vxlan flannel

    • 2.1 flannel.1接口是怎么创建的?
    • 2.2 fdb 转发数据库
    • 2.3 newKubeSubnetManager
    • 2.4 arp table

  • 3 udp flannel
  flannel是coreos贡献给社区的一个kubernetes网络插件。overlay。

1 VXLAN

1.1 VXLAN协议
  二层数据中心网络的一个关键特征就是它们的使用虚拟局域网(VLAN)提供广播隔离,从而更好的为多租户提供隔离。但随着租户数量越来越多,VLAN由于上限容量4096,越来越捉襟见肘。
  vxlan(Virtual eXtensible Local Area Network)是一种隧道协议,用来解决IEEE 802.1q VLAN>  vlan协议在IETF RFC 7348中定义,有多种实现,如linux kernel的vxlan模块,OpenVswitch等。vxlan协议跑在UDP上,UDP连接的端口固定,如linux kernel vxlan的端口号为8472。
  跟其他隧道不同,VXLAN并不是一个点到点的网络,而是1 to N。VXLAN设备可以动态的学习IP地址,也可以从静态配置的转发表中学习。
  VXLAN的配置管理使用iproute2包,这个工具是和VXLAN一起合入到内核的。

1.2 VXLAN配置
  先来看看如何管理VXLAN接口。
  1 创建VXLAN接口
  

ip link add vxlan0 type vxlan>

  

  这条命令会创建一个叫做vxlan0的新接口,它使用在eth1上的组播组239.1.1.1来通信。初始化时没有转发表。目的端口号是IANA规定的4789。在VXLAN中,一般将vxlan接口叫做VTEP(Vxlan tunnel endpoint),VXLAN子网的报文,都需要从VTEP出去。
  多播组主要用来泛洪学习arp:vxlan子网内广播ARP请求,对应VM响应。但并不是必须的。
  如果网络不复杂,可以认为某一Hypervisor上所有的子网IP的MAC,和Hypervisor上的VTEP的MAC一致,可以直接用VTEP MAC封装报文;而VTEP的MAC,可以用bridge命令手工配置。
  2 配置错了可以删除vxlan
  

ip link delete vxlan0  

  

  3 查看vxlan的信息
  

ip -d link show vxlan0  

  

  可以用bridge命令查看,删除,查看VXLAN的转发表。
  1 创建一条转发表项。MAC即对端VTEP的MAc,地址即对端VTEP的地址
  

bridge fdb add to 00:17:42:8a:b4:05 dst 192.19.0.2 dev vxlan0  

  

  2 删除一条转发表项
  

bridge fdb delete 00:17:42:8a:b4:05 dev vxlan0  

  

  3 查看VXLAN接口的转发表
  

bridge fdb show dev vxlan0  

  

  一个典型的数据中心vxlan网络:

  一个典型的vxlan报文:


2 vxlan flannel
  flannel的vxlan相对数据中心来说,是比较简单的,因为其在Layer 3上只有1个Vxlan网络,只有1个vxlan接口(flannel.[VNI],默认为flannel.1)。VTEP的MAC地址不是通过组播学习的,而是通过从apiserver的node接口watch到并静态下发的。

2.1 flannel.1接口是怎么创建的?
  一、main.go查找ExtIface(Hypervisor L3出接口,所有vxlan报文都要封装后走ExtIface出去overlay)。flannel的出接口允许用户按以下方式来选择(LookupExtIface):


  • 指定具体接口
  • 指定接口的正则表达式来匹配查找
  • 啥也不指定,由flannel根据默认网关找出接口
  1.5.4版本默认kubeadm不会指定flannel的出接口,所以出接口选的是默认网关的接口。如果机器上网络比较复杂,可能需要手工指定出接口。
  二、确定subnet
  flannel网络中,以我们的集群为例,整个flannel网络是10.244.0.0/16,每个node都是一个子网(subnet),如10.244.0.0/24, 10.244.1.0/24。
  subnet的网段、长度是怎么确定的呢?k8s创建时会生成net-conf.json,其设置了Network和Backend的信息(configmap kube-flannel-cfg,以volume形式挂到flanneld容器里去)。
  

# flanneld容器中  
cat /etc/kube-flannel/net-conf.json
  
{
  
"Network": "10.244.0.0/16",
  
"Backend": {
  
"Type": "vxlan"
  
}
  
}
  

  

  ParseConfig中会确定subnet的配置项:SubnetMin, SubnetMax, SubnetLen, BackendType。如果net-conf.json没有指定Backend,则默认使用udp。我这里使用了vxlan。注意,由于udp方式下,报文是通过tun从内核上送到用户态的flanneld进程,在用户态进程做udp封装、解封装,性能不佳,所以生产环境最好选用vxlan。
  三、根据backend类型创建backend,然后调用be.RegisterNetwork函数去初始化flannel接口。步骤如下。
  1 创建flannel接口。netlink下内核创建flannel.1接口,需要指定vni,出接口,源地址,目的端口,nolearning(netlink.Vxlan),并设置app_solicit为3。相当于如下命令:
  

ip link add $DEVNAME type vxlan>
echo '3' > /proc/sys/net/ipv4/neigh/$DEVNAME/app_solicit  

  

  2 调用kube subnet manager获取租约。ksm会去调用apiserver的node api,查询node的PodCIDR,即该节点的pod overlay网络,如10.244.1.0/24(kubeSubnetManager.AcquireLease, subnet/kube/kube.go:213)
  3 如果从apiserver查询node的backend Annotations跟实际node的信息不一致(例如VTEP MAC不同),则向node打patch,更新Anootations。此更新会被其他node watch到,从而更新其本地的fdb table(下面会提到)。
  4 设置flannel.1接口地址,激活接口,并增加网段路由(vxlanDevice.Configure, backend/vxlan/device.go:125)
  

ip address add $VXSUBNET dev $DEVNAME  
ip link set $DEVNAME up
  
ip route add $SUBNET dev $DEVNAME scope global
  

  

  一个典型的flannel.1接口信息如下。
  

ip -d link show flannel.1  
8: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT
  
link/ether 12:c0:e6:d3:0d:df brd ff:ff:ff:ff:ff:ff promiscuity 0

  
vxlan>  

  

  至此,flannel.1接口配置完毕,接下来就是配置fdb静态表项了。

2.2 fdb 转发数据库
  flannel接口配置完毕后,接下来就是在集群中配置fdb表了。要做的其实也就是完成下面这条命令的下发,只是由flannel自动完成,用户不需要手动操作。
  

bridge fdb add/append $mac-of-vtep-on-node-2 dev $DEVNAME dst $DESTIP  

  

  跟数据中心的vxlan不一样,flannel网络中的VTEP的MAC并不是通过组播学习的,而是通过apiserver去做的同步(或者是etcd)。前面在创建flannel.1接口时有提到,各个节点会将自己的VTEP信息上报给apiserver,而apiserver会再同步给各节点上正在watch node api的listener(flanneld),flanneld拿到了更新消息后,再通过netlink下发到内核,更新fdb表项,从而达到了整个集群的同步。

2.3 newKubeSubnetManager
  flanneld会在启动的时候,创建一个针对apiserver node api的informer(newKubeSubnetManager)。
  flannel的子网管理器SubnetManager有2种:基于etcd、基于k8s的apiserver。我这里使用的是基于k8s的kubeSubnetManager(subnet/kube/kube.go, 下面简称ksm),它会去listWatch k8s apiserver的node api,通过ksm.events与backend通信。ksm.events是一个长度为5000的subnet.Event chan,ksm作为生产者,会将从k8s那里watch到的信息封装(nodeToLease,节点信息转为租约信息)后写到ksm.events里去。
  ksm.events的消费者是backend。backend/vxlan_network.go在run时,会拉起一个goroutine,调用subnet/watch/WatchLeases(),在这个函数里批量读取ksm.events chan,并将批量事件推入backend的接收chan;backend会在其goroutine中处理这些事件:根据事件中带的nodes信息,如IP,VtepMAC,下发到本机内核fdb table。
  subnet/watch/WatchLeases()做了个优化:node比较活跃时,ksm.events里可能会有比较多的events;读取ksm.events的时候,可以一次性读出一组events,并且在处理这些events时,可以将同一SUBNET的lease合并,不过事件的总数不会减少。
  第一批事件的处理函数是handleInitialSubnetEvents,进行初始化+事件处理。其获取内核的fdbtable,之后会根据获取的上面WatchLeases丢过来的event,对比fdbtable刷新内核fdb table:删除内核多余的表项,增加内核缺少的表项,保持跟flannel网络一致。这里有个疑问,initial的时候,怎么保证event都是Added的呢?如果是删除的,刷新内核arp table的流程是有问题的。
  后续事件的处理函数是handleSubnetEvents,它比较纯粹,根据event.Type是Added还是Removed,修改内核fdb表现 和 flannel维护的routes(后面arp解析时会用到)
  fdb更新下发内核相当于调用了如下命令:
  

bridge fdb add $mac-of-vtep-on-node dev $DEVNAME dst $DESTIP  

  

  一个典型的fdb表项如下。
  

bridge fdb show dev flannel.1  
76:bc:c1:37:14:32 dst 192.168.136.35 self permanent
  
ca:07:82:ff:d1:6a dst 192.168.136.34 self permanent
  
0e:c4:9f:71:f3:56 dst 192.168.136.32 self permanent
  
66:73:1c:ea:76:58 dst 192.168.136.33 self permanent
  

  

  至此,fdb静态表项配置完成,并且可以达到与集群同步更新。

2.4 arp table
  fdb完成后,报文转发没问题了,但在L2封装时,还需要对端ip的arp表项。linux ARP解析是这样的:

  When there is no forward progress, ARP tries to reprobe. It first tries to ask a local arp daemon app_solicit times for an updated MAC address. If that fails and an old MAC address is known, a unicast probe is sent ucast_solicit times. If that fails too, it will broadcast a new ARP request to the network. Requests are sent only when there is data queued for sending.

  即:


  • 向用户态arp daemon请求app_solicit次;
  • 如果还有旧的MAC地址记录,单播一下试试;
  • 绝望了,怒而广播之
  (说起来好像跟某些事件有点类似)
  所以,明白为啥前面创建flannel.1接口时,需要设置app_solicit为3了吗?
  在flannel网络中,flanneld会在启动时监听RTM_GETNEIGH(vxlanDevice.MonitorMisses),flanneld相当于arp daemon;arp请求会在内核中通过netlink发送请求到用户态的flanneld,由flanneld根据该arp请求ip所属网段(该node上所有ip的MAC也就是VTEP的MAC),查询其记录的routes信息,然后netlink下发内核。
  

func (nw *network) handleL3Miss(miss *netlink.Neigh) {  
route := nw.routes.findByNetwork(ip.FromIP(miss.IP))
  
err := nw.dev.AddL3(neighbor{IP: ip.FromIP(miss.IP), MAC: route.vtepMAC})
  
}
  


  所以如果你先arp -d x.x.x.x -i flannel.1删掉arp缓存,然后再ping想触发一个arp请求,抓包是抓不到arp报文的。
  arp table更新下发内核相当于调用了如下命令:
  

ip neighbor add/replace $ip-on-node-2 lladdr $mac-of-vtep-on-node-2 dev flannel.1  

  

  至此,vxlan的流程就走通了。

3 udp flannel
  vxlan要求内核版本3.7+,最好3.9+,所以在一些旧版本的linux上就无法使用基于vxlan的flannel了,只能使用基于udp的flannel。
  udp flannel原理与vxlan类似,都是package in udp,只是一个在内核做报文封装,一个在用户态做(通过tun, pkg/ip/tun.go)。可想而知,udp flannel的性能不会太好,所以除非是内核版本太低,一般还是用vxlan flannel性能会比较好。
  ref:


  • Virtual eXtensible Local Area Networking documentation
  • vxlan在Flannel中的Overlay网络的实现
  • Difference of VXLAN L3MISS between flannel and docker overlay implementation

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-432225-1-1.html 上篇帖子: 一次Flannel和Docker网络不通定位问题 下篇帖子: 分布式技术追踪 2017年第三十五期
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表