Kubernetes网络与防火墙联动方案探索

【编者的话】作为事实上的容器云标准,Kubernetes为应用带来了快速部署、快速迭代、快速扩缩容等便利,同时在简化运维和提高硬件资源利用率等方面也有很大的优势。但Kubernetes中应用的Pod IP是允许变化的,而且Pod使用Kubernetes内部虚拟网络,Pod本身IP对外不可见,应用Pod出集群数据包源IP地址使用的是其所在宿主机IP。在这种情况下,为满足对应用流量管控的要求,需要为应用划分专用的虚拟机节点,以虚拟机的IP区分应用进行流量管控,这不能充分发挥Kubernetes资源利用率方面的优势。为达到对应用Pod流量进行精细化管控的目的,提高Kubernetes资源利用率,我们对Kubernetes网络和防火墙联动方案进行探索。

Kubernetes网络方案介绍

在介绍Kubernetes网络与防火墙联动方案之前,需要先简单介绍一下Kubernetes的网络方案。

Kubernetes网络的基本设计原则是每个Pod都拥有唯一一个独立的IP地址,用户不需要额外考虑如何建立Pod之间的连接,也不需要考虑容器端口与宿主机端口映射等问题。Kubernetes并不具体去实现诸如给Pod分配IP、回收IP、记录宿主机IP—Pod IP对应关系之类的细节,而是委托CNI实例去管理Pod的网络资源并为Pod建立互通能力。CNI(Container Network Interface)是一个标准的接口规范,其本身实现了一些基本的插件, 比如bridge、ipvlan、macvlan、loopback、vlan等网络接口。

目前主流的容器网络解决方案都有对应CNI的支持能力,比如Flannel、Calico、Weave、Contiv、SR-IOV、Amazon ECS CNI Plugins等。我行Kubernetes集群使用的网络插件即为Flannel插件。一般来说,这些容器网络插件的工作模式可从容器网络流量穿越宿主机网络的形态方面分为两种:

  • Overlay网络:容器网络的IP和MAC地址对宿主机网络不可见,跨宿主机容器间通信需要将容器流量进行封装转发,而容器出集群的流量需要进行SNAT转换。Flannel的vxlan工作模式、Calico的IPIP模式均属于该类型。
  • Underlay网络:容器网络对宿主机可见,在容器进行通信时不需要对流量进行封装,直接建立路由表,根据规则进行路由转发进行通信。Flannel的host-gw工作模式、Calico的BGP工作模式均属于该类型。

目前我行使用的Fannel插件的VXLAN工作模式即属于第一种方案。如下图所示,在该模式下,Pod-1通过veth pair的方式连接到node1的cni0网桥上。在跟Pod-2通信时数据包首先通过cni0到达宿主机,根据宿主机路由规则(172.16.2.0/24 via 172.16.2.0 dev flannel.1 onlink)将数据包交给VTEP设备Flannel.1处理。然后,Flannel.1设备将数据包进行VXLAN封装,在宿主机网络中进行传输,待数据包到达Node2时再由Node2上的Flannel.1设备解封得到原始数据包并传递给Pod-2。

在该种模式下,跨宿主机Pod间的通信需要进行封装传输,Pod的IP地址不会暴露在宿主机网络,使得不同集群可以使用同一个Pod地址池。但是,在该种模式下,除了Pod间跨宿主机通信会对原始消息进行封装,Pod出集群的数据包也会进行SNAT转换,出集群的所有Pod流量其源地址使用的均是宿主机IP地址,导致我们无法对单个Pod进行精确的流量管控。

Kubernetes网络与防火墙联动方案

为达到对应用Pod流量进行精确管控的目的,第一,Pod数据流量需要可以区分;第二,Kubernetes中Pod的IP不是一直不变的,会随着Pod的建立、销毁、漂移等动作进行分配、回收、更新,这需要流量管控方随时掌握Pod和IP的对应关系。对于第一个问题,我们考虑使用基于路由转发方式的underlay容器网络方案,将Pod的IP地址对外暴露。对于第二个问题,我们使用Kubernetes客户端编写 Kubemonitor工具对Pod的变动信息进行监控,并实时把变动信息发送给网络防火墙更新策略。

基于路由转发的容器网络方案

行内Kubernetes平台使用的Flannel网络插件可以使用host-gw工作模式,该模式将宿主机作为主机路由,对其上的Pod流量进行路由转发,如图所示:

