一、基础知识
1. 四层负载均衡(基于IP+端口的负载均衡)
所谓四层负载均衡,也就是主要通过报文中的目标ip地址和端口,再加上负载均衡设备设置的服务器选择方式(分发策略,轮询),决定最终选择的内部服务器。
layer4
在三层负载均衡的基础上,通过发布三层的IP地址(VIP),然后加四层的端口号,来决定哪些流量需要做负载均衡,对需要处理的流量进行NAT处理,转发至后台服务器,并记录下这个TCP或者UDP的流量是由哪台服务器处理的,后续这个连接的所有流量都同样转发到同一台服务器处理。
以常见的TCP为例,负载均衡设备在接收到第一个来自客户端的SYN 请求时,即通过上述方式选择一个最佳的服务器,并对报文中目标IP地址进行修改(改为后端服务器IP),直接转发给该服务器。TCP的连接建立,即三次握手是客户端和服务器直接建立的,负载均衡设备只是起到一个转发动作。在某些部署情况下,为保证服务器回包可以正确返回给负载均衡设备,在转发报文的同时可能还会对报文原来的源地址进行修改。
实现四层负载均衡的有:
F5:硬件负载均衡器,功能很好,但是成本很高。
lvs:重量级的四层负载均衡软件
haproxy:模拟四层、七层转发,较灵活
2. LVS 介绍
LVS 是一种预装在 Linux 系统中,基于四层、具有强大性能的反向代理服务器/负载均衡器
(1)LVS 是Linux Virtual Server的简称,也就是 Linux 虚拟服务器, 是一个由章文嵩博士发起的自由软件项目,它的官方站点是www.linuxvirtualserver.org。现在LVS已经是 Linux标准内核的一部分,因此性能较高。
(2)LVS软件作用:通过LVS提供的负载均衡技术实现一个高性能、高可用的服务器群集,它具有良好可靠性、可扩展性和可操作性。从而以低廉的成本实现最优的服务性能。
3. LVS 优势与不足
(1)优势
高并发连接:LVS基于内核工作,有超强的承载能力和并发处理能力。单台LVS负载均衡器,可支持上万并发连接。
稳定性强:是工作在网络4层之上仅作分发之用,这个特点也决定了它在负载均衡软件里的性能最强,稳定性最好,对内存和cpu资源消耗极低。
成本低廉:硬件负载均衡器少则十几万,多则几十万上百万,LVS只需一台服务器和就能免费部署使用,性价比极高。
配置简单:LVS配置非常简单,仅需几行命令即可完成配置,也可写成脚本进行管理。
支持多种算法:支持多种论调算法,可根据业务场景灵活调配进行使用
支持多种工作模型:可根据业务场景,使用不同的工作模式来解决生产环境请求处理问题。
应用范围广:因为LVS工作在4层,所以它几乎可以对所有应用做负载均衡,包括http、数据库、DNS、ftp服务等等
(2)不足
工作在4层,不支持7层规则修改,机制过于庞大,不适合小规模应用。
4. LVS 工作内核模型及工作模式
当客户端的请求到达负载均衡器的内核空间时,首先会到达 PREROUTING 链。
当内核发现请求数据包的目的地址是本机时,将数据包送往 INPUT 链。
LVS由用户空间的ipvsadm和内核空间的IPVS组成,ipvsadm用来定义规则,IPVS利用ipvsadm定义的规则工作,IPVS工作在INPUT链上,当数据包到达INPUT链时,首先会被IPVS检查,如果数据包里面的目的地址及端口没有在规则里面,那么这条数据包将被放行至用户空间。
如果数据包里面的目的地址及端口在规则里面,那么这条数据报文将被修改目的地址为事先定义好的后端服务器,并送往POSTROUTING链。
最后经由POSTROUTING链发往后端服务器。
5. LVS 负载均衡四种工作模式
LVS/NAT:网络地址转换模式,进站/出站的数据流量经过分发器/负载均衡器(IP负载均衡,他修改的是IP地址) --利用三层功能
LVS/DR:直接路由模式,只有进站的数据流量经过分发器/负载均衡器(数据链路层负载均衡,因为他修改的是目的mac地址)--利用二层功能mac地址
LVS/TUN:隧道模式,只有进站的数据流量经过分发器/负载均衡器
LVS/full-nat:双向转换,通过请求报文的源地址为DIP,目标为RIP来实现转发:对于响应报文而言,修改源地址为VIP,目标地址为CIP来实现转发
6. DR 模式原理
负载均衡器和RS都使用同一个IP对外服务,但只有DB对ARP请求进行响应,所有RS对本身这个IP的ARP请求保持静默,也就是说,网关会把对这个服务IP的请求全部定向给DB,而DB收到数据包后根据调度算法,找出对应的RS,把目的MAC地址改为RS的MAC(因为IP一致)并将请求分发给这台RS。这时RS收到这个数据包,处理完成之后,由于IP一致,可以直接将数据返给客户,则等于直接从客户端收到这个数据包无异,处理后直接返回给客户端。
如下图所示,实线框表示实体,虚线框表示数据包,虚线及箭头表示数据包流向:
┌Client┐ ┌---[3]---┐ ┌────RS1────┐
│ │<-----------------| VIP|CIP |<--------------------┐ ┌┤lo:VIP │
│ │ └---------┘ └---││eth0:RIP1 │
│ │ ┌────LVS────┐ ┌-----[2]-----┐ │└───────────┘
│ │ ┌---[1]---┐ │ │ | CIP|VIP | ┌-->│┌────RS2────┐
│ CIP│---| CIP|VIP |-->│VIP DIP│---|DIPmac|RIPmac|--┘ └┤lo:VIP │
│ │ └---------┘ │ │ └-------------┘ │eth0:RIP2 │
└──────┘ └───────────┘ └───────────┘
[1] 数据包CIP|VIP发送给LVS
[2] LVS通过修改MAC地址把数据包直接扔给RS,由于RS也有VIP,所以收下数据包
[3] RS处理完成后,直接封数据包VIP|CIP,返回给客户端,不经过LVS
特征:
保证前端路由将目标地址为VIP报文统统发给LVS,而不是RS(因为RS的VIP是隐藏的)
RS跟LVS必须在同一个物理网络中(因为MAC地址欺骗/ARP欺骗就只能发生在局域网中)
所有的请求报文经由LVS,但响应报文必须不能经过LVS
不支持地址转换,也不支持端口映射(因为这是链路层/2层的处理,不涉及到IP)
RS的网关绝不允许指向DIP(因为我们不允许他经过LVS)
RS上的lo接口配置VIP的IP地址(对外隐藏,对内可见)
7. LVS 核心组件
LVS的管理工具和内核模块 ipvsadm/ipvs
ipvsadm:用户空间的命令行工具,用于管理集群服务及集群服务上的RS等;
ipvs:工作于内核上的程序,可根据用户定义的集群实现请求转发;
8. LVS 相关术语
LB (Load Balancer) 负载均衡
HA (High Available) 高可用
LVS (Linux Virtual Server) Linux 虚拟服务器
DB (Director, Balancer) 负载均衡器、分发器
DS (Director Server) 前端负载均衡器节点
RS (Real Server) 后端真实的工作服务器
VIP (Virtual IP) 虚拟的 IP 地址,向外部直接面向用户请求,作为用户请求的目标的 IP 地址
DIP (Director IP) 主要用于和内部主机通讯的 IP 地址
RIP (Real Server IP) 后端服务器的 IP 地址
CIP (Client IP) 访问客户端的 IP 地址
9. 其他
ipvsadm 是 LVS 的命令行管理工具,但使用 keepalived 配置更方便
keepalived 是 LVS 的扩展项目, 因此它们之间具备良好的兼容性,可直接通过 Keepalived 的配置文件来配置 LVS
LVS 架构中存在一个虚拟 IP 的概念,需要多申请一个 IP 来做虚拟 IP
而 Nginx 等软件是基于七层的负载均衡器,因此尽管配置、使用灵活,但考虑性能与原生的话还是首选 LVS
免费开源的高可用软件keepalived:
a. Keepalived通过VRRP协议实现高可用功能,VRRP是Virtual Router Redundancy Protocol(虚拟路由器冗余协议)
b. VRRP的目的是为了解决静态路由单点故障问题的,它能够保证当个别节点宕机时,整个网络可以不间断地运行
二、架构图
┌──────────────┐
│ Client │
│10.128.190.252│
└──────┬───────┘
│VIP:10.128.190.248
┌────────┴────────┐
┌──────┴───────┐ ┌───────┴──────┐
│ DS1 │ │ DS2 │
│10.128.190.253│ │10.128.190.254│
└──────┬───────┘ └───────┬──────┘
└────────┬────────┘
┌────────────────┼────────────────┐
┌──────┴───────┐ ┌──────┴───────┐ ┌──────┴───────┐
│ RS1 │ │ RS2 │ │ RS3 │
│10.128.190.249│ │10.128.190.250│ │10.128.190.251│
└──────────────┘ └──────────────┘ └──────────────┘
以上集群架构中,DS1、DS2 为两个 LB 节点,RS1、RS2 为两个真实的服务节点,通过一个虚拟 IP 地址对外提供服务。
最终要达到的目标为:
Client 通过 VIP 访问服务,能够将请求根据配置的规则进行分发(LB)
当 MATSER 的 LB 节点(即 DS1)故障时,自动切换到 BACKUP 的 LB 节点(即 DS2)上,保证服务正常访问
MASTER 恢复后,再次作为主 LB 负载节点
当某个 RS 节点故障时,自动剔除该节点;恢复后,再次加入集群
三、软件环境
1. DS1/2
# cat /etc/*release
CentOS Linux release 7.9.2009 (Core)
# yum install -y keepalived ipvsadm
# keepalived -v
Keepalived v1.3.5 (03/19,2017), git commit v1.3.5-6-g6fa32f2
# ipvsadm -v
ipvsadm v1.27 2008/5/15 (compiled with popt and IPVS v1.2.1)
2. RS1
# cat /etc/*release
CentOS Linux release 7.9.2009 (Core)
# yum install -y httpd
echo "RS1" > /var/www/html/index.html
3. RS2/3
同RS1,略过
四、配置 RS1/2/3
RS 配置主要是网络转发配置。
在网络转发配置上,LVS 支持多种通信模型(NAT、DR、TUN),本文采用 DR 模型来进行通信,大致的流程如下:
请求数据包从到达 LB 后,LVS 会将这个数据包的 MAC 地址改成轮询到的 RS 的 MAC 地址,并丢给交换机;
RS 收到后进行处理并从网卡的 lo 端口发送出去,响应报文到达交换机后直接转发给 Client。
因此,需在 RS 的网卡上配置 lo 为 VIP,配置脚本如下:
vim /etc/lvsRS.sh
#!/bin/bash
#VIP=192.168.222.18
VIP=10.128.190.248
#/etc/rc.d/init.d/functions
case "$1" in
start)
echo "Start Real Server ..."
ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP up
route add -host $VIP dev lo:0
echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce
sysctl -p > /dev/null 2>&1
echo "Real Server Started."
;;
stop)
echo "Stop Real Server ..."
ifconfig lo:0 down
route del $VIP >/dev/null 2>&1
echo "0" > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo "0" > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "0" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "0" > /proc/sys/net/ipv4/conf/all/arp_announce
echo "Real Server Stopped."
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
exit 0
# 添加VIP,修改内核参数(实现对内可见、对外隐藏),注意掩码必须是255.255.255.255
# 因为VIP是绑在环回网卡上(回环网卡离内核更近,数据包优先匹配)的,如果掩码不是4个255,则数据包在返回的时候匹配上了回环网卡,匹配不上真实网关,数据包发送不出去
RS、DS 有同样的vip,同一个网段中拥有两个vip,客户端在网关发送arp广播需找vip时需要让RS不接受响应。
arp_ignore 设置为1,意味着当别人的arp请求过来的时候,如果接收的设备没有这个ip,就不做出响应(这个ip在lo上,lo不是接收设备的进口)
使用最好的ip来回应,什么是最好的ip?同一个网段内子网掩码最长的
本地创建完后修改脚本属性,执行如下:
chmod a+x /etc/lvsRS.sh
/etc/lvsRS.sh start
# /etc/lvsRS.sh stop
五、配置 DS1
cp /etc/keepalived/keepalived.conf{,.org}
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id LVS1 # 设置lvs的id,在一个网络内应该是唯一的
}
vrrp_instance VI_1 {
state MASTER # 两个 DS,一个为 MASTER,一个为 BACKUP
interface ens1f1 # 当前 IP 对应的网络接口
virtual_router_id 62 # 虚拟路由 ID(0-255),在一个 VRRP 实例中主备服务器 ID 必须一样
priority 100 # 优先级值设定:MASTER 要比 BACKUP 的值大
advert_int 1 # 通告时间间隔:单位秒,主备要一致
authentication { # 认证机制,主从节点保持一致即可
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.128.190.248 # VIP,可配置多个
}
}
# LB 配置,定义对外提供服务的LVS的VIP以及port
virtual_server 10.128.190.248 80 {
delay_loop 3 # 设置健康状态检查时间
lb_algo rr # 设置负载调度的算法,wrr/rr等
lb_kind DR # 这里测试用了 Direct Route 模式
persistence_timeout 0 # 持久连接超时时间即会话保持时间,这段时间内同一ip发起的请求将被转发到同一个 RS
protocol TCP
real_server 10.128.190.249 80 {
weight 1
TCP_CHECK {
connect_timeout 10
retry 3 # 旧版本为 nb_get_retry
delay_before_retry 3
connect_port 80
}
}
real_server 10.128.190.250 80 {
weight 1
TCP_CHECK {
connect_timeout 10
retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 10.128.190.251 80 {
weight 1
TCP_CHECK {
connect_timeout 10
retry 3
delay_before_retry 3
connect_port 80
}
}
}
开启路由转发功能:
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
sysctl -p
查看转发是否生效:
sysctl -a|grep net.ipv4.ip_forward
六、配置 DS2
复制上面的配置文件,修改:
router_id LVS2
state BACKUP
priority 99
七、重启 Keepalived
配置完成后,分别重启 Keepalived 服务
systemctl restart keepalived
八、测试
以上配置完成后,通过 VIP 应该就可以访问到 RS 上的服务了。
1. 访问VIP
while true; do curl 10.128.190.248; sleep 1;done
RS3
RS2
RS1
RS3
RS2
RS1
RS3
RS2
RS1
RS3
RS2
2. 实时查看负载均衡的状态
watch ipvsadm -Ln --stats
Every 2.0s: ipvsadm -Ln --stats Mon Mar 13 16:23:05 2023
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes
-> RemoteAddress:Port
TCP 10.128.190.248:80 43 258 0 17114 0
-> 10.128.190.249:80 14 84 0 5572 0
-> 10.128.190.250:80 14 84 0 5572 0
-> 10.128.190.251:80 15 90 0 5970 0
九、扩展
在已有架构上扩展一个MySQL集群3306端口服务的负载均衡功能,则在已有keepalived配置文件增加一个虚拟服务器,类似如下:
virtual_server 7.7.7.18 3306 {
delay_loop 3
lb_algo rr
lb_kind DR
persistence_timeout 0
protocol TCP
real_server 7.7.7.11 3306 {
weight 1
TCP_CHECK {
connect_timeout 10
retry 3
delay_before_retry 3
connect_port 3306
}
}
real_server 7.7.7.12 3306 {
weight 1
TCP_CHECK {
connect_timeout 10
retry 3
delay_before_retry 3
connect_port 3306
}
}
real_server 7.7.7.13 3306 {
weight 1
TCP_CHECK {
connect_timeout 10
retry 3
delay_before_retry 3
connect_port 3306
}
}
}
重启keepalived服务,在客户端连接测试,可见负载均衡的分布到了后端的数据服务节点,如下所示:
[root@node4 ~]# watch ipvsadm -Ln --stats
Every 2.0s: ipvsadm -Ln --stats Tue Mar 14 09:01:38 2023
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes
-> RemoteAddress:Port
TCP 7.7.7.18:80 22 132 0 8624 0
-> 7.7.7.11:80 8 48 0 3136 0
-> 7.7.7.12:80 7 42 0 2744 0
-> 7.7.7.13:80 8 48 0 3136 0
TCP 7.7.7.18:3306 205 2873 0 344018 0
-> 7.7.7.11:3306 68 952 0 114036 0
-> 7.7.7.12:3306 68 952 0 114036 0
-> 7.7.7.13:3306 69 969 0 115946 0
如上可见,205个前端数据连接请求3306端口,均匀的分布到了后端的3个服务节点上。
十、总结
此时,DS1、DS2以主备模式提供高可用的前端访问VIP,不管哪一个DS节点出现问题,都不影响通过VIP访问后端的RS服务,此即高可用。
且由于配置了rr模式的轮询机制,前端的访问可以均衡的分布到后端的RS多节点服务上,此即负载均衡。
【致谢】
首先向LVS的原创作者章文嵩博士致敬,LVS早就已经成为linux的核心模块之一,这是国人的骄傲!
另外看似简单的一个技术测试,断断续续耗时好几天时间,在此感谢浮生邀月lizhb同学的热心指点!
【网文参考】
https://www.cnblogs.com/caoweixiong/p/14690527.html