一、前言
在典型的网络服务模型中,请求流量/响应流量(Req/Res)比是很小的一个值;在直播、高清视频等视频多媒体服务中,请求响应流量比将更小(几十KB的请求V.S.几十MB的返回)。对于这样的应用场景,大量的请求可以通过负载均衡器进行接入,但是响应数据包是无法在某个中心节点进行汇聚在返回客户的。所以针对这种小请求响应比的服务,必须使用在响应返回路径没有汇聚点的负载均衡机制。
根据响应数据包返回路径的不同,可以负载均衡分为如下两种模式:
- 双臂模式:请求、转发和返回在同一路径上,client和load balancer、
load balancer和后端server都是由请求和返回两个路径连接;返回数据包也要由
load balancer处理。
- 三角模式:请求、转发和返回三个路径连接client、
load balancer和后端server成为一个三角形;返回数据包直接从server发送到client,不经过
load balancer处理。
在传统的视频分发产品中,IPVS可以作为一个小规模的解决方案。使用IPVS的Direct Routing模式,可以保证IPVS作为请求接入点而并不承担响应汇聚点的角色,所有响应将直接从后端服务节点返回到客户端。但是这种方案对于网络部署存在特殊要求:IPVS DR模式要求所有服务后端主机和IPVS director在同一个LAN里面(IPVS director 仅仅对数据包进行dst mac替换),并且每个服务后端需要不同的MAC地址和IP地址。
一般情况下,在应用容器化后,容器会被挂载到宿主机的内部bridge上,拥有内部IP地址,所以无法和IPVS处于同一个LAN之中,也无法简单的配置一个外部IP直接给容器。任何从容器返回给客户端的请求都要经过bridge和NAT的处理。
在将容器化的应用迁移到Kubernetes或者Openshift之后,情况将更加复杂。因为Kubernetes默认是没有网络方案的,需要通过CNI插件引入第三方开发的网络方案。现有可用的CNI包括Flannel、Calico、Weave、Contiv、Openshift OVS SDN等。这些CNI网络方案主要的目的就是配置网络的协议、路由、设备、策略等基本元素,保证分布在不同工作节点的POD、kubernetes service之间可以互联互通。在这种要求下,满足kubernetes CNI要求的网络实现方案必定包含跨节点的数据通信,尤其是kubernetes将POD抽象成service之后,跨节点的通信更是不可避免(内置的基于iptables/ipvs的POD级别load balancer),这种通信不仅在请求阶段发生,响应数据包也会遵循请求数据包的路径原路返回,形成大量跨节点流量,给CNI内部带宽带来巨大开销。
载自https://blog.csdn.net/cloudvtech
所以考虑小请求响应比的服务数据面的要求以及kubernetes网络解决方案的限制,一个合理的kubernetes应用服务层面的负载均衡方案需要满足如下条件:
- 请求接入点可以合理的选择后端POD并将请求转发到处于kubernetes私有网络中的应用POD
- 可以在没有数据面返回路径汇聚点的情况下进行扩展
- 不存在跨节点的响应数据包的转发
- 尽量减少iptables里面的NAT操作
在设计负载均衡方案的时候,可以将如下条目作为工程实现复杂度的参考:
- 是否需要开发一个基于DNS的服务路由前端
- 是否需要实现一个kubernetes平台级别的扩展服务
- 是否需要iptables NAT的支持
- 是否需要修改kubernetes生的iptables规则
- 是否需要修改kubernetes节点的内核网络配置
- 是否需要修改kubernetes/Openshift的代码
- 是否需要独占的kubernetes节点或者将节点进行分区使用
载自https://blog.csdn.net/cloudvtech
二、可选的解决方案
- 基于DNS和HTTP 302的转发
- 基于Openshift router的七层(haproxy)负载均衡
- 基于container host network模式的IPVS负载均衡
- 基于kubernetes nodeport service的IPVS负载均衡
载自https://blog.csdn.net/cloudvtech
三、各个方案概览和分析
3.1 基于DNS和HTTP 302的转发
在这个方案中,需要设计一个基于URL(域名或者访问路径)的HTTP request redirctor,这个转发器了解URL与后端服务POD的对于关系以及后端POD的服务能力,在请求过来之后,基于这些信息进行请求redirct。redirector向客户端返回HTTP 302重定向响应,这个响应将携带一个选中的后端服务POD的访问地址,客户端能理解这个302返回,并且访问这回返回包里面携带的资源重定向之后的POD的地址。
要实现这个方案,需要如下一些设定:
- 每个后端的服务POD需要有一个外部可达的IP地址
- 需要一个基于URL的redirector作为请求接入点,根据后端服务POD的部署情况和变化,进行redirect设置的动态调整
- 需要一个管理程序,维护一个外部IP地址池,管理这些地址的分配和收回,以及对POD进行IP地址配置和删除
方案的优点:
- 不需要扩展kubernetes平台服务
- 不需要配置复杂的iptabels规则
- 形成三角模式的流量,具有好的扩展性
方案缺点:
- 需要开发一个基于URL的redirector
- 需要一个管理外部IP地址池的程序
风险:
- 需要向Kubernetes管理的POD加入一个额外的NIC,不确定这个方式会带来什么影响
3.2 基于Openshift router的七层(haproxy)负载均衡
在这个方案中,使用基于haproxy实现的Openshift router服务,这个router是一个七层的proxy,除了处理请求还要处理返回流量,所以容易成为性能瓶颈。
要实现这个方案,需要如下一些设定:
- 需要为Openshift router配置DNS entry来保证多个router可以同时对外服务
- 需要一个router管理器来管理router的动态变化并进行配置
- 修改router来保证haproxy能动态了解服务POD的分布并且只将request proxy到本地的服务POD
优点:
- 不需要操作iptales
- 可以进行基于请求内容的七层proxying
- 形成三角模式的流量,具有好的扩展性
缺点:
- 需要haproxy的DNS entry的动态管理机制
- 需要修改Openshift router的控制机制
- 需要iptables NAT
风险:
- 基于七层代理的haproxy可能成为系统瓶颈
3.3 基于container host network模式的IPVS负载均衡
在这个模式下,无法使用就不能使用Kubernetes的网络支持功能,在POD启动之后,需要为每个POD配置macvlan网络,在这种方式下,IPVS可以和POD处在同一个LAN,使用IPVS的direct routing模式。具体配置可以参见这篇文章《container网络方案之macvlan》。
要实现这个方案,需要如下一些设定:
- 同一个工作节点上的每个服务POD需要不同的外部IP和端口
- 需要一个管理程序监控POD的增减并进行IP地址的管理和配置
优点:
- 不需要操作iptables
- 不需要iptables NAT
缺点:
- 需要管理程序管理IP池和给POD配置IP
- POD处于特权模式,不利于安全性
3.4 基于kubernetes nodeport service的IPVS负载均衡
在这个模式下,IPVS运行在直接路由模式,后端服务通过node port service暴露,请求从IPVS director进入,响应从节点直接返回客户,形成三角模式流量。
要实现这个方案,需要如下一些设定:
- 需要一个管理程序来感知POD和工作节点的变化,来调整负载均衡转发目标权重
- 需要抢占系统的port资源作为服务的node port
- 在部署的时候需要对工作节点进行一些配置
优点:
- 没有内部流量中继
- 形成三角流量
- 扩展性很好
缺点:
- 需要一个IPVS控制器来感知kubernetes POD的变化来对IPVS负载均衡权重和目标进行配置
- 需要扩展kubernetes的系统服务来运行IPVS控制器,并且这个服务处于特权模式
- 需要使用kubernetes的源IP保持服务,见文章《kubernetes的源地址保持(source IP preserve)》
- 需要对节点的arp进行配置
- 需要对节点的label进行配置
- 需要对节点的iptables进行配置