由于OpenVPN不支持多线程处理,无法利用多核CPU、网卡多队列的优势。为了提升服务器CPU的利用率,增强数据处理能力、提升VPN总带宽,为服务器部署多个独立的OpenVPN工作进程,组成OpenVPN集群。
基于OSI网络模型4层进行负载均衡,性能较高,使用LVS做UDP协议端口负载均衡,可以基于ipvsadm或者keepalived组件做lvs负载配置。
lvs支持多种负载均衡算法,这里采用最小连接(Least-Connection)策略,该策略在客户端下线后会更新在线连接数量,再根据在线连接数量进行负载均衡,因此能较均衡的分配在线连接的客户端数量,使OpenVPN集群各个节点尽可能均衡地负载客户端连接的压力。
多个进程服务端,怎么保持客户端的会话状态。由于多个OpenVPN进程之间数据状态是不共享的,所以需要将同一个会话的请求都调度到同一个OpenVPN节点,保证业务的持续性。要将来自同一个客户端IP的请求转发到同一个RS,可以通过设置IPVS的持久化时间persistence_timeout,通过设置这个持久化时间,可以实现会话保持。当客户端UDP连接到达IPVS后,IPVS会在记录表里添加一条state为UDP的连接记录。该连接记录的源IP为客户端IP,端口为客户端端口,超时时间为上面所说的持久化时间persistence_timeout,超时剩余时间会逐步减小,在UDP的超时时间减到0之前,如果客户端与服务端之间还有交互,则persistence_timeout值会刷新为初始值。在该UDP状态的连接记录存在的期间,同一客户端IP的消息都会被调度到同一个RS节点。每当客户端和服务端的连接中有信息交互时,该超时时间都会刷新为初始值。如果连接处于空闲状态,即一直没有信息交互,则等到该值超时后,该UDP连接记录会直接消失,后续同一客户端(IP+Port)过来的请求会重新调度。所以要使同一客户端的会话请求始终负载到同一个OpenVPN服务,需要VPN客户端与VPN服务端维持心跳交互,且心跳间隔时间小于IPVS的持久化时间persistence_timeout。
VPN多进程负载均衡高可用实施步骤:
- 创建1个OpenVPN配置文件,里面放置4个OpenVPN进程的相同的参数;
- 启动4个OpenVPN进程,分别指定对应的端口(例如1195~1198端口)和虚拟子网(例如172.16.1.0/24~172.16.4.0/24子网);
- ipvsadm --set 0 0 30 设置IPVS UDP连接超时时间为30秒,这个时间不宜过大也不宜过小,可以是VPN客户端与服务端心跳间隔(10秒)的3倍,即3次心跳连接都失败才将认为客户端掉线,这样既可以减少对掉线操作的误判又不至于保留过多的已失效连接;
- 绑定需要负载均衡的端口(以10.10.0.1为例),ipvsadm -A -u 10.10.0.1:1194 -s lc,其中lc为采用最小连接(Least-Connection)负载均衡策略,采用最小连接数策略可以尽可能使在线的连接用户数保持均衡分布;
- 添加后端服务ipvsadm -a -u 10.10.0.1:1194 -r 10.10.0.1:1195 –m,类似的,可以添加端口号为1195~1198的后端服务;
- 最后由探活脚本周期性检测OpenVPN进程的UDP服务是否正常,如果不正常则将其从ipvsadm后端服务列表移除,恢复后则将其重新加入列表。