flannel 实战与源码分析(五)
来源:互联网 发布:linux开机启动mysql 编辑:程序博客网 时间:2024/06/05 01:01
上一篇介绍的vxlan模式,本篇还想介绍一个host-gw模式,顾名思义,就是主机网关模式。这个和calico的路由模式中主机网关是一样的,只不过没有BGP罢了。
先介绍一下怎么使用,然后分析了源码。先设置一下网络模式
etcdctl set /flannel/network/config '{"Network": "192.168.0.0/16","SubnetLen": 24,"SubnetMin": "192.168.1.0","SubnetMax": "192.168.100.0","Backend": {"Type": "host-gw"}}'
这样就设置好了,重启flannel和docker就行了。简单!
测试一下
19: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:c0:a8:45:02 brd ff:ff:ff:ff:ff:ff inet 192.168.69.2/24 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:c0ff:fea8:4502/64 scope link valid_lft forever preferred_lft forever/ # / # ping 192.168.49.2PING 192.168.49.2 (192.168.49.2): 56 data bytes64 bytes from 192.168.49.2: seq=0 ttl=62 time=1.179 ms64 bytes from 192.168.49.2: seq=1 ttl=62 time=0.675 ms64 bytes from 192.168.49.2: seq=2 ttl=62 time=6.091 ms
网络是联通的,下面分析一下网络路由
ip routedefault via 10.39.0.1 dev eth0 proto static metric 100 10.39.0.0/24 dev eth0 proto kernel scope link src 10.39.0.53 metric 100 192.168.0.0/16 dev flannel.1 192.168.49.0/24 via 10.39.0.45 dev eth0 192.168.69.0/24 dev docker0 proto kernel scope link src 192.168.69.1
这里面通过192.168.49.0/24 via 10.39.0.45 dev eth0 将流量通过eth0发送出去
在另一台机器商量也有对应的
ip routedefault via 10.39.0.1 dev eth0 proto static metric 100 10.39.0.0/24 dev eth0 proto kernel scope link src 10.39.0.45 metric 100 192.168.0.0/16 dev flannel.1 192.168.49.0/24 dev docker0 scope link 192.168.69.0/24 via 10.39.0.53 dev eth0
通过路由互通,这个和calico很相似
下面通过抓包查看
从eth0抓取的包可以看出,这就是路由转发,没有overlay封包。源mac为宿主机mac,目的mac为目的宿主机的mac地址,源IP为宿主机IP,目的IP为目标容器的IP,什么情况?目的IP为啥不是容器的IP呢?你可能忘记docker自带的SANT了
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERAD
这主要是为了屏蔽docker自己的IP,将容器内部出去的流量通过SNAT修改为宿主机的IP,避免暴露容器。那么这个就不符合kubernetes对容器网络的定义,这里我一直强调的是概念的理解。那么你可以把这个规则删除就可以了这样,网络就可以,看看现在抓包结果
这样容器就能看到对方容器的IP了。分析完原理,我们再进入代码讲解,它的代码比较简单,关于网段租赁的代码之前有讲解再次不再赘述,主要看看路由是怎么下发的吧
func (n *network) handleSubnetEvents(batch []subnet.Event) { for _, evt := range batch { switch evt.Type { case subnet.EventAdded: log.Infof("Subnet added: %v via %v", evt.Lease.Subnet, evt.Lease.Attrs.PublicIP) if evt.Lease.Attrs.BackendType != "host-gw" { log.Warningf("Ignoring non-host-gw subnet: type=%v", evt.Lease.Attrs.BackendType) continue } route := netlink.Route{ Dst: evt.Lease.Subnet.ToIPNet(), Gw: evt.Lease.Attrs.PublicIP.ToIP(), LinkIndex: n.linkIndex, } // Check if route exists before attempting to add it routeList, err := netlink.RouteListFiltered(netlink.FAMILY_V4, &netlink.Route{ Dst: route.Dst, }, netlink.RT_FILTER_DST) if err != nil { log.Warningf("Unable to list routes: %v", err) } // Check match on Dst for match on Gw if len(routeList) > 0 && !routeList[0].Gw.Equal(route.Gw) { // Same Dst different Gw. Remove it, correct route will be added below. log.Warningf("Replacing existing route to %v via %v with %v via %v.", evt.Lease.Subnet, routeList[0].Gw, evt.Lease.Subnet, evt.Lease.Attrs.PublicIP) if err := netlink.RouteDel(&route); err != nil { log.Errorf("Error deleting route to %v: %v", evt.Lease.Subnet, err) continue } } if len(routeList) > 0 && routeList[0].Gw.Equal(route.Gw) { // Same Dst and same Gw, keep it and do not attempt to add it. log.Infof("Route to %v via %v already exists, skipping.", evt.Lease.Subnet, evt.Lease.Attrs.PublicIP) } else if err := netlink.RouteAdd(&route); err != nil { log.Errorf("Error adding route to %v via %v: %v", evt.Lease.Subnet, evt.Lease.Attrs.PublicIP, err) continue } n.addToRouteList(route) case subnet.EventRemoved: log.Info("Subnet removed: ", evt.Lease.Subnet) if evt.Lease.Attrs.BackendType != "host-gw" { log.Warningf("Ignoring non-host-gw subnet: type=%v", evt.Lease.Attrs.BackendType) continue } route := netlink.Route{ Dst: evt.Lease.Subnet.ToIPNet(), Gw: evt.Lease.Attrs.PublicIP.ToIP(), LinkIndex: n.linkIndex, } if err := netlink.RouteDel(&route); err != nil { log.Errorf("Error deleting route to %v: %v", evt.Lease.Subnet, err) continue } n.removeFromRouteList(route) default: log.Error("Internal error: unknown event type: ", int(evt.Type)) } }}
先介绍一下添加网络事件EventAdded,先是创建一个路由对象,查找本地路由比对:
如果目的地址一样但网关不一样,删了重建
如果已经有重复的则不做任何操作
如果没有这条路由则通过RouteAdd添加到本地路由表中并通过addToRouteList写到本地缓存中
删除的逻辑就粗暴了直接删除本地路由表和本地缓存。这样路由管理就完成了。
- flannel 实战与源码分析(五)
- flannel 实战与源码分析(一)
- flannel 实战与源码分析(二)
- flannel 实战与源码分析(三)
- flannel 实战与源码分析(四)
- flannel 实战与源码分析(六)
- flannel 实战与源码分析(七)
- 《Android源码设计模式解析与实战》读书笔记(五)
- HandlerThread源码分析与实战
- 调优案例分析与实战(五)
- zookeeper实战与源码分析----zookeeper安装
- quake3源码分析(五)
- Logcat源码分析(五)
- pomelo源码分析(五)
- mosquitto源码分析(五)
- openMPM源码分析(五)
- mosquitto源码分析(五)
- mosquitto源码分析(五)
- iOS侧滑返回
- 《java编程思想》--基础知识
- Lucene 索引库的操作
- Linux操作以及c编程规范 、附带个问题
- RT5350原厂SDK及AP移植步骤详解
- flannel 实战与源码分析(五)
- Node.js 切近实战(九) 之Excel在线(在线编辑)
- myeclipse 内存溢出解决
- Could not parse mapping document from input stream
- ssh免密码登入
- 问题记录
- BlueROV-3: Fathom-S Tether Interface Board Set and Batteries
- 考试篇(5.2) NSE4 题库 08. 显式代理 ❀ 飞塔 (Fortinet) 网络安全专家
- 索引相关