Kubernetes | 读代码:Flannel Backends(2) - Network类型

2021 03 5, Fri

最近重心都不在K8S上,就简单写写。代码也不贴了,一方面没有意义,另一方面没有时间整理。

2022-9-27: 对不起,对不起。今天重新翻看以前的文章,才发现这篇当时没有写完。今天补完

上次我们提到flannel的main函数中,实际上核心的部分就是

  • 获取网络的配置,获取到网络的实际实现(be backend.Backend)
    bm := backend.NewManager(ctx, sm, extIface)
    be, err := bm.GetBackend(config.BackendType)
  • be实际配置了网络,顺便配置了iptables,把网络配置写到了本地。
    bn, err := be.RegisterNetwork(ctx, &wg, config)
    bn.Run(ctx)

bn是一个满足了Netowrk的接口的变量。其中Network接口在backend/common.go中:

type Network interface {
	Lease() *subnet.Lease
	MTU() int
	Run(ctx context.Context)
}

主要是用来配置和驱动网络运行的。

SimpleNetwork & RouteNetwork

flannel不止提供了这个接口,也提供了自己实现的两个类型,分别是SimpleNetwork和RouteNetwork。

其中包括

  • 直接使用了SimpleNetwork的插件:
    • alivpc
    • alloc
    • awsvpc
    • gce
  • 插件中的Network类型内嵌了SimpleNetwork
    • ipsec
    • vxlan
    • udp
  • RouteNetwork
    • host-gw
    • ipip

SimpleNetwork

SimpleNetwork 简单说就是除了刷新租约以外什么事情都不做。因为需要配置的东西大多并不在宿主机上,比如说配置好云主机的路由以后,就不需要再做什么了。

直接使用SimpleNetwork的插件,除了啥都不做的alloc以外,看起来都是云平台的网络。我们打开alivps会看到插件用了github.com/denverdino/aliyungo去修改阿里云的虚拟网络路由表,awsvpc和gce则是用了github.com/aws/aws-sdk-gogoogle.golang.org/api/compute/v1。设置好了虚拟网络的路由后,SimpleNetwork就是一个什么都不做、简单记录了Lease和MTU信息的类型,Run只是等待Context结束。简单通过路由就可以让不同子网的pod、svc互相访问到。

RouteNetwork

而RouteNetwork内嵌了SimpleNetwork,除了记录基本的类型以外,还会根据子网变更情况,使用netlink(github.com/vishvananda/netlink)来试试在内核中增减路由规则。host-gw就是这样一个通过一个网关设置路由的插件,它获取到其他节点的ip以及分配的子网然后直接在各个节点上配置路由。而ipip则是通过netlink建立一个ipip的tunnel,然后配置路由。

内嵌SimpleNetwork的三种网络

除了udp是flannel自己写的一个通过udp转发数据包的tun设备以外,ipip、ipsec和vxlan都是Linux直接支持的三种Tunnel,ipsec用到了Strongswan。四种类型都可以看作是一种VPN,只不过ipip因为比较简单,所以直接用了RouteNetwork设置一下路由就好。其余的三个类型就略微特殊那么一点点。

一开始就提到的udp tunnel中,flannel开了一个tun设备。一个tun设备实际上就是一个文件,flannel打开了/dev/net/下面的tun设备文件,用ioctl配置了TUNSETIFF,然后就会在Run的循环中处理udp,由于数据是应用发给内核、内核由通过tun发给flannel、flannel最后才发给其他节点,所以性能非常低。

vxlan是通过netlink,ipsec是通过strongswan和netlink,都开了一个新的tunnel设备。自己各自写了一个处理subnet变动和lease变动的Run。

Extension Network

除此之外 flannel 还提供一个 extension 类型的 backend。

ExtensionNetwork 和上面几种比起来也非常的粗暴。就是很简单的在特定的事件驱动下执行命令,一共有四个时机:

  • preStartup: flannel 启动时执行
  • postStartup: 退出前执行
  • SubnetAdd: 子网划分有变动,增加Subnet时
  • SubnetRemove: 子网划分有变动,除去Subnet时