K8S网络模型的概述
对于普通的网络环境,网络实现以物理设备为主,以一个局域网为例,通过多台交换机组成一个交换域,实现主机间通信,如果有访问外网的需求,加一个路由器,添加必要的路由即可。
对于容器网络环境,网络实现以网桥为主,一般的单体应用,利用本机的网络栈可以实现互访,例如一个harbor应用,其nginx,redis等服务组件都是运行在一个宿主机上的容器,docker自带的网桥插件即可实现,网桥就是一个软件交换机。
K8S作为目前作为主流的容器编排工具,其承接的任务越来越多,所能适应的场景也在增加,因此我们把K8S的网络模型进行一个剖析,看看起网络需求有哪些,以及对应的技术实现。
K8S典型应用场景
我们首先看看K8S平台可以有哪些典型应用场景
微服务是相对于单体应用而言的,单体应用的特点是业务逻辑高度集中,以一个电商交易类网站为例,他的登录注册,库存管理等功能逻辑,都是一种编程语言java写成,数据库连接也是单一的mysql。
而在微服务中,这些功能会被拆分成若干个子模块,编程语言和数据库的使用也可以存在多个,例如登录注册,用java实现,数据库使用NOSQL。而库存管理,这种偏底层的模块,可以用C语言实现,使用关系型数据库。
这样做有什么好处呢?简单讲,可以优化整体应用的性能并且服务迭代升级的粒度也可以更细。所以应用微服务化的趋势,会造成容器数目的大量增加。
还有一个应用场景就是深度学习的分布式训练,例如以tensorflow的ps-worker的架构为代表。一般普通的GPU训练,可以是在一台宿主机上,部署CUDA框架,并结合必要的算法模型,使用单机单卡进行训练。
分布式训练可以部署在K8S平台上,具体形式是,多个ps节点连同多个worker节点,以容器形式分布在K8S平台上,构成一个分布式训练集群。在训练过程中,权重和梯度等模型参数的分发和汇总,会产生一些大的网络通信量,特别对于一些大tensor的场景,对于K8S网络模型的性能要求就会高一些。
了解应用场景的目的,就是说明在K8S中,网络插件的选型是取决于具体的应用
K8S网络模型
在K8S网络设计中,容器是抽象封装在POD中的,一个POD对应一个网络空间,里面可以存在多个容器,POD是K8S中最小单元,但为了方便描述,我们把POD等价于容器,并按照复杂性依次分成四个需求点:
一是POD访问外网,即POD访问K8S集群外的主机或者是互联网
这个需求通过容器中的路由和宿主机上的路由可实现,只要容器内的路由表和宿主机的路由表设置正确,这个很容易实现,唯一需要关注的是dns解析的问题
二是外网访问POD,即集群外访问POD的服务
这个其实K8S平台最主要的作用,即对外提供服务,例如数据库或者web访问服务,这个在具体实现,是通过ingress/router组件,实现四层和七层的负载均衡后,再访问后端的POD,产品的选型一般以nginx或者haproxy为主,当然也可以选择硬件的F5实现
以下图haproxy实现的配置为例
balance leastconn代表负载均衡的策略是最小连接数
server则是对应后端POD的端点(端点即指ip+端口的形式)
三是POD与服务之间的访问
如上图,一个KUBE-SEP规则链就对应一个POD端点,其负载均衡的策略通过probability的数值实现,0.33代表33%的请求命中率,0.50代表50%的请求命中率
而根据probability概率,经过DNAT找到对应的POD后,在iptables的conntract记录POD选择,以保证后续的数据转发
四是POD之间的跨主机通信,这个是比较重要的,主流实现可以概括为叠加网络和路由网络两种方式
叠加网络,以ovs和flannel等较为普适的网络模型为代表,在okd中默认ovs,其特点是以正常三层网络为underlay,构建一个以vxlan技术的overlay网络,实现一个大二层网络,这样实现最基本的POD的互访,而不需要做一些NAT的动作,所以叠加网络更加适合一般使用场景,例如上述场景中的微服务,可以选择ovs作为默认网络模型
路由访问,包括calico和macvlan,calico的特点是,把宿主机当作三层路由器使用,而一个容器就对应一条路由,如下图所示
10.128.170.111就是对应一个具体的POD,这个在路由表中就是一条路由,寻址时,直接把网络请求转发到cali开头的虚拟网卡上
由于Calico少了一层overlay的封装,在做路由转发时,其性能损耗几乎是没有的,所以calico比较适合网络性能要求高的场景,上述应用场景中的分布式训练,就可以考虑选择calico作为容器网络模型。
当然实际网络模型的选型不一定根据某个指标来确定,这里只是参考。产品成熟度,社区活跃度,自身开发运维能力都是需要考虑的因素。网络模型的多样性和灵活性总是伴随着选择的复杂度。
例如ovs的缺点是对于万兆以上网络的支持会弱一些,而calico的缺点,在于路由表项的维护问题,当容器量很大时,路由表项也会随着变得庞大,表项的分发和更新的效率会出现性能瓶颈
我们以一个简单的原理图来总结下这四个点,原理图已按照上述顺序进行编号
其中eth0这里,如果是叠加网络,这个物理网卡eth0就看做隧道远端,如果是路由网络,这里就看做一个网关
1是两层路由表出去
2是外部流量经过ingress进来
3是通过iptables实现一层抽象
4是通过网络插件,经过隧道远端或者网关到达POD
网络模型本身是一个很复杂的系统,比较难以掌握,本文尝试把K8S网络模型,分解成一个个具体网络需求,换一个思路,可以较为清楚网络在K8S平台的角色定位以及网络插件选型的着力点在哪里
理解了K8S网络模型,有什么实际意义呢?从运维部署的角度出发,可以帮助我们在进行网络层面的troubleshooting时,厘清排查的思路
网络模型还包括其他的网络需求,例如第一点提到DNS域名解析系统,这个也是较为复杂的系统,我们后续会单独讨论