LVS负载均衡
LVS 由2部分程序组成,包括 ipvs 和 ipvsadm,LVS基于linux内核的netfilter机制,以IP的HOOK链为切入点,注册实现了多个HOOK函数来完成具体功能
- 用户空间: ipvsadm就是实现命令行管理,也就是客户端工具
- 内核空间:ipvs就是依赖netfilter机制之上的一个个模块功能
- LVS在2.6版本就已经集成到内核中,所以只要关注ipvs模块是否加载就行
同样iptables也是基于netfilter机制,所以iptables也是能实现负载均衡,一般不会选择而已(K8s支持2个方式)
LVS-DR模式
DR模式是真正LVS性能最好的,但是有前提条件存在,就是负载调度器和真实服务器要属于一个广播域(一个网段内)
看一个转发流程(注意调度器转发用户端的源地址是没有改变的)
无法建立,因为用户发出去的源和目的无法匹配,TCP肯定建立不起来,需要解决方案
解决的方案
- 怎么让RS1的源地址变成192.168.1.100,这样就能实现TCP的建立
- 利用网络二层MAC地址通讯原理,调度器收到数据包后进行包头的修改,把目的IP改成了自己(192.168.1.100)MAC地址改成RS1的,转发给RS1,同样RS1能转发给用户端也要有一个192.168.1.100源地址才行
为什么RS1能收到?
- 这个就是条件,一个广播域内,也就是基于网络的二层转发给RS1,而二层是基于MAC地址转发的,不看三层IP地址,如果不在一个广播域数据包就会现转发给网关,这个就进行三层通讯了
RS1为什么能转发?
- 因为1.100这个地址已经被调度器使用,正常RS1配置相同IP是无法使用的,会地址冲突,冲突的原因是主机在配置IP的时候会发免费arp广播包,这样调度器就会收到arp报文,知道了原理剩下就怎么让RS1不发arp广播包,不就可以解决问题了,而发不发广播包是程序写的,只要关闭就可以了
arp_ignore
arp_ignore是解决RS1的ARP相应级别,也就是如果我们主机有多个网卡默认只要网卡接收到就会进行相应,这样就导致源地址发生改变
- arp_ignore=0,默认级别,表示响应任意网卡上接收到的对本机IP地址的arp请求(包括环回网卡上的地址),而不管该目的IP是否在接收网卡上
- arp_ignore=1,只有匹配到调度器请求的目的地址才进行相应(也就是到192.168.1.100这个网卡上)
arp_announce
当192.168.1.100进行回应,这个时候需要知道用户端的MAC地址,就会进行ARP广播,如果多网卡情况下默认所有的网卡都会进行广播通告,这样就导致ARP表混乱,因为交换机接口会频繁更新arp表,因为主机通告的mac地址发生了改变
- arp_announce=0,默认选项,源ip可以随意选择,也就是全部网卡都会进行arp泛洪
- arp_announce=1,尽可能的避免随意选择
- arp_announce=2,向目的网络回应匹配的IP信息,也就是匹配调度器的目的IP进行回应
arp_ignore=1和arp_announce=2就能实现了
vim /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
#参数分别有all,default,lo,eth0等对应不同网卡
# sysctl -p
路由问题
由于 arp_ignore=1和arp_announce=2的设置,导致主机RS1收不到调度器转发的流量,因为RS1真实的IP地址不会响应和通告,因为跟自己没关系,是发给192.168.1.100(RS1的隐藏IP)怎么办?
- 配置主机路由去往192.168.1.100转给lo网卡(一般我们都会把调度器IP配置到本地回环口上lo接口)这样eth0接受到数据包会转发给lo(lo当然配置是子接口)
lo接口特性:
1、虚拟接口,状态永远UP,稳定性高
2、可以配置掩码为全1的IP地址,节省IP还能防止其他问题出现
route add -host 192.168.1.100 dev lo:0
#主机路由
调度器的VIP地址
- 因为VIP地址需要用于其他的机器共享使用,调度器的VIP地址都会被设置成网卡的子接口,因为这个地址可能会更改,而子接口就起到了方便,也可以叫调度器的IP叫VIP
accept_redirects和send_redirects(网卡重定向)
- 当服务器接收数据接口和发送数据接口都是来源一个IP地址就会触发网卡发送ICMP重定向给源,通知源IP有更优的路由,你不要发给我了,直接给目的网关,这样就会导致调度器不会把流量转发给真实服务器,就需要关闭调度器的发送和接收重定向功能
vim /etc/sysctl.conf
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# sysctl -p
总结
- 调度器和真实服务器需要在一个广播域
- 真实服务器的网关是指向自己真实的网关
- 调度器只处理入站请求,压力最小
- 端口需要一致
实例
LVS服务器(DS) DIP:192.168.26.140 VIP:192.168.26.240
nginx1服务器(RS) RIP:192.168.26.241 VIP:192.168.26.240
nginx2服务器(RS) RIP:192.168.26.242 VIP:192.168.26.240
LVS调度器配置
[root@LVS1 ~]# ls /usr/lib/modules/3.10.0-957.el7.x86_64/kernel/net/netfilter/ipvs/ |grep -e ip_vs
ip_vs_dh.ko.xz
ip_vs_ftp.ko.xz
ip_vs.ko.xz
ip_vs_lblc.ko.xz
ip_vs_lblcr.ko.xz
ip_vs_lc.ko.xz
ip_vs_nq.ko.xz
ip_vs_pe_sip.ko.xz
ip_vs_rr.ko.xz
ip_vs_sed.ko.xz
ip_vs_sh.ko.xz
ip_vs_wlc.ko.xz
ip_vs_wrr.ko.xz
#查询内核是否集成了LVS模块
lsmod |grep ip_vs
#是否加载是取决于系统是否调用lvs模块,只要确保内核集成即可
yum install -y ipvsadm
# 安装用户管理工具
ipvsadm --save > /etc/sysconfig/ipvsadm
systemctl start ipvsadm
systemctl enable ipvsadm
#确保服务的正常启动,不然配置无法永久保存
cd /etc/sysconfig/network-scripts
cp ifcfg-ens33 ifcfg-ens33:0
vi ifcfg-ens33:0
DEVICE=ens33:0
BOOTPROTO=static
IPADDR=192.168.26.240
NETMASK=255.255.255.0
ONBOOT=yes
TYPE=Ethernet
#配置VIP虚拟IP地址
vi /etc/sysctl.conf
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
#sysctl -p
LVS负载配置
ipvsadm -A -t 192.168.26.240:80 -s rr
# 添加虚拟服务,指定IP、端口、算法(rr轮询算法)
ipvsadm -a -t 192.168.26.240:80 -r 192.168.26.141:80 -g
ipvsadm -a -t 192.168.26.240:80 -r 192.168.26.142:80 -g
#添加真实服务,指定DR模式(-g)如果是nat模式(-m)
ipvsadm --save
#永久保存配置,确保ipvsadm服务已经正常
真实服务器节点
vi /etc/sysctl.conf
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
#sysctl -p
#关闭ARP的响应和公告通知
cd /etc/sysconfig/network-scripts
cp ifcfg-lo ifcfg-lo:0
vi ifcfg-lo:0
DEVICE=lo:0
IPADDR=192.168.26.240
NETMASK=255.255.255.255
BROADCAST=192.168.26.240
ONBOOT=yes
#配置lo子接口VIP
route add -host 192.168.26.240 dev lo:0 (重启失效)
#添加主机路由
vi /etc/sysconfig/network-scripts/route-lo:0
192.168.26.240/32 dev lo:0
#添加永久路由
#客户端安装nginx进行测试
可以看到OutBytes是没有数据包的,也就验证了DR模式只负责接收不负责转发
每次都是轮询访问