刘泽宇 分布式实验室
本文主要介绍谐云在Calico容器网络在实践过程中,面对在大规模容器场景,根据每种Calico网络模式的优劣势,如何进行选型。重点讲解在实践过程中的遇到的容器网络高可用、频繁动态变更、服务稳定性等相关的问题,以及对应的解决方式。
概述
Calico网络模式
Overlay模式
IPIP node-to-node Mesh
Calico Overlay模式部署简单,要求Node节点允许IPIP协议,如果有安全组策略需要开放IPIP协议;要求Node允许BGP协议,如果有安全组策略需要开放TCP 179端口;官方推荐使用在Node小于100的集群,我们在使用的过程中已经通过IPIP模式支撑了100-200规模的集群稳定运行。
IPIP RR
采用Calico RR模式通过建立路由反射器接点减少每个工作节点的BGP邻居数量,保证了集群支撑规模。
Calico IPIP模式对物理网络无侵入,符合云原生容器网络要求;使用IPIP封包,性能略低于Calico BGP模式;无法使用传统防火墙管理、也无法和存量网络直接打通。Pod在Node做SNAT访问外部,Pod流量不易被监控。
BGP模式
Calico underlay模式,一般也称calico BGP模式,不同Node Pod使用直接路由进行通信。
Kubernetes集群为什么要与交换机建立BGP连接呢?
性能要求,Calico IPIP模式虽然能够满足大部分应用对于容器网络的性能要求,有些对网络延迟敏感的业务是不能使用overlay网络的。
规模要求,在Calico BGP模式下,如果不与网络设备建立BGP连接,Node只能在同一个局域网内。
安全管理要求,使用IPIP隧道会导致容器网络流量不能被传统的硬件防火墙管控,无法满足安全管理要求。使用硬件防火墙管理Pod IP,集群的规模会受到硬件设备的限制,在Calico BGP模式下,路由条目会从Node级别成Pod级别,使用EBGP模式可以将路由全部由交换机设备处理,目前看来企业数据中心级别核心交换机和接入交换机三层组网在支持1000-2000Node时,路由规模、BGP邻居、路由收敛速度就接近瓶颈;如果启用双栈,路由规模的压力会进一步增加。
BGP小规模集群
Node节点与交换机建立BGP邻居关系,学习Pod路由;Node和容器网络交换机建立BGP连接,在现网核心交换机上添加一条到容器网络的静态路由。这种模式适合有性能要求和管理要求的小规模集群。集群规模过大,需要在原有网络网关上频繁添加静态路由,增加网络管理员的了维护工作;频繁变更网络设备的配置,也存在一定的业务风险。
BGP大规模集群
Calico可以根据接入交换和核心交换机的性能参数,使用IBGP和EBGP容器组网。我们通常使用Calico的Downward Default模式来与交换机建立BGP连接,使用Node节点与接入交换机建立EBGP邻居关系,学习Pod路由;接入交换机将Pod路由汇聚后上报给核心交换机,将Pod路由分发到现网;采用Downward Default,Node网关是接入交换机,接入交换机网关是核心。这种模式减少了接入交换机和Node上的路由条目数量,但缺点是发送到无效IP的流量必须到达核心交换机以后,才能被确定为目的不可达。
Calico实践经验
在Calico IPIP模式,Pod间跨Node通信是通过Node IP建立IPIP隧道建立通信,Pod访问集群外网络,是通过Node SNAT 出去。只要保证Node网络是高可用的,Calico网络也是高可用。
生产上物理主机的网卡都是双网卡,并且使用bond��ӡ,�ż�模块配置高可用模式。对于物理主机而言,实际上是连接的两台交换机设备,当物理主机与交换机建立BGP邻居时,在堆叠组网模式或LACP组网模式下,需要交换机支持不间断路由的特性或者在主机与上联接入配置双BGP来实现路由的高可用。
路由更新速率问题
为什么要考虑路由更新速率?在Calico默认的使用模式中,Calico每个Node一个分配一个Block,每个Block默认为64个IP,当单个Node启动的Pod超过64时,才会分配下一个Block。Calico BGP client默认只向外通告聚合后的Block的路由,默认配置,只有在Node上下线、Node上Pod数量超过Block size的倍数才会出现路由的更新,路由的条目数量是Node级别的。
而实际业务在使用的过程中,会针对一个服务或者一个deployment分配一个IP Pool,这种使用模式会导致Calico的IP Pool没有办法按照Node聚合,出现一些零散的无法聚合的IP地址,最差的情况,会导致每个Pod产生一条路由,会导致路由的条目变为Pod级别。
在默认情况下,交换机设备为了防止路由震荡,会对BGP路由进行收敛保护。但是Kubernetes集群中,Pod生命周期短,变化频繁,需要关闭网络设备的路由变更保护机制才能满足Kubernetes的要求;对于不同的网络设备,路由收敛速度也是不同的,在大规模Pod扩容和迁移的场景,或者进行双数据中心切换,除了考虑Pod的调度时间、启动时间,还需要对网络设备的路由收敛速度进行性能评估和压测。
路由黑洞问题
使用Calico Downward Default模型组网时,Node使用EBGP模式与Node建立邻居关系。当Pod使用的IP地址为内部统一规划的地址,出现Pod IP地址紧张的时候,会出现Pod之间不能正常访问的情况。
Calico分配IP地址的原则为,将整个IPPool分为多个地址块,每个Node获得一个Block,当有Pod调度到某个Node上时,Node优先使用Block内的地址。如果每个新增的Node分不到一个完整的地址块,Calico IP地址管理功能会去使用其他Node的Block的IP,此时,就会出现Pod无法访问的现象。
如下图所示,Pod 10.168.73.82无法访问Pod 10.168.73.83。
查看Node 10.0.0.170的路由表,其中“blackhole 10.168.73.80/28 proto bird”为黑洞路由。如果没有其他优先级更高的路由,主机会将所有目的地址为10.168.73.80/28的网络数据丢弃掉。所以在Node 10.0.0.70上ping Pod 10.168.73.84会报“参数不合法”的错误。此时,在Downward Default模式下,Calico配置的这一条黑洞路由使得Node 10.0.0.70不能够响应其他Node上PodIP在10.168.73.80/28网段发起的网络请求。
首先,分析Calico黑洞路由的作用,查看Calico BGP Client中bird的配置文件:
配置解释:
Protocol static里面配置了一条静态路由到Node节点,为一条黑洞路由。BGP本身的机制会将路由通告出去。
Function calico_aggr里面定义的路由通告规则:路由目的地地址等于10.168.73.80/28的路由会执行accept,BGP Client会将路由通告出去;路由的地址被10.168.73.80/28包含的执行reject,BGP Client不会通告出去。
通过这两条规则和静态路由,Calico做到了路由聚合,并且不通告明细路由的功能。
要解决路由黑洞问题问题,首先,除了对整个Calico 的IP Pool总量进行监控外,还需要对可用的IP Block进行监控,确保不会出现IP Block不够分的情况,或者或者IP地址Block借用的情况;也可以通过在规划时计算IP地址总量,以及在kubelet配置参数中指定maxPods来规避这个问题;但是实际上Kubernetes节点的上线和规模的扩展是一个渐进的过程,对于IP地址紧张的企业来说,提前预分配太多IP地址会浪费IP地址资源。
取消Calico的黑洞路由只需修改bird_aggre.cfg的模板文件即可,如下图所示。
取消Calico的黑洞路由会带来一些副作用,BGP协议会将每个Pod的明细路由通告出去,且路由表无法聚合。这会导致交换机的压力增大,每创建一个Pod都会进行一次路由通告。
Calico默认配置是IPIP隧道是IBGP模式,启用IBGP非IPIP模式黑洞路由也不会影响Pod之间的通信,因为出现Block不够的时候,Pod的明细路由比黑洞路由的优先级更高。只有在EBGP模式下,Node不学习Pod通信路由,在IP地址紧张的情况下,集群才会出现Pod通信故障。
动态更新IPPool问题
由于Calico的IPPool的CIDR字段不支持数组的形式,导致在IP地址扩容时,只能修改Pod template的annotation,会导致服务滚动升级,影响业务的稳定性。
我们通过添加一个新的ServiceIPPool的CRD,来记录服务和IPPool的映射关系,通过修改Calico CNI地址分配的流程。的来避免更新服务IPPool而引起的滚动升级。IPPool的disabled标识也是Calico官方推荐用来替换IP地址的方式。
ServiceIPPool存储Service和IPPool的映射关系,为1:n的关系,一个Service可以对应多个IPPool。Deployment的annotation从IPPool列表修改为ServiceIPPool CR;原有calico-cni修改deployment对应的IPPool,需要修改pod template的annotation,会导致Pod重启。修改后只需要变更serviceIPPool,不需要进行滚动升级。但是缩容操作涉及到IPPool的释放,仍然不可避免的需要在下次滚动升级时才能释放,但是滚动升级的动作被推迟了。
总结
我们遇到的这些问题主要还是安全管理要求带来的,后续也会陆续开源到社区。