LVS+nginx搭建高可用架构
# LVS与nginx
vs是基于linux内核的ipvs模块工作的,是四层协议的负载均衡,主要支持LVS-nat、LVS-tun、LVS-dr的方式进行负载。
LVS相对nginx而言开销更低,性能更好
nginx的网络拓扑,请求出入都需要经过nginx会带来性能上的损耗
LVS的网络拓扑:请求经过LVS,响应可以不经
# LVS的模式
# NAT
特点:
- 请求、响应都经过LVS
- LVS提供一个对外的公网ip,后端的服务外网不能访问
- 支持端口转发
# TUN
特点:
LVS需要基于ip隧道模式与后端服务建立隧道,每个节点配有网卡,后端的服务暴露在公网
- 响应不经过LVS
- LVS提供虚拟ip,公网可以访问

# DR
特点:
- 请求经过LVS,响应经过router
- LVS和router对外公网可访问

# 搭建LVS-DR模式
# 服务器IP约定
LVS与后端的server的请求示例

通过DIP分发请求到RIP上,最终通过VIP返回响应,注意DIP与RIP需要在同一网段内
角色 | 备注 |
---|---|
DIP | 调度者的ip,负责调度后端的real server |
VIP | 虚拟ip,用户通过虚拟ip发起请求,这里约定虚拟ip为192.168.1.15 |
RIP | 后端服务各个节点的ip |
调度器和所有的Real Server都配置了VIP地址,区别在于LVS的VIP配置在物理网卡接口上,而Real Server都是配置在了本地接口lo上
# 准备工作
准备工作
# 停止网络管理
systemctl stop NetworkManager
# 禁用网络管理
systemctl disable NetworkManager
# 安装LVS集群管理工具
yum install ipvsadm
# 确认是否安装成功
ipvsadm -Ln
2
3
4
5
6
7
8
9
10
11
主要是为了避免网关接口的冲突,需要关闭三台服务器上的网络管理服务
注:阿里云不支持虚拟ip
,腾讯云支持,但是有数量限制,网卡都需要进行付费
# 配置调度者LVS虚拟IP
复制现有的网卡配置进行修改
# 备份网卡配置
cd /etc/sysconfig/network-scripts/
# 重命名为ens33:1
cp ifcfg-ens33 ifcfg-ens33:1
vim ifcfg-ens33:1
2
3
4
5
6
7
修改网卡配置
# 网卡名称,跟文件名一致
DEVICE="ens33:1"
ONBOOT=yes
BOOTPROTO=static
# 指定内网的ip,即vip
IPADDR=192.168.1.150
NETMASK=255.255.255.0
2
3
4
5
6
7
8
9
10
重启网络
# 重启网络
service network restart
2
# 配置RS的虚拟IP
后端两台服务器主要调整ifcfg-lo文件,目的是为了返回用户数据报文
cd /etc/sysconfig/network-scripts/
# 本地环回接口,用于构建网络子接口,返回数据报文,不能被用户访问到真实服务
cp ifcfg-lo ifcfg-lo:1
2
3
4
lo配置修改
DEVICE=lo:1
IPADDR=192.168.1.150
#子网掩码调整为255,这个跟LVS节点不一致
NETMASK=255.255.255.255
NETWORK=127.0.0.0
BROADCAST=127.255.255.255
ONBOOT=yes
NAME=loopback
2
3
4
5
6
7
8
9
刷新网卡配置
# 刷新lo配置
ifup lo # 或者使用service network restart都可以
# 查看lo下是否新增192.168.1.150的虚拟ip
ip addr
2
3
4
5
# 配置RS的ARP
arp
用于更加精准的处理用户请求,是配置网卡的行为,配置arp主要是为了后端server只被调度器调度
,因此需要限制real server的响应级别。
# arp_ignore
arp响应级别,处理请求
值 | 备注 |
---|---|
0 | 默认值为0,只要本机配置了ip,就能响应请求 |
1 | 请求的目标地址到达对应的网络接口,才会响应请求 |
2 | 请求的目标地址到达对应的网络接口,且来访IP必须在该网络接口的子网段内 |
3 | 不回应该网络界面的arp请求,而只对设置的唯一和连接地址做出回应 |
4-7 | 保留未使用 |
8 | 不回应所有(本地地址)的arp查询 |
为了保证客户端的ARP广播请求可以只被调度器所响应,因此必须限制所有Real Server的arp响应级别,所以才设置arp_ignore为1,这样对于Real Server来说,因为arp请求一定来自别的主机,所以接收的网卡只能是物理接口,而Real Server又将VIP配置到了lo接口上,因此刚好不会回应,从而保证了请求只会到达调度器;
# arp_announce
通告行为,主要是处理返回响应
值 | 备注 |
---|---|
0 | 所有的网络接口都可以向外通告和接收到通道 |
1 | 尽可能的避免本网卡与不匹配的目标通告 |
2 | 只在本网卡内通告 |
# ARP配置
打开sysctl.conf
vim /etc/sysctl.conf
配置所有网卡、默认网卡以及虚拟网卡的arp响应级别和通告行为,分别对应:all,default,lo:
# 所有的网卡
net.ipv4.conf.all.arp_ignore=1
# 默认的网卡
net.ipv4.conf.default.arp_ignore=1
# lo的网卡
net.ipv4.conf.lo.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.default.arp_announce=2
net.ipv4.conf.lo.arp_announce=2
2
3
4
5
6
7
8
9
10
刷新网卡配置
# 刷新网卡配置
sysctl -p
2
增加一个网关,用于接收数据报文,当有请求到本机后,会交给lo去处理
# 在两台server上分别添加route
route add-host:192.168.1.150 dev lo:1
# 确认路由是否添加?
route -n
# 将路由添加到开启自启,避免重启失效
echo "route add-host:192.168.1.150 dev lo:1" >> /etc/rc.local
2
3
4
5
6
# 使用ipvsadm配置集群规则
创建LVS节点,即用户访问的集群调度者
# 添加一个集群
ipvsadm -A -t 192.168.1.150:80 -s rr -p 5
# -A 添加集群
# -t tcp协议
# ip地址:设置集群的访问ip,即虚拟ip
# -s 设置负载均衡算法,rr表示轮询
# -p 设置持久化连接的时间
2
3
4
5
6
7
添加两台服务器到集群节点
# 添加集群节点
ipvsadm -a -t 192.168.1.150:80 -r 192.168.1.171:80 -g
ipvsadm -a -t 192.168.1.150:80 -r 192.168.1.172:80 -g
# -a 添加真实服务器
# -t tcp协议
# -r 真实服务器ip
# -g 设置为DR模式
2
3
4
5
6
7
保存到规则库,否则重启失效
ipvsadm -S
检查集群
# 查看集群列表
ipvsadm -Ln
# 查看集群状态
ipvsadms -Ln --stats
# 查看请求的节点
ipvsadm -Lnc
2
3
4
5
6
其他命令
# 重启ipvsadm,重启后需要重新配置
service ipvsadm restart
# 查看持久化连接
ipvsadm -Ln --persistent-conn
# 查看连接请求过期时间以及请求源ip和目标
ipipvsadm -Lnc
# 设置tcp tcpfin udp的过期时间(一般保持默认)
ipvsadm --set 1 1 1
# 查看过期时间
ipvsadm -Ln --timeout
2
3
4
5
6
7
8
9
10
注:如果没有发生轮询,请检查节点的持久化的时间
# 搭建keepalived+LVS+Nginx
通过配置keepalived
来保证LVS节点的高可用
# master
! Configuration File for keepalived
global_defs {
router_id LVS_151
}
vrrp_instance VI_1 {
state MASTER # 两个 DS,一个为 MASTER 一个为 BACKUP
interface ens33 # 当前 IP 对应的网络接口,通过 ifconfig 查询
virtual_router_id 41 # 虚拟路由 ID(0-255),在一个 VRRP 实例中主备服务器 ID 必须一样
priority 100 # 优先级值设定:MASTER 要比 BACKUP 的值大
advert_int 1 # 通告时间间隔:单位秒,主备要一致
authentication { # 认证机制,主从节点保持一致即可
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.150 # VIP,可配置多个
}
}
# LVS 配置
virtual_server 192.168.1.150 80 {
delay_loop 3 # 设置健康状态检查时间,单位为秒
lb_algo rr # 调度算法,这里用了 rr 轮询算法
lb_kind DR # 指定LVS的模式Direct Route 模式
persistence_timeout 50 # 持久连接超时时间,保持客户端前后请求的间隔,时间段内会落到同一台server上
protocol TCP # 协议为tcp
real_server 192.168.1.171 80 {
weight 1 # 轮询的权重
# 健康检查
TCP_CHECK {
connect_timeout 10 # 连接超时时间,单位为秒
retry 3 # 重试次数,旧版本为 nb_get_retry
delay_before_retry 3 # 间隔时间
connect_port 80 # 检查的端口
}
}
real_server 192.168.1.171 80 {
weight 1 # 轮询的权重
# 健康检查
TCP_CHECK {
connect_timeout 10 # 连接超时时间,单位为秒
retry 3 # 重试次数,旧版本为 nb_get_retry
delay_before_retry 3 # 间隔时间
connect_port 80 # 检查的端口
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# backup
! Configuration File for keepalived
global_defs {
router_id LVS_152
}
vrrp_instance VI_1 {
state BACKUP # 从节点指定为BACKUP
interface ens33
virtual_router_id 41 # 跟master节点保持一致
priority 80 # 优先级比master节点低
advert_int 1 # 通告时间间隔:单位秒,主备要一致
authentication { # 认证机制,主从节点保持一致即可
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.150 # VIP,可配置多个
}
}
# LVS 配置,跟master的保持一致
virtual_server 192.168.1.150 80 {
delay_loop 3 # 设置健康状态检查时间,单位为秒
lb_algo rr # 调度算法,这里用了 rr 轮询算法
lb_kind DR # 指定LVS的模式Direct Route 模式
persistence_timeout 50 # 持久连接超时时间,保持客户端前后请求的间隔,时间段内会落到同一台server上
protocol TCP # 协议为tcp
real_server 192.168.1.171 80 {
weight 1 # 轮询的权重
# 健康检查
TCP_CHECK {
connect_timeout 10 # 连接超时时间,单位为秒
retry 3 # 重试次数,旧版本为 nb_get_retry
delay_before_retry 3 # 间隔时间
connect_port 80 # 检查的端口
}
}
real_server 192.168.1.171 80 {
weight 1 # 轮询的权重
# 健康检查
TCP_CHECK {
connect_timeout 10 # 连接超时时间,单位为秒
retry 3 # 重试次数,旧版本为 nb_get_retry
delay_before_retry 3 # 间隔时间
connect_port 80 # 检查的端口
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
配置完成后,需要对两台server进行清空路由
ipvsadm -C
分别启动keepalived服务,此时会加载keepalived配置,实际上跟ipvsadm本质上一致,都是创建了route
syetemctl restart keepalived
# LVS算法
# 静态算法
LVS本身固定的算法分发用户请求
算法 | 简称 | 描述 |
---|---|---|
轮询 | Round Robin (rr) | 平均的分发请求到后端的各个server |
加权轮询 | Weight Round Robin(wrr) | 按照权重比例来分发请求到后端server |
源地址散列 | Source Hash(sh) | 根据用户的ip地址分发,同一个ip最终会落到同一个server |
目标地址散列 | Destination Hash (dh) | 根据用户的url地址分发,同一个ip最终会落到同一个server |
# 动态算法
根据流量、服务器压力的大小,动态的计算
算法 | 简称 | 描述 |
---|---|---|
最小连接数 | Leat Connections lc | 分发新的连接数到连接数最小的server |
加权最小连接数 | Weight Leat Connections wlc | 优先分发到权重较大、连接数最小的server |
最短期望延迟 | Shortest Expected Delay sed | 特殊的wlc的算法,优先分配给延迟比较低的server |
最小队列调度 | Never Queue nq | 永不使用队列,优先分发到不需要排队等待运算的server |