负载均衡
网络技术,LB要解决的问题本质上是网络的问题,所以它实际上就是通过修改数据包中MAC地址、IP地址字段来实现数据包的“中转”;
资源,这里的资源不仅仅是计算机也可以是交换机、存储设备等;
最优,它则是针对业务而言最优,所以一般负载均衡有很多算法;轮询、加权轮询、最小负载等;
实现LB的问题

修改数据包,使得数据包可以发送到backend servers;
frontend server要维护一个算法,可以选出最优的backend server
frontend server要维护一张表记录Client和backend servers的关系(比如TCP请求是一系列数据包,所以在TCP关闭所有的数据包都应该发送到同一个backend server)
LVS的实现

IP包处理模块,用于截取/改写IP报文;
连接表管理,用于记录当前连接的Hash表;
调度算法模块,提供了八种负载均衡算法——轮询、加权轮询、最少链接、加权最少链接、局部性最少链接、带复制的局部性最少链接、目标地址哈希、源地址哈希;
连接状态收集,回收已经过时的连接;
统计,IPVS的统计信息;
LVS实战
DS:Director Server,前端负载均衡器节点(后文用Director称呼);
RS:Real Server,后端真实服务器;
VIP:用户请求的目标的IP地址,一般是公网IP地址;
DIP:Director Server IP,Director和Real Server通讯的内网IP地址;
RIP:Real Server IP,Director和Real Server通讯的内网IP地址;
NAT模式中,RS返回数据包是返回给Director,Director再返回给客户端;
DR(Direct Routing)模式中,RS返回数据是直接返回给客户端(通过额外的路由);Director通过修改请求中目标地址MAC为选定的RS实现数据转发,这就要求Diretor和Real Server必须在同一个广播域内(关于广播域请看《程序员学网络系列》)。
TUN(IP Tunneling)模式中,RS返回的数据也是直接返回给客户端,这种模式通过Overlay协议(把一个IP数据包封装到另一个数据包内部叫Overlay)避免了DR的限制。
NAT模式

配置IP地址

注意:Director配置了双网卡,默认路由指向10.10.10.1。即——VIP所在的网卡设置网关,DIP所在的网卡不要设置网关。
配置director
ipvsadm -A -t 10.10.10.10:80 -s rr # 添加LVS集群,负载均衡算法为轮询(rr)
ipvsadm -a -t 10.10.10.10:80 -r 192.168.122.101 -m -w 1 # 添加LVS集群主机(10.10.10.10:80),VS调度模式为NAT(-m)及RS权重为1
ipvsadm -a -t 10.10.10.10:80 -r 192.168.122.102 -m -w 1 # 同上
验证

NAT模式原理解析
client发送数据包,被路由到director服务器上;
director的netfilter local_in hook被触发,lvs模块收到该请求
lvs查询规则库(ipvsadm生成的规则),发现10.10.10.10:80端口被定义为NAT模式,执行轮询算法
IP包处理模块修改数据包,把目标IP地址修改为192.168.122.101,从DIP的所在网卡发送出去(所以源MAC是DIP网卡的MAC)。此时的数据包是:源MAC地址变成了00:01:3a:4d:5d:00(DIP网卡的MAC地址)源IP地址是172.10.10.10(client的IP地址),目标MAC和目标IP地址是本机地址。通过在RS1上抓包验证这一点

RS1收到请求目标MAC和IP都是本机,所以直接交给Nginx处理
Nginx的返回数据包交给Linux协议栈,系统发现目标地址是172.10.10.10和自己不在同一个网段,则把数据包交给网关——192.168.122.100(director)。这就是Real Server必须把网关指向Director Server的原因
director上的lvs再次触发,发现是返回数据包是:源MAC地址和IP地址是VIP网卡的MAC地址
DR模式

所以DR模式中要求
Director和RS必须在同一个广播域中,也就是二层可达(实验的拓扑中是通过SW2实现的) ,因为Director要修改目标MAC地址所以数据包只能在广播域内转发;
RS必须可以路由到用户,也就是三层可达(实验的拓扑中Director和Real server共享同一个路由),因为Real Server的返回数据包是直接返回给用户的不经过Director;
配置IP
配置Real Server
#绑定VIP到本机的环回口
ifconfig lo:0 10.10.10.10 netmask 255.255.255.255 broadcast 10.10.10.10 up
#禁用ARP响应
echo 1 > proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > proc/sys/net/ipv4/conf/lo/arp_announce
配置Director
ipvsadm -A -t 10.10.10.10:80 -s rr # 添加LVS集群,负载均衡算法为轮询(rr)
ipvsadm -a -t 10.10.10.10:80 -r 192.168.122.101 -g -w 1 # 添加LVS集群主机(10.10.10.10:80),VS调度模式为DR(-g)及RS权重为1
ipvsadm -a -t 10.10.10.10:80 -r 192.168.122.102 -g -w 1 # 同上
验证

DR模式原理解析
client发送数据包,被路由到director服务器上;
director的netfilter local_in hook被触发,lvs模块收到该请求
lvs查询规则库(ipvsadm生成的规则),发现10.10.10.10:80端口被定义为DR模式,执行轮询算法
IP包处理模块修改数据包,把目标MAC修改为选中的RS的MAC地址,从DIP的所在网卡发送出去(所以源MAC是DIP网卡的MAC)。此时的数据包是:源MAC地址变成了00:01:3a:4d:5d:00(DIP网卡的MAC地址)源IP地址是172.10.10.10(client的IP地址),目标MAC是00:01:3a:f4:c5:00(RS的MAC)目标IP地址10.10.10.10(VIP)。通过在RS1上抓包验证这一点

RS1收到请求目标MAC和IP都是本机(VIP配置在本机的环回口),所以直接交给Nginx处理
Nginx的返回数据包交给Linux协议栈,系统发现目标地址是172.10.10.10和自己不在同一个网段,则把数据包交给网关——192.168.122.1。在我们的试验中R1是网关,它是可以直接返回数据给客户端的,所以数据被成功返回到客户端。
TUN模式

Director和Real Server必须三层可达,拓扑图中故意加上一个R2用于分割两个广播域;
Real Server必须可以路由到用户,也就是三层可达(实验的拓扑中Director和Real server共享同一个路由),因为RS的返回数据包是直接返回给用户的不经过Director;
因为采用Overlay协议,Real Server的MTU值必须设置为1480(1500-20)——即实际上能发送的数据要加上外层IP头部
总结
LVS NAT的改进
在用户空间实现一个反向代理,比如Nginx;
修改LVS代码重新编译内核
ipvsadm -A -t 192.168.122.100:80 -s rr
ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.101 -m -w 1
ipvsadm -a -t 192.168.122.100:80 -r 192.168.122.102 -m -w 1
两个疑问
为啥LVS不直接做彻底的NAT而直接使用客户端IP地址呢?改进后的NAT怎么规避这个问题?
Linux内核为什么不吸纳FullNAT模式?
欢迎关注公众账号了解更多信息“写程序的康德——思考、批判、理性”