在host-gw网络模式下,Pod-1转发给Pod-2的流量不再经过封装,直接根据Node1的路由表转发至Node2传递到Pod-2。除此之外,要在集群外监控Pod-1的流量包,还需Pod-1的IP地址对集群外可见,需要配置Flannel的启动参数 –ip-masq=false 使得出群流量不经过SNAT转换。

使用Flannel host-gw网络模式,并且配置出集群流量不经过SNAT转换,除了需要网络方面配置Pod IP地址的回程路由外,每个集群将单独需要一个地址段来作为本集群的Pod 网络地址池。现用的VXLAN模式,集群的IP地址池是一个子网掩码为16为的虚拟地址段(172.16.0.0/16),该地址段最多支持256个集群节点,每个节点上可以为256个Pod分配IP地址。使用host-gw后,为了区分Pod流量和配置Pod的回程路由,Pod网络不能再使用虚拟地址段,且不同集群间也不能共用同一个地址段。该种情况下如果继续使用16位掩码的地址段作为Pod的IP地址池,会大量浪费行内IP地址段资源。为避免该问题,可将集群Pod网络的地址池的子网掩码调整为18,这样能在很大程度上减轻地址段的浪费。子网掩码为18的Pod地址段支持64个节点,每个节点支持256个Pod,可以满足我行集群需求。

Pod IP信息实时推送工具——Kubemonitor

要达到精细化管控Pod流量的目的,除了区分出Pod的流量,在Kubernetes中应用Pod会发生销毁、重建、副本缩放、漂移等情况,应用的Pod数量和IP地址是会发生变化的,需要编写自动化工具将Pod IP的变动信息实时推送防火墙开通策略。

如下图所示,Kubemonitor主要包含以下几个部分。

  • Kubernetes Client是Kubernetes集群的开源客户端,完成与Kuberetes集群的连接、验证、资源获取、监听等功能。该客户端使用了Kubernetes统一的异步消息处理机制——List-Watch机制,其中List机制用于一次性获取集群资源最新的状态,Watch机制用于监听Kubernetes资源变动,在资源新建、更新、删除时实时获得最新信息。
  • Resources Controller 根据配置文件选择监听的集群资源类型(Pod、Server、Statefultset、Deployment等),并调动Resources Manager模块去处理所监听资源的变动信息。
  • 当集群资源的任何属性值发生变化(如状态、硬件资源申请量、网络属性等)Resources Controller都会监听并获取到,但这么庞杂的变动信息不一定是我们关注的。在与防火墙联动的需求中,我们其实主要关注(应用系统,Pod名称,IP地址)这样一个三元组信息,而对其余的比如硬件资源申请量等并不关注。Resources Manager模块主要用于去除无关变动信息,并按约定格式生成通知消息。
  • Interface模块实现了与其他系统的对接接口。Kubemonitor通过Interface支持的接口类型(如Webhook、Kafka)将资源变动消息通知给所需系统。
  • Consensus Server共识服务。在容器环境部署需要考虑在Pod在被迁移、杀死、出错时的产生的服务连续性问题。Kubemonitor通过多副本部署来实现高可用行。但是多副本部署时每个副本都会独立监听并发送资源变动信息,导致对接系统收到变动消息重复。为此Kubeminitor使用分布式一致性协议Raft实现了Consensus Server功能。Consensus Server负责监听Kubemonitor副本的变化,选举出Master节点与对接系统通信,同时负责同步Kubemonitor所有副本获取到的资源变动信息的状态。该共识服务模块完成多副本部署时消息去重任务,且最多能容忍不多于一半的Kubemonitor副本掉线。
  • Kubemonitor的配置文件通过Config模块进行管理。除了给防火墙通知Pod变动信息外,未来所有需要Kubernete集群资源最新状态的系统均可进行配置,通过Kubemonitor进行实时推送。

后记

该工作完成后,Kubernetes集群内部东西向网络性能将提升20%,并可在对Pod流量进行精细化网络管控的前提下实现集群内应用混合部署,极大提高硬件资源利用率。

Kubernetes网络与防火墙联动方案目前已经与网络中心配合完成了前期的测试验证工作,即将交付业务进行试用。该方案对于容器平台来说除了涉及到Kubernetes集群underlay网络改造外,还要保证Kubemonitor推送消息的准确性和及时性;对于网络方也要论证使用underlay方案后的Kubernetes集群Pod地址段的划分、Pod回程路由的建立和路由规则下发、以及针对Pod进行的防火墙策略更新等问题,这些问题需要双方共同探索、论证、携手推进。

原文链接: https://mp.weixin.qq.com/s/FRTXWvn_Q-CpZFGELjhGHA