服务器向外部提供服务,当一台服务器承受过多的压力,那么服务可能会产生服务不可用的情况,所以,我们应该让一台服务器承受的压力在合理范围内,如果一台服务器无法满足需求,那么可以横向扩展使用多台服务器分摊这些压力,这些服务器作为一个整体对外提供服务,并且分摊压力时,那么我们可以称这些服务器为"负载均衡集群"。
LVS 是 Linux Virtual Server 的简称,也就是 Linux 虚拟服务器。现在 LVS 已经是 Linux 标准内核的一部分,从 Linux2.4 内核以后,已经完全内置了 LVS 的各个功能模块,无需给内核打任何补丁,可以直接使用 LVS 提供的各种功能。LVS在内核中名称是ipvs,作为netfilter的模块存在,管理ipvs的工具为ipvsadm。
LVS 是四层负载均衡,也就是说建立在 OSI 模型的第四层——传输层之上,传输层上有我们熟悉的 TCP/UDP,LVS 支持 TCP/UDP 的负载均衡。因为 LVS 是四层负载均衡,因此它相对于其它高层负载均衡的解决办法,比如 DNS 域名轮流解析、应用层负载的调度、客户端的调度等,它的效率是非常高的。
为方便后续探讨,这里先说明下几个名词
VS: Virtual Server,调度器,负责调度
RS: Real Server,负责真正提供服务,后端服务器
VIP: LVS服务器上的公网IP,即Virtual IP
DIP: LVS服务器上的内网IP,即Director IP
RIP: Real Server上的内网IP
CIP: 客户端的IP
工作原理:
VS根据请求报文的目标IP和目标协议及端口将其调度转发至某RS,根据调度算法来挑选RS。
LVS 的工作模式:
NAT :
SNAT: 修改源地址
DNAT: 修改目标地址
DR : 修改目标 MAC
TUN : 在原请求IP报文之外新加一个IP首部
FULLNAT: 修改请求报文的源和目标IP
LVS的工作位置
LVS-NAT模式:
LVS-NAT报文中IP转换过程
上图所示:
1.客户端的请求会发往LVS主机,此时,客户端请求报文的源IP为CIP,目标IP为LVS的VIP
2.当LVS收到客户端的请求报文时,会将请求报文中的目标IP修改为后端某个RealServer的RIP,具体为哪个RealServer的RIP,取决于LVS使用的具体算法
3.当RealServer收到对应的请求报文时,会发现报文的目标IP就是自己的RIP,于是就会接收报文并 处理后进行响应。响应报文的源IP则为RIP,目标IP则为CIP
4.当LVS收到对应的响应报文时,LVS会将响应报文的源IP修改为VIP,目标IP不变为CIP,于是响应报文被发往客户端。
5.客户端则会收到响应报文,源IP为VIP,端口为80,而LVS相对于客户端而言,转换过程是透明的。
优点:集群中的物理服务器可以使用任何支持TCP/IP操作系统,物理服务器可以分配Internet的保留 私有地址,只有负载均衡器需要一个合法的IP地址。
缺点:扩展性有限。当服务器节点(普通PC服务器)数量增长到20个或更多时,负载均衡器将成为整个系统的瓶颈,因为所有的请求包和应答包都需要经过负载均衡器再生。
LVS-NAT的建议:
(1)RIP和DIP建议在同一个IP网络,且应使用私网地址;RS的网关要指向DIP(中间无其他设备)
(2)请求报文和响应报文都必须经由LVS转发,LVS易于成为系统瓶颈。但是也能满足一般需求
(3)支持端口映射,可修改请求报文的目标PORT
(4)VS必须是Linux系统,RS可以是任意OS系统
LVS-DR模式:
LVS默认模式。直接路由,应用最广泛,通过为请求报文重新封装一个MAC首部进行转发。
DR 模式下需要 LVS 和 RS 集群绑定同一个 VIP(RS 通过将 VIP 绑定在 loopback 实现),
请求报文由 LVS 接受,响应报文不经过 LVS,由RealServer(RS)直接返回给用户。因此,DR 模式具有较好的性能,也是目前大型网站使用最广泛的一种负载均衡手段。
源MAC是DIP所在的接口的MAC,
目标MAC是调度算法选出的RS的RIP所在接口的MAC地址;
源IP/端口,以及目标IP/端口均保持不变
LVS和各RS都配置有VIP
LVS-DR报文中IP和MAC转换过程
上图所示:
1.客户端的请求会发往LVS主机,此时,客户端请求报文的源IP为CIP,目标IP为LVS的VIP
2.当LVS收到客户端的请求报文时,会将请求报文中的源MAC修改为本机的DIP所在网卡的MAC,把目标MAC修改为后端某个RealServer的RIP的MAC,具体为哪个RealServer的RIP,取决于LVS使用的具体算法。其他不作修改。
3.当RealServer收到对应的请求报文时,因为RealServer会在本机的LO上绑定了VIP的地址,并且会因为在内核中修改了ARP相关参数从而在同一网络中同时拥有了与LVS同样的IP地址,因此在接收到请求报文时会发现报文的目标IP就是自己的VIP,于是就会接收报文并处理后不经过LVS进行响应。响应报文的源IP则为VIP,目标IP则为CIP,源MAC地址则为RS发送数据包的MAC,目标MAC则为最近的路由MAC。
4.客户端则会收到响应报文,源IP为VIP,端口为80。而LVS相对于客户端而言,转换过程是透明的。
优点:负载均衡器也只是分发请求,应答包通过单独的路由方法返回给客户端。与LVS-TUN相比,LVS-DR这种实现方式不需要隧道结构,因此可以使用大多数操作系统做为物理服务器。
缺点:要求负载均衡器的网卡必须与物理网卡在一个物理段上。
因为VIP在同一网络中同时存在,必须改变RealServer 对APR报文响应规则
方法1:在RS上使用arptables工具
# arptables -A IN -d $VIP -j DROP
# arptables -A OUT -s $VIP -j mangle --mangle-ip-s $RIP
方法2:在RS上修改内核参数以限制arp通告及应答级别 (推荐)
arp_announce = 2
arp_ignore = 1
LVS-DR的建议:
(1) RealServer的RIP建议使用私网地址。RIP与DIP在同一IP网络;RIP的网关不能指向DIP,以确保响应报文 不会经过VS
(2) LVS和RS要在同一个物理网络。不能跨地域物理网络调度。
(3) 请求报文要经由VS,但响应报文不经由VS,而由RealServer直接发往Client
(4) 不支持端口映射(端口不能修改)
(5) RealServer可使用大多数OS系统
(6) VS可以只要一块网卡,同时配置VIP和DIP,注意路由走向。
LVS-TUN模式:
转发方式工作,不修改请求报文的IP首部,而在原IP报文之外再封装一个IP首部(源IP是DIP,目标IP是RIP),将报文发往挑选出的目标RealServer;RealServer直接响应给客户端(源IP是VIP,目标IP是CIP)
LVS-TUN报文中IP包头转换过程
上图所示:
1.客户端的请求会发往LVS主机,此时,客户端请求报文的源IP为CIP,目标IP为LVS的VIP
2.当LVS收到客户端的请求报文时,会在原请求报文基础上再封装一个新的IP包头,源IP为本机的DIP,目标IP为后端某个RealServer的RIP,具体为哪个RealServer的RIP,取决于LVS使用的具体算法。其他不作修改。
3.当RealServer收到对应的请求报文时,在接收到请求报文时会发现报文的目标IP就是自己的RIP,于是就会接收报文并处理后不经过LVS进行响应。响应报文的源IP则为VIP,目标IP则为CIP。
4.客户端则会收到响应报文,源IP为VIP,端口为80。而LVS相对于客户端而言,转换过程是透明的。
优点:负载均衡器只负责将请求包分发给物理服务器,而物理服务器将应答包直接发给用户。所以,负载均衡器能处理很巨大的请求量,这种方式,一台负载均衡能为超过100台的物理服务器服务,负载均衡器不再是系统的瓶颈。
缺点:这种方式需要所有的服务器支持"IP Tunneling"(IP Encapsulation)协议。
LVS-TUN的建议:
(1) DIP, VIP, RIP都应该是公网地址(或具备跨网络通讯支持)
(2) RS的网关不能指向DIP
(3) 请求报文要经由VS,但响应不能经由VS
(4) 不支持端口映射
(5) RealServer的OS须支持隧道功能。相对DR模式来讲,具备跨地域物理网络调度。
LVS-FULLNAT模式:
转发工作。通过同时修改请求报文的源IP地址和目标IP地址进行转发。
LVS-FULLNAT报文中IP包头转换过程
上图所示:
1.客户端的请求会发往LVS主机,此时,客户端请求报文的源IP为CIP,目标IP为LVS的VIP
2.当LVS收到客户端的请求报文时,会将源IP修改为本机的DIP,同时将请求报文中的目标IP修改为后端某个RealServer的RIP,具体为哪个RealServer的RIP,取决于LVS使用的具体算法
3.当RealServer收到对应的请求报文时,会发现报文的目标IP就是自己的RIP,于是就会接收报文并 处理后进行响应。响应报文的源IP则为RIP,目标IP则为DIP
4.当LVS收到对应的响应报文时,LVS会将响应报文的源IP修改为VIP,目标IP修改为CIP,于是响应报文被发往客户端。
5.客户端则会收到响应报文,源IP为VIP,端口为80,而LVS相对于客户端而言,转换过程是透明的。
LVS-FULLNAT的建议:
(1) VIP是公网地址,RIP和DIP是私网地址,且通常不在同一IP网络;因此,RIP的网关一般不会 指向DIP
(2) RS收到的请求报文源地址是DIP,因此,只需响应给DIP;但VS还要将其发往Client
(3) 请求和响应报文都经由VS,LVS易于成为系统瓶颈。但是也能满足一般需求
(4) 支持端口映射
注意:此类型kernel默认不支持
实验:lvs调度器实现
实验:keepalived实现基于VIP地址飘动(主备keepalived实现VIP地址飘到)
实验:实验双主kepalived的VIP地址飘到
在CentOS7.6_1.0_test4机器操作
在/etc/keepalived/keepalived.conf配置文件中
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keeplived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id ka1
vrrp_mcast_group4 224.100.100.100
}
vrrp_instance VI_1 {
state MASTER
interface ens37
virtual_router_id 66
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.111.100/24 dev ens37 label ens37:1
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
vrrp_instance VI_2 {
state BACKUP
interface ens37
virtual_router_id 88
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 654321
}
virtual_ipaddress {
192.168.111.200/24 dev ens37 label ens37:2
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
在CentOS7.6_1.0_test5机器操作
在/etc/keepalived/keepalived.conf配置文件中
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keeplived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id ka2
vrrp_mcast_group4 224.100.100.100
}
vrrp_instance VI_1 {
state BACKUP
interface ens37
virtual_router_id 66
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.111.100/24 dev ens37 label ens37:1
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
vrrp_instance VI_2 {
state MASTER
interface ens37
virtual_router_id 88
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 654321
}
virtual_ipaddress {
192.168.111.200/24 dev ens37 label ens37:2
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
keepalived实现nginx反向代理的高可用性(主备模式)
在CentOS7.6_1.0test4中/etc/keepalived/keepalive.conf配置文件
! Configuration File for keepalived
global_defs {
notification_email{
admin@quguwei.net
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id ka1
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_down {
script "/etc/keepalived/test.sh"
interval 1
weight -30
}
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 1
weight -30
}
vrrp_instance VI_1 {
state MASTER
interface ens37
virtual_router_id 66
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.111.100/24 ens37 label ens37:1
}
track_script {
chk_down
chk_nginx
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
在CentOS7.6_1.0test5中/etc/keepalived/keepalive.conf配置文件
! Configuration File for keepalived
global_defs {
notification_email{
admin@quguwei.net
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id ka2
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
vrrp_mcast_group4 224.0.199.32
}
vrrp_script chk_down {
script "/etc/keepalived/test.sh"
interval 1
weight -30
}
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 1
weight -30
}
vrrp_instance VI_1 {
state BACKUP
interface ens37
virtual_router_id 66
priority 80
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.111.100/24 ens37 label ens37:1
}
track_script {
chk_down
}
track_script {
chk_down
chk_nginx
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}