阿里terway源码分析

随着公司业务的发展,底层容器环境也需要在各个区域部署,实现多云架构, 使用各个云厂商提供的CNI插件是k8s多云环境下网络架构的一种高效的解法。我们在阿里云的方案中,便用到了阿里云提供的CNI插件terway。terway所提供的VPC互通的网络方案,方便对接已有的基础设施,同时没有overlay网络封包解包的性能损耗,简单易用,出现网络问题方便诊断。本文对该插件做简单的代码分析,理解其原理,以便后期诊断问题和维护。

功能划分

阿里云开源的terway代码有三部分组成:

CNI plugin: 即CNI插件,实现ADD、DEL、VERSION三个接口来供kubelet调用, 该插件将kubelet传递的参数进行简单处理后,会通过gRPC调用terwayBackendServer来实现具体的逻辑,例如申请网络设备等。同步调用terwayBackendServer将网络设备分配完毕之后,会通过ipvlanDriver.Driver进行pod sandbox network namespace的Setup操作,同时还会通过TC进行流控。该插件会通过daemonSet中initContainer安装到所有node上。

backend server: terway中主要的执行逻辑, 会进行IPAM管理,并申请对应的网络设备, 这部分是本次着重分析的对象。该程序以daemonSet的方式运行在每个节点上。

networkPolicy: 该部分是借助calico felix实现, 完全与上面两部分解耦。我们看到terway创建的网络设备是以cali为前缀的, 其实就是为了兼容calico的schema。

TerwayBackendServer

在terway的main函数中会启动gRPC server监听请求,同时会创建一个TerwayBackendServer, TerwayBackendServer封装全部操作逻辑,在newNetworkService函数中会依次初始化各个子模块实例,具体包括:

ECS client 用来操作ECS client, 所有创建删除更新操作最后都会通过该client进行处理,简单封装了一层alicloud的SKD

kubernetes pod 管理模块,用来同步kubernetes pod信息

resouceDB 用来存储状态信息,便于重启等操作后恢复状态

resourceManager 管理资源分配的实例,terway会根据不同的配置生成不同的resourceManager,此处我们使用的是ENIMultiIP这种模式,对应的就是newENIIPResourceManager

ENIMultiIP模式会申请阿里云弹性网卡并配置多个辅助VPC的IP地址,将这些辅助IP地址映射和分配到Pod中,这些Pod的网段和宿主机网段是一致的,能够实现VPC网络互通。

整个架构如下图所示:

阿里terway源码分析

首先我们理解一下kubernetes pod管理模块,该模块用于获取kubernetes pod状态。terway为了支持一些高级的特性,例如流控等,有一些信息无法通过CNI调用传递过来, 还是得去kubernetes中去查询这些信息。此外CNI调用在一些异常情况下可能无法准确回调CNI插件, 例如用户直接kubectl delete pod --force --graceperiod=0,此时就需要kubernetes作为唯一的single source of truth, 保证最后网络设备在pod删除时肯定能够被释放掉。 它内部主要的方法就是GetPod与GetLocalPod。GetPod方法会请求apiserver返回pod信息,如果该pod已经在apiserver中删除,就会从本地的storage中获取。该storage是用boltDB做为底层存储的一个本地文件,每个被处理过的pod都会在该storage中保存一份信息,且该pod副本并不会随着apiserver中pod的删除而删除,这样后面程序如果需要该pod信息可以从该storage中获取。同时该pod副本会通过异步清理goroutine在pod删除一小时后删除。GetLocalPod是从apiserver获取该node上所有的pod信息,该过程是调用kubernetes最多的地方,目前两个清理goroutine会每5min调用一次,调用量相对较小,对apiserver的负载影响不大。该模块也会在本地DB里缓存一份数据,便于在kubernetes pod删除后还可以拿到用户信息。

其次是resourceDB模块,该模块是用来持久化状态信息,该DB中记录了当前已分配的pod及其网络设备(networkResource)信息。每次请求/释放设备都会更新该DB。程序重新启动初始化完成之后,也会从resouceDB中恢复上次运行的数据。
除了基本的分配删除操作会更新该DB, terway还启动异步goroutine定期清理,保证异常情况下的最终一致性,该goroutine会从apiserve中获取所有pod信息和当前DB中的信息进行对比,如果对应的pod已经删除会先释放对应的网络设备,然后从DB中删除该记录。同时延迟清理可以实现Statefulset的Pod在更新过程中IP地址保持不变,

最重要的是resouceManager模块,该iterface封装了具体网络设备的操作,如下所示:

// ResourceManager Allocate/Release/Pool/Stick/GC pod resource // managed pod and resource relationship type ResourceManager interface { Allocate(context *networkContext, prefer string) (types.NetworkResource, error) Release(context *networkContext, resID string) error GarbageCollection(inUseResList map[string]interface{}, expireResList map[string]interface{}) error }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsspgg.html