# 企业级负载均衡 LVS
# 1. LVS 基本概述
# 1.1 什么是 LVS
LVS 是 Linux Virtual Server 的简称,即 Linux 虚拟服务器。其实它是一种 Cluster 集群技术,主要用于负载均衡,将用户请求均匀的调度到不同部服务器上执行。LVS 是基于四层目标 IP、PORT 的负载均衡。
# 1.2 为何需要 LVS
- 1. 解决七层端口不够问题,实现百万链接;
- 2. 解决七层负载均衡高可用问题;
# 1.3 LVS 组成部分
ipvsadm:用户空间的客户端工具,负责 ipvs 内核框架编写规则。定义谁是集群服务,谁是后端服务,数据包如何调度,调度到那个节点;
ipvs:工作在内核空间,实现集群服务的 “调度”,借鉴了 iptables 的实现方式;
# 1.4 LVS 组成部分

- DS:Director Server,lvs 服务器名称
- RS:Real Server ,后端请求处理服务器,真实服务器
- CIP: Client IP ,客户端 IP
- VIP:Director Virtual IP ,负载均衡器虚拟 IP
- DIP:Director IP ,ds 服务器真实的 IP 地址
- RIP:Real Server IP ,后端请求处理的服务器 IP
# 1.5 LVS 常见模型
LVS 负载均衡模型有 NAT、DR、TUN、FULL-NAT,较为常见的模型有 NAT、DR,使用最为广泛的模型是 DR。
# 1.5.1 NAT 模型
NAT:通过修改请求报文的目标 IP 地址,然后根据算法挑选出某台 RS 进行转发。(请求进入负载均衡器 LVS 时做 DNAT,后端返回数据报文出负载均衡时做 SNAT)
# 1.5.2 DR 模型
DR:通过修改请求报文的目标 MAC 地址,然后根据算法挑选出某台 RS 进行转发。(请求进入负载均衡器 LVS 时做 MAC 地址转换,后端返回数据报文不经过负载均衡,所以无需做转换)
# 1.6 管理工具 ipvsadm 使用
[root@web01 ~]# yum install ipvsadm -y |
# 1.6.1 集群管理参数
# COMMANDS-CLUSTER | |
-A, --add-service: #添加一个集群服务。 | |
-E, --edit-service: #修改已添加的集群服务。 | |
-D, --delete-service: #删除一个虚拟服务。 | |
-C, --clear: #清除所有虚拟服务。 | |
-R, --restore: #从文件中恢复集群。 | |
-S, --save: #将集群信息保存至文件中。 | |
-L, -l, --list: #列出当前集群信息。 | |
-Z, --zero: #将所有数据相关的记录清零。 | |
-n #数字格式显示 ip 和 port,注意 - n 只能写在 - L 之后。 |
# 1.6.2 节点管理参数
# COMMANDS-RS | |
-a, --add-server: #表示添加一个 RS 节点 | |
-e, --edit-server: #表示修改一个 RS 节点 | |
-d, --delete-server: #表示删除一个 RS 节点 | |
-t, service-address: #指定操作那个节点地址与端口,host:[port],tcp 协议。 | |
-u, service-address: #指定操作那个节点地址与端口,host:[port],ucp 协议。 | |
-r, --real-server: #指定 RS 节点地址与端口。 | |
-w, --weight: #指定 RS 节点的权重。 | |
-m, --masquerading: #指定 LVS 工作模型(NAT 模型)。 | |
-g, --gatewaying: #指定 LVS 工作模型(DR 模型)。 | |
-i, --ipip: #指定 LVS 工作模型(TUN 模型)。 | |
-s, --scheduler: #指定 LVS 调度策略,默认为 wlc。 | |
-p, --persistent: #持久连接超时时间。 | |
-f, --fwmark-service: #防火墙标记 | |
-c, --connection: #列出当前的 IPVS 连接。 |
# 1.6.3 集群管理示例
#1. 添加虚拟服务,定义集群 | |
[root@web01 ~]# ipvsadm -A -t 192.168.1.7:3306 | |
[root@web01 ~]# ipvsadm -L -n | |
IP Virtual Server version 1.2.1 (size=4096) | |
Prot LocalAddress:Port Scheduler Flags | |
-> RemoteAddress:Port Forward Weight ActiveConn InActConn | |
TCP 192.168.1.7:3306 wlc | |
#2. 添加真实服务 IP | |
[root@web01 ~]# ipvsadm -a -t 192.168.1.7:3306 -r 192.168.1.51:3306 | |
[root@web01 ~]# ipvsadm -a -t 192.168.1.7:3306 -r 192.168.1.41:3306 | |
[root@web01 ~]# ipvsadm -L -n | |
IP Virtual Server version 1.2.1 (size=4096) | |
Prot LocalAddress:Port Scheduler Flags | |
-> RemoteAddress:Port Forward Weight ActiveConn InActConn | |
TCP 192.168.1.7:3306 wlc | |
-> 192.168.1.41:3306 Route 1 0 0 | |
-> 192.168.1.51:3306 Route 1 0 0 |
# 2. LVS NAT 模型详解
通过修改请求报文的目标 IP 地址,然后根据算法挑选出某台 RS 进行转发。(请求进入负载均衡器 LVS 时做 DNAT,后端返回数据报文出负载均衡时做 SNAT)
# 2.1 NAT 基础图解

# 2.2 NAT 底层实现
客户端:10.0.0.10(外网)
DS 节点:172.16.1.100(VIP)、172.16.1.3(DIP)
RD 节点:172.16.1.5、172.16.1.6、Gateway:172.16.1.3

# 2.3 NAT 访问原理
- 1. 当用户请求到达 Director Server,此时请求的数据报文会先到内核空间的 PREOUTING 链。此时报文的源 IP 为 CIP,目标 IP 为 VIP;
- 2.PREOUTING 检查发现数据包的目标 IP 是本机,将数据包送至 INPUT 链;
- 3.IPVS 比对数据包请求的服务是否为集群服务,若是,通过调度算法挑选一台后端 RS 服务器,并修改数据包的目标 IP 为 RS 的 IP,然后将数据包发至 POSTROUTING 链。此时报文的源 IP 为 CIP,目标 IP 为 RIP;
- 4.POSTROUTING 链通过选路,将数据包通过 Director Server 的 DIP 发送给 RS;
- 5.RS 发现目标为自己的 IP,则交给应用程序处理,然后构建相应报文发回给 Director Server。此时报文的源 IP 为 RIP,目标 IP 为 CIP;
- 6.Director Server 在响应客户端前,会将源 IP 地址修改为 VIP 地址,然后响应给客户端。此时报文的源 IP 为 VIP,目标 IP 为 CIP;
# 2.4 NAT 特性总结
- 1.RS 必须使用私网地址,并需要将网关指向 DS;
- 2.RIP 和 DIP 必须为同一网段内;
- 3.NAT 模型支持端口映射;
- 4.RS 可以使用任意操作系统,例如 Linux、Windows 等;
- 5. 请求和响应报文都要经过 RS,高负载场景中,DS 易成为瓶颈;
# 2.5 NAT 模型场景实战
# 2.5.1 NAT 架构规划

| 角色 | 主机名称 | 外网地址 | 内网地址 |
|---|---|---|---|
| 客服端 | client | eth0:192.168.40.41 | / |
| 路由器 | route | eth0:192.168.40.200 | eth1:172.16.1.200 |
| LVS | lb01 | / | eth1:172.16.1.3/VIP:172.16.1.100 |
| 应用服务器 | web01 | / | eth1:172.16.1.7 |
| 应用服务器 | web02 | / | eth1:172.16.1.8 |
# 2.5.2 客户端配置
#1. 配置 eth1 | |
[root@client ~]# ifdown eth1 | |
#2. 配置 eth0 | |
[root@client ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth0" | |
UUID="09f9df8f-9a2c-48ec-a530-cedcbc801991" | |
DEVICE="eth0" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="192.168.40.10" | |
PREFIX="24" | |
#GATEWAY="192.168.40.2" | |
#DNS1="223.5.5.5" | |
[root@client ~]# ifdown eth0 && ifup eth0 |
# 2.5.3 路由器配置
#1. 配置 eth0 (eth0: 192.168.40.200 gateway: 192.168.40.2) | |
[root@route ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth0" | |
UUID="09f9df8f-9a2c-48ec-a530-cedcbc801991" | |
DEVICE="eth0" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="192.168.40.200" | |
PREFIX="24" | |
GATEWAY="192.168.40.2" | |
DNS1="223.5.5.5" | |
#2. 配置 eth1 (eth1: 172.16.1.200) | |
[root@route ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth1" | |
DEVICE="eth1" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="172.16.1.200" | |
PREFIX="24" | |
#3. 开启 forward 转发 | |
[root@route ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf | |
[root@route ~]# sysctl -p |
# 2.5.4 web01 配置 (RS 节点)
#1. 配置 eth0 | |
[root@web01 ~]# ifdown eth0 | |
#2. 配置 eth1 网关指向 LVS 的 VIP | |
[root@web01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth1" | |
DEVICE="eth1" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="172.16.1.7" | |
PREFIX="24" | |
GATEWAY=172.16.1.100 | |
[root@web01 ~]# ifdown eth1 && ifup eth1 | |
#3. 配置 Nginx | |
[root@web01 ~]# cat /etc/nginx/conf.d/lvs.hmallleasing.com.conf | |
server { | |
listen 80; | |
server_name lvs.hmallleasing.com; | |
root /code; | |
location / { | |
index index.html; | |
} | |
} | |
[root@web01 ~]# echo "web01 Real Server" > /code/index.html | |
[root@web01 ~]# nginx -t | |
[root@web01 ~]# systemctl reload nginx | |
[root@web01 ~]# curl -HHost:lvs.hmallleasing.com http://172.16.1.7 |
# 2.5.5 web02 配置 (RS 节点)
#1. 配置 eth0 | |
[root@web02 ~]# ifdown eth0 | |
#2. 配置 eth1 网关指向 LVS 的 VIP | |
[root@web02 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth1" | |
DEVICE="eth1" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="172.16.1.8" | |
PREFIX="24" | |
GATEWAY=172.16.1.100 | |
[root@web02 ~]# ifdown eth1 && ifup eth1 | |
#3. 配置 Nginx | |
[root@web02 ~]# cat /etc/nginx/conf.d/lvs.hmallleasing.com.conf | |
server { | |
listen 80; | |
server_name lvs.hmallleasing.com; | |
root /code; | |
location / { | |
index index.html; | |
} | |
} | |
[root@web02 ~]# echo "web02 Real Server" > /code/index.html | |
[root@web02 ~]# nginx -t | |
[root@web02 ~]# systemctl reload nginx | |
[root@web02 ~]# curl -HHost:lvs.hmallleasing.com http://172.16.1.8 |
# 2.5.6 LVS 配置
#1. 关闭 eth0 | |
[root@lvs01 ~]# ifdown eth0 | |
#2. 配置 eth1 (eth1: 172.16.1.3 gateway:172.16.1.200) | |
[root@lvs01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth1" | |
DEVICE="eth1" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="172.16.1.3" | |
PREFIX="24" | |
GATEWAY=172.16.1.200 | |
[root@lvs01 ~]# ifdown eth1 && ifup eth1 | |
#3. 配置 vip (vip : 172.16.1.100) | |
[root@lvs01 ~]# cp /etc/sysconfig/network-scripts/ifcfg-eth1 /etc/sysconfig/network-scripts/ifcfg-eth1:1 | |
[root@lvs01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1:1 | |
TYPE=Ethernet | |
BOOTPROTO=none | |
DEFROUTE=yes | |
NAME=eth1:1 | |
DEVICE=eth1:1 | |
ONBOOT=yes | |
IPADDR=172.16.1.100 | |
PREFIX=24 | |
[root@lvs01 ~]# ifdown eth1:1 && ifup eth1:1 | |
#4. 开启 forward 转发功能 | |
[root@lvs01 ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf | |
[root@lvs01 ~]# sysctl -p | |
#5. 配置 ipvs 规则,将请求的 80 端口,调度到后端 rs 节点; | |
[root@lvs01 ~]# ipvsadm -A -t 172.16.1.100:80 -s rr | |
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.100:80 -r 172.16.1.7 -m | |
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.100:80 -r 172.16.1.8 -m | |
[root@lvs01 ~]# ipvsadm -L -n | |
IP Virtual Server version 1.2.1 (size=4096) | |
Prot LocalAddress:Port Scheduler Flags | |
-> RemoteAddress:Port Forward Weight ActiveConn InActConn | |
TCP 172.16.1.100:80 rr | |
-> 172.16.1.7:80 Masq 1 0 0 | |
-> 172.16.1.8:80 Masq 1 0 0 |
# 2.5.7 路由器配置端口映射
#1. 在路由器上增加端口映射,模拟实现真实的公网环境 | |
[root@route ~]# iptables -t nat -A PREROUTING -d 192.168.40.200 -p tcp --dport 80 -j DNAT --to 172.16.1.100:80 | |
[root@route ~]# iptables -t nat -A PREROUTING -d 192.168.40.200 -p tcp --dport 443 -j DNAT --to 172.16.1.100:443 | |
[root@route ~]# iptables -t nat -L -n | |
Chain PREROUTING (policy ACCEPT) | |
target prot opt source destination | |
DNAT tcp -- 0.0.0.0/0 192.168.40.200 tcp dpt:80 to:172.16.1.100:80 | |
DNAT tcp -- 0.0.0.0/0 192.168.40.200 tcp dpt:443 to:172.16.1.100:443 |
# 2.5.8 测试验证
#1. 验证测试 | |
[root@client ~]# curl -HHost:lvs.hmallleasing.com http://192.168.40.200 | |
web01 Real Server | |
[root@client ~]# curl -HHost:lvs.hmallleasing.com http://192.168.40.200 | |
web02 Real Server | |
#2. 查看客户端是否与 web 服务器建立握手 | |
[root@web01 ~]# dd if=/dev/zero of=/code/bigdata bs=3000M count=1 | |
[root@web01 ~]# netstat -ntp | |
Active Internet connections (w/o servers) | |
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name | |
tcp 0 4077780 172.16.1.7:80 192.168.40.1:59525 ESTABLISHED 1871/nginx: worker | |
tcp 0 0 172.16.1.7:22 172.16.1.41:58656 ESTABLISHED 1731/sshd: root@pts | |
#3. 对于客服端与路由器建立握手 | |
C:\Users\Administrator>netstat -an | |
TCP 192.168.40.1:59525 192.168.40.200:80 ESTABLISHED | |
#4. 查看 LVS 连接记录 | |
[root@lvs01 ~]# ipvsadm -L -c -n | |
IPVS connection entries | |
pro expire state source virtual destination | |
TCP 00:02 CLOSE 192.168.40.1:59067 172.16.1.100:80 172.16.1.7:80 |
# 3.LVS DR 模型详解
通过修改请求报文的目标 MAC 地址,然后根据算法挑选出合适的 RS 节点进行转发。(请求进入 DS Server 时做 MAC 地址替换,后端返回数据报文不经过 DS Server 节点,直接返回给客户端即可。)
# 3.1 NAT 基础图解

# 3.2 DR 底层实现

1. 路由器如何规划 VIP 以及 MAC 地址呢?
路由器通过 ARP 广播获取 VMAC,然后封装 CIP、VIP、CMAC、VMAC,通过交换机转发至目标主机。
2.RS 处理请求直接返回给 CIP,不经过 DS,那么 RS 如何将数据包回传给 CIP?
由于 CIP 请求的是 VIP,而响应是通过 RIP 响应给 CIP,所以数据报文一定会被丢弃。那么就需要在所有的 RS 的接口上配置 VIP 的地址,由 RS 上的 VIP 响应给 CIP 即可。
3. 所有 RS 节点都配置 VIP,那么路由器在广播的时候,岂不是所有的 VIP 都会响应?
方式 1:在路由器上静态绑定 VIP 与 VMAC 的关系。
方式 2:在所有 RS 节点上配置 ARP 抑制,简单来说就是路由器广播获取 VMAC 时,所有的 RS 都不应答,其次所有的 RS 都不对外宣布自己的 VIP。
4.VIP、DIP、RIP 需要在同一网段中吗?
一般来说 DIP 和 RIP 在同一物理网络中,并不一定在同一网段中。
# 3.3 DR 访问流程
- 1. 当用户请求到达 DS 节点,此时请求的数据报文会先到内核空间的 PREOUTING 链。此时报文的源 IP 为 CIP,目标 IP 为 VIP;
- 2.PREOUTING 检查发现数据包的目标 IP 是本机,将数据包送至 INPUT 链条;
- 3.IPVS 比对数据包请求的服务是否为集群服务,是则将请求报文中的源 MAC 修改为 DMAC,将目标 MAC 修改为 RMAC,然后将数据包通过 POSTROUTING 链发出,此时的源 IP 和目的 IP 均未修改,仅将源 MAC 修改为 DMAC,目标 MAC 修改为 RMAC;
- 4.RS 拆解数据报文发现请求的 IP 地址是本机,则会接收该数据报文,而后构建响应报文发出,此时的源 IP 是 VIP,目标 IP 是 CIP;
- 5. 响应报文最终送达至客户端;
# 3.4 NAT 特性总结
- 1. 请求报文必须有 DS 节点转发,但响应报文必须不经过 DS 节点;
- 2.RS 不能将网关指向 DS 节点的 DIP;
- 3.DS 和 RS 节点必须位于同一物理网络中;
- 4.DR 模型不支持地址转换,也不支持端口映射;
- 5.RS 可以是常见的操作系统 Windows、Linux、MacOSl;
- 6.RS 在 lo 接口上配置 VIP;
# 3.5 DR ARP 参数
arp_ignore(控制系统在收到外部的 arp 请求时,是否应答。)
- 0 默认值,将本机所有接口的所有信息向每一连接的网络进行通告。
- 1 只应答本地主机访问网络接口(eth0->lo), 才给予响应。
arp_announce(控制系统是否对外宣布自己的地址)
- 0 默认值,把本机所有接口的所有信息向每个接口的网络进行通信
- 1 “尽量避免” 将接口信息向非直接连接网络进行通信
- 2 “必须避免” 将接口信息向非本网络进行通信
# 3.6 DR 模型场景实战
# 3.6.1 DR 架构规划

| 角色 | 主机名称 | 外网地址 | 内网地址 |
|---|---|---|---|
| 客服端 | client | eth0:192.168.40.10 | / |
| 路由器 | route | eth0:192.168.40.200 | eth1:172.16.1.200 |
| LVS | lb01 | / | eth1:172.16.1.3/VIP:172.16.1.100 |
| 应用服务器 | web01 | / | eth1:172.16.1.7 |
| 应用服务器 | web02 | / | eth1:172.16.1.8 |
# 3.6.2 客户端配置
#1. 配置 eth1 | |
[root@client ~]# ifdown eth1 | |
#2. 配置 eth0 | |
[root@client ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth0" | |
UUID="09f9df8f-9a2c-48ec-a530-cedcbc801991" | |
DEVICE="eth0" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="192.168.40.10" | |
PREFIX="24" | |
#GATEWAY="192.168.40.2" | |
#DNS1="223.5.5.5" | |
[root@client ~]# ifdown eth0 && ifup eth0 |
# 3.6.3 路由器配置
#1. 配置 eth0 (eth0: 192.168.40.200 gateway: 192.168.40.2) | |
[root@route ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth0" | |
UUID="09f9df8f-9a2c-48ec-a530-cedcbc801991" | |
DEVICE="eth0" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="192.168.40.200" | |
PREFIX="24" | |
GATEWAY="192.168.40.2" | |
DNS1="223.5.5.5" | |
#2. 配置 eth1 (eth1: 172.16.1.200) | |
[root@route ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth1" | |
DEVICE="eth1" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="172.16.1.200" | |
PREFIX="24" | |
#3. 开启 forward 转发 | |
[root@route ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf | |
[root@route ~]# sysctl -p | |
#4. 清除 iptables 规则 | |
[root@route ~]# iptables -t nat -F | |
[root@route ~]# iptables -t nat -L -n |
# 3.6.4 web01 配置 (RS 节点)
#1. 配置 eth0 | |
[root@web01 ~]# ifdown eth0 | |
#2. 配置 eth1 网关指向路由器 | |
[root@web01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth1" | |
DEVICE="eth1" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="172.16.1.7" | |
PREFIX="24" | |
GATEWAY=172.16.1.200 | |
[root@web01 ~]# ifdown eth1 && ifup eth1 | |
#3. 配置 Nginx | |
[root@web01 ~]# cat /etc/nginx/conf.d/lvs.hmallleasing.com.conf | |
server { | |
listen 80; | |
server_name lvs.hmallleasing.com; | |
root /code; | |
location / { | |
index index.html; | |
} | |
} | |
[root@web01 ~]# echo "web01 Real Server" > /code/index.html | |
[root@web01 ~]# nginx -t | |
[root@web01 ~]# systemctl reload nginx | |
[root@web01 ~]# curl -HHost:lvs.hmallleasing.com http://172.16.1.7 | |
#4. 配置 VIP 地址; | |
[root@web01 ~]# cp /etc/sysconfig/network-scripts/ifcfg-lo /etc/sysconfig/network-scripts/ifcfg-lo:0 | |
[root@web01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-lo:0 | |
DEVICE=lo:0 | |
IPADDR=172.16.1.100 | |
NETMASK=255.0.0.0 | |
ONBOOT=yes | |
NAME=loopback | |
[root@proxy01 ~]# ifdown lo:0 && ifup lo:0 | |
#5. 配置 arp 抑制 | |
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore | |
echo "1" >/proc/sys/net/ipv4/conf/default/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/default/arp_announce | |
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce |
# 3.6.5 web02 配置 (RS 节点)
#1. 配置 eth0 | |
[root@web02 ~]# ifdown eth0 | |
#2. 配置 eth1 网关指向路由器 | |
[root@web02 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth1" | |
DEVICE="eth1" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="172.16.1.8" | |
PREFIX="24" | |
GATEWAY=172.16.1.200 | |
[root@web02 ~]# ifdown eth1 && ifup eth1 | |
#3. 配置 Nginx | |
[root@web02 ~]# cat /etc/nginx/conf.d/lvs.hmallleasing.com.conf | |
server { | |
listen 80; | |
server_name lvs.hmallleasing.com; | |
root /code; | |
location / { | |
index index.html; | |
} | |
} | |
[root@web02 ~]# echo "web02 Real Server" > /code/index.html | |
[root@web02 ~]# nginx -t | |
[root@web02 ~]# systemctl reload nginx | |
[root@web02 ~]# curl -HHost:lvs.hmallleasing.com http://172.16.1.8 | |
#4. 配置 VIP 地址; | |
[root@web01 ~]# cp /etc/sysconfig/network-scripts/ifcfg-lo /etc/sysconfig/network-scripts/ifcfg-lo:0 | |
[root@web02 ~]# cat /etc/sysconfig/network-scripts/ifcfg-lo:0 | |
DEVICE=lo:0 | |
IPADDR=172.16.1.100 | |
NETMASK=255.0.0.0 | |
ONBOOT=yes | |
NAME=loopback | |
[root@web02 ~]# ifdown lo:0 && ifup lo:0 | |
#5. 配置 arp 抑制 | |
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore | |
echo "1" >/proc/sys/net/ipv4/conf/default/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/default/arp_announce | |
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce |
# 3.6.6 LVS 配置
#1. 关闭 eth0 | |
[root@lvs01 ~]# ifdown eth0 | |
#2. 配置 eth1 (eth1: 172.16.1.3 gateway:172.16.1.200) | |
[root@lvs01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth1" | |
DEVICE="eth1" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="172.16.1.3" | |
PREFIX="24" | |
GATEWAY=172.16.1.200 | |
[root@lvs01 ~]# ifdown eth1 && ifup eth1 | |
#3. 配置 vip (vip : 172.16.1.100) | |
[root@lvs01 ~]# cp /etc/sysconfig/network-scripts/ifcfg-eth1 /etc/sysconfig/network-scripts/ifcfg-eth1:1 | |
[root@lvs01 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1:1 | |
TYPE=Ethernet | |
BOOTPROTO=none | |
DEFROUTE=yes | |
NAME=eth1:1 | |
DEVICE=eth1:1 | |
ONBOOT=yes | |
IPADDR=172.16.1.100 | |
PREFIX=24 | |
IPV6_PRIVACY="no" | |
[root@lvs01 ~]# ifdown eth1:1 && ifup eth1:1 | |
#4. 配置 LVS 规则,配置 DR 模型: | |
[root@lvs01 ~]# ipvsadm -C | |
[root@lvs01 ~]# ipvsadm -L -n | |
[root@lvs01 ~]# ipvsadm -A -t 172.16.1.100:80 -s rr | |
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.100:80 -r 172.16.1.7:80 -g | |
[root@lvs01 ~]# ipvsadm -a -t 172.16.1.100:80 -r 172.16.1.8:80 -g | |
[root@lvs01 ~]# ipvsadm -L -n | |
IP Virtual Server version 1.2.1 (size=4096) | |
Prot LocalAddress:Port Scheduler Flags | |
-> RemoteAddress:Port Forward Weight ActiveConn InActConn | |
TCP 172.16.1.100:80 rr | |
-> 172.16.1.7:80 Route 1 0 0 | |
-> 172.16.1.8:80 Route 1 0 0 |
# 3.6.7 路由器配置端口映射
#1. 端口路由器的映射: | |
[root@route ~]# iptables -t nat -A PREROUTING -d 192.168.40.200 -p tcp --dport 80 -j DNAT --to 172.16.1.100:80 | |
[root@route ~]# iptables -t nat -A PREROUTING -d 192.168.40.200 -p tcp --dport 443 -j DNAT --to 172.16.1.100:443 | |
[root@route ~]# iptables -L -n -t nat | |
Chain PREROUTING (policy ACCEPT) | |
target prot opt source destination | |
DNAT tcp -- 0.0.0.0/0 192.168.40.200 tcp dpt:80 to:172.16.1.100:80 | |
DNAT tcp -- 0.0.0.0/0 192.168.40.200 tcp dpt:443 to:172.16.1.100:443 |
# 3.6.8 测试验证
#1. 验证测试 | |
[root@client ~]# curl -HHost:lvs.hmallleasing.com http://192.168.40.200 | |
web02 Real Server | |
[root@client ~]# curl -HHost:lvs.hmallleasing.com http://192.168.40.200 | |
web01 Real Server | |
#2. 查看客户端是否与 web 服务器虚拟 IP 建立握手 | |
[root@web01 ~]# dd if=/dev/zero of=/code/bigdata bs=3000M count=1 | |
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name | |
tcp 0 0 172.16.1.100:80 192.168.40.1:61004 ESTABLISHED 1809/nginx: worker | |
tcp 0 0 172.16.1.8:22 172.16.1.41:51444 ESTABLISHED 1676/sshd: root@pts | |
#3. 对于客服端与路由器建立握手 | |
C:\Users\Administrator>netstat -an | |
TCP 192.168.40.1:61004 192.168.40.200:80 ESTABLISHED | |
#4. 查看 LVS 连接记录 | |
[root@lvs01 ~]# ipvsadm -L -c -n | |
IPVS connection entries | |
pro expire state source virtual destination | |
TCP 01:25 FIN_WAIT 192.168.40.10:51664 172.16.1.100:80 172.16.1.7:80 | |
TCP 01:23 FIN_WAIT 192.168.40.10:51662 172.16.1.100:80 172.16.1.8:80 |
# 3.7 shell 脚本配置 LVS 场景
在网络规划没有问题的情况下,通过脚本来实现 LVS-DR 模型。(注意修改脚本中的 IP 地址)
# 3.7.1 DS 配置脚本
[root@lvs01 ~]# cat lvs_ds.sh | |
#!/usr/bin/bash | |
VIP=172.16.1.100 | |
RS1=172.16.1.7 | |
RS2=172.16.1.8 | |
PORT=80 | |
SCHEDULER=rr | |
DEV=eth1:1 | |
case $1 in | |
start) | |
# 配置虚拟 IP 地址 VIP | |
cat >/etc/sysconfig/network-scripts/ifcfg-${DEV} <<-EOF | |
TYPE=Ethernet | |
BOOTPROTO=none | |
DEFROUTE=yes | |
NAME=${DEV} | |
DEVICE=${DEV} | |
ONBOOT=yes | |
IPADDR=${VIP} | |
PREFIX=24 | |
EOF | |
# 启动网卡 | |
ifup ${DEV} | |
# 配置 LVS 规则 | |
ipvsadm -C | |
ipvsadm -A -t ${VIP}:${PORT} -s ${SCHEDULER} | |
ipvsadm -a -t ${VIP}:${PORT} -r ${RS1} -g | |
ipvsadm -a -t ${VIP}:${PORT} -r ${RS2} -g | |
;; | |
stop) | |
ifdown ${DEV} | |
rm -f /etc/sysconfig/network-scripts/ifcfg-${DEV} | |
ipvsadm -C | |
;; | |
*) | |
echo "Usage: sh $0 { start | stop }" | |
;; | |
esac | |
[root@lvs01 ~]# chmod +x lvs_ds.sh | |
[root@lvs01 ~]# sh lvs_ds.sh stop | |
[root@lvs01 ~]# sh lvs_ds.sh start |
# 3.7.2 RS 配置脚本
[root@web01 ~]# cat lvs_rs.sh | |
#!/usr/bin/bash | |
VIP=172.16.1.100 | |
DEV=lo:0 | |
case $1 in | |
start) | |
# ARP 抑制 | |
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore | |
echo "1" >/proc/sys/net/ipv4/conf/default/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/default/arp_announce | |
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce | |
# VIP | |
cat >/etc/sysconfig/network-scripts/ifcfg-${DEV} <<-EOF | |
DEVICE=lo:0 | |
IPADDR=${VIP} | |
NETMASK=255.0.0.0 | |
ONBOOT=yes | |
NAME=loopback | |
EOF | |
ifup ${DEV} # 启动网卡 | |
systemctl start nginx | |
;; | |
stop) | |
echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore | |
echo "0" >/proc/sys/net/ipv4/conf/default/arp_ignore | |
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore | |
echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce | |
echo "0" >/proc/sys/net/ipv4/conf/default/arp_announce | |
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce | |
ifdown ${DEV} # 停止网卡 | |
rm -f /etc/sysconfig/network-scripts/ifcfg-${DEV} | |
systemctl stop nginx | |
;; | |
*) | |
echo "Usage: sh $0 { start | stop }" | |
esac | |
[root@web01 ~]# chmod +x lvs_rs.sh | |
[root@web01 ~]# sh lvs_rs.sh stop | |
[root@web01 ~]# sh lvs_rs.sh start |
# 4.LVS+Keepalived 实现高可用
# 4.1 为什么需要高可用
问题:LVS 可以实现负载均衡功能,但是没有健康检查机制,以及冗余机制。
- 1. 如果一台 RS 节点故障,LVS 任然会将请求调度至该盖章 RS 节点服务器;
- 2. 其次 LVS 节点出现故障,那么整个集群就无法正常对外提供服务;
解决:可以使用 keepalived 软件来解决如上问题。
- 1. 使用 keealived 可以实现 LVS 的健康检查机制,RS 节点故障,则自动剔除该故障的 RS 节点,如果 RS 节点恢复则自动加入集群;
- 2. 使用 keealived 可以解决 LVS 单点故障,以此实现 LVS 的高可用
总结:keealived 就是为 LVS 而诞生的。
# 4.2 Master 节点配置
1. 安装 keealived 软件
#1. 安装软件 | |
[root@lvs02 ~]# yum install keepalived -y | |
#2. 关闭七层负载均衡的 keepalived | |
#3. 配置 lvs-master 的 keepalived, (记得先删除 lvs 上的虚拟 IP,以及 ipvs 规则) | |
[root@lvs01 ~]# sh lvs_ds.sh stop | |
[root@lvs01 ~]# ipvsadm -L -n |
2. 配置 lvs-master 的 keepalived
[root@lvs01 ~]# cat /etc/keepalived/keepalived.conf | |
global_defs { | |
router_id lb01 | |
} | |
vrrp_instance VI_1 { | |
state MASTER | |
priority 200 | |
interface eth1 | |
virtual_router_id 50 | |
advert_int 1 | |
authentication { | |
auth_type PASS | |
auth_pass 1111 | |
} | |
virtual_ipaddress { | |
172.16.1.100 | |
} | |
} | |
# 配置集群地址访问的 IP+Port | |
virtual_server 172.16.1.100 80 { | |
# 健康检查的时间,单位:秒 | |
delay_loop 6 | |
# 配置负载均衡的算法 | |
lb_algo rr | |
# 设置 LVS 的模式 NAT|TUN|DR | |
lb_kind DR | |
# 设置会话持久化的时间 | |
#persistence_timeout 30 | |
# 设置协议 | |
protocol TCP | |
# 负载均衡后端的真实服务节点 RS-1 | |
real_server 172.16.1.7 80 { | |
# 权重配比设置为 1 | |
weight 1 | |
# 设置健康检查 | |
TCP_CHECK { | |
# 检测后端 80 端口 | |
connect_port 80 | |
# 超时时间 | |
connect_timeout 3 | |
# 重试次数 2 次 | |
nb_get_retry 2 | |
# 间隔时间 3s | |
delay_beefore_retry 3 | |
} | |
} | |
# 负载均衡后端的真实服务节点 RS-2 | |
real_server 172.16.1.8 80 { | |
weight 1 | |
TCP_CHECK { | |
connect_port 80 | |
connect_timeout 3 | |
nb_get_retry 2 | |
delay_beefore_retry 3 | |
} | |
} | |
} | |
# 配置集群地址访问的 IP+Port | |
virtual_server 172.16.1.100 443 { | |
delay_loop 6 | |
lb_algo rr | |
lb_kind DR | |
protocol TCP | |
real_server 172.16.1.7 443 { | |
weight 1 | |
TCP_CHECK { | |
connect_port 443 | |
connect_timeout 3 | |
nb_get_retry 2 | |
delay_beefore_retry 3 | |
} | |
} | |
real_server 172.16.1.8 443 { | |
weight 1 | |
TCP_CHECK { | |
connect_port 80 | |
connect_timeout 3 | |
nb_get_retry 2 | |
delay_beefore_retry 3 | |
} | |
} | |
} |
# 4.3 Backup 节点配置
1. 安装 keealived 软件
#1. 新的节点 172.16.1.4 需要做如下基础信息配置: | |
[root@lb02 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth1 | |
TYPE="Ethernet" | |
PROXY_METHOD="none" | |
BROWSER_ONLY="no" | |
BOOTPROTO="none" | |
DEFROUTE="yes" | |
IPV4_FAILURE_FATAL="no" | |
IPV6INIT="yes" | |
IPV6_AUTOCONF="yes" | |
IPV6_DEFROUTE="yes" | |
IPV6_FAILURE_FATAL="no" | |
IPV6_ADDR_GEN_MODE="stable-privacy" | |
NAME="eth1" | |
DEVICE="eth1" | |
ONBOOT="yes" | |
IPV6_PRIVACY="no" | |
IPADDR="172.16.1.4" | |
PREFIX="24" | |
GATEWAY=172.16.1.200 | |
[root@lvs02 ~]# ifdown eth1 && ifup eth1 | |
#2. 关闭七层负载均衡的 keepalived | |
#3. 配置 lvs-master 的 keepalived, (记得先删除 lvs 上的虚拟 IP,以及 ipvs 规则) | |
[root@lvs02 ~]# yum install keepalived -y | |
[root@lb02 ~]# yum install ipvsadm -y | |
#4. 关闭 eth0 | |
[root@lvs02 ~]# ifdown eth0 |
2. 配置 keealived 未 BACKUP 角色
[root@lb02 ~]# cat /etc/keepalived/keepalived.conf | |
global_defs { | |
router_id lb02 | |
} | |
vrrp_instance VI_1 { | |
state BACKUP | |
priority 150 | |
interface eth1 | |
virtual_router_id 50 | |
advert_int 1 | |
authentication { | |
auth_type PASS | |
auth_pass 1111 | |
} | |
virtual_ipaddress { | |
172.16.1.100 | |
} | |
} | |
# 配置集群地址访问的 IP+Port | |
virtual_server 172.16.1.100 80 { | |
# 健康检查的时间,单位:秒 | |
delay_loop 6 | |
# 配置负载均衡的算法 | |
lb_algo wlc | |
# 设置 LVS 的模式 NAT|TUN|DR | |
lb_kind DR | |
# 设置会话持久化的时间 | |
#persistence_timeout 30 | |
# 设置协议 | |
protocol TCP | |
# 负载均衡后端的真实服务节点 RS-1 | |
real_server 172.16.1.7 80 { | |
# 权重配比设置为 1 | |
weight 1 | |
# 设置健康检查 | |
TCP_CHECK { | |
# 检测后端 80 端口 | |
connect_port 80 | |
# 超时时间 | |
connect_timeout 3 | |
# 重试次数 2 次 | |
nb_get_retry 2 | |
# 间隔时间 3s | |
delay_beefore_retry 3 | |
} | |
} | |
# 负载均衡后端的真实服务节点 RS-2 | |
real_server 172.16.1.8 80 { | |
# 权重配比设置为 1 | |
weight 1 | |
# 设置健康检查 | |
TCP_CHECK { | |
# 检测后端 80 端口 | |
connect_port 80 | |
# 超时时间 | |
connect_timeout 3 | |
# 重试次数 2 次 | |
nb_get_retry 2 | |
# 间隔时间 3s | |
delay_beefore_retry 3 | |
} | |
} | |
} | |
# 配置集群地址访问的 IP+Port | |
virtual_server 172.16.1.100 443 { | |
delay_loop 6 | |
lb_algo rr | |
lb_kind DR | |
protocol TCP | |
real_server 172.16.1.7 443 { | |
weight 1 | |
TCP_CHECK { | |
connect_port 443 | |
connect_timeout 3 | |
nb_get_retry 2 | |
delay_beefore_retry 3 | |
} | |
} | |
real_server 172.16.1.8 443 { | |
weight 1 | |
TCP_CHECK { | |
connect_port 80 | |
connect_timeout 3 | |
nb_get_retry 2 | |
delay_beefore_retry 3 | |
} | |
} | |
} |
# 4.4 测试验证
1. 启动 keepalived 并查看 LVS 规则
#1. 启动 keepalived | |
[root@lvs01 ~]# systemctl enable keepalived | |
[root@lvs02 ~]# systemctl enable keepalived | |
[root@lb01 ~]# systemctl start keepalived | |
[root@lb02 ~]# systemctl start keepalived | |
#2.MASTER 查看 LVS 规则 | |
[root@lvs01 ~]# ipvsadm -L -n | |
IP Virtual Server version 1.2.1 (size=4096) | |
Prot LocalAddress:Port Scheduler Flags | |
-> RemoteAddress:Port Forward Weight ActiveConn InActConn | |
TCP 172.16.1.100:80 rr | |
-> 172.16.1.7:80 Route 1 0 0 | |
-> 172.16.1.8:80 Route 1 0 0 | |
TCP 172.16.1.100:443 rr | |
-> 172.16.1.7:443 Route 1 0 0 | |
-> 172.16.1.8:443 Route 1 0 0 | |
#3.BACKUP 查看 LVS 规则 | |
[root@lb02 ~]# ipvsadm -L -n | |
IP Virtual Server version 1.2.1 (size=4096) | |
Prot LocalAddress:Port Scheduler Flags | |
-> RemoteAddress:Port Forward Weight ActiveConn InActConn | |
TCP 172.16.1.100:80 wlc | |
-> 172.16.1.7:80 Route 1 0 0 | |
-> 172.16.1.8:80 Route 1 0 0 | |
TCP 172.16.1.100:443 rr | |
-> 172.16.1.7:443 Route 1 0 0 | |
-> 172.16.1.8:443 Route 1 0 0 | |
#4. 查看 VIP | |
[root@lvs01 ~]# ip addr | grep 172.16.1.100 | |
inet 172.16.1.100/32 scope global eth1 | |
#5. 检查应用服务是否正常 | |
[root@client ~]# curl -HHost:lvs.hmallleasing.com http://192.168.40.200 | |
web01 Real Server | |
[root@client ~]# curl -HHost:lvs.hmallleasing.com http://192.168.40.200 | |
web02 Real Server |
2. 如果 realserver 节点故障,是否会自动将其移除
#1. 停止 web01 服务 | |
[root@web01 ~]# systemctl stop nginx | |
#2. 通过查看 systemctl status keepalived -l 会发现有移除的记录 | |
[root@lvs01 ~]# systemctl status keepalived -l | |
● keepalived.service - LVS and VRRP High Availability Monitor | |
Loaded: loaded (/usr/lib/systemd/system/keepalived.service; enabled; vendor preset: disabled) | |
Active: active (running) since Thu 2025-09-11 21:42:18 CST; 9min ago | |
Process: 2050 ExecStart=/usr/sbin/keepalived $KEEPALIVED_OPTIONS (code=exited, status=0/SUCCESS) | |
Main PID: 2051 (keepalived) | |
CGroup: /system.slice/keepalived.service | |
├─2051 /usr/sbin/keepalived -D | |
├─2052 /usr/sbin/keepalived -D | |
└─2053 /usr/sbin/keepalived -D | |
Sep 11 21:51:20 lvs01 Keepalived_healthcheckers[2052]: TCP connection to [172.16.1.7]:80 success. | |
Sep 11 21:51:20 lvs01 Keepalived_healthcheckers[2052]: Adding service [172.16.1.7]:80 to VS [172.16.1.100]:80 | |
Sep 11 21:51:26 lvs01 Keepalived_healthcheckers[2052]: TCP connection to [172.16.1.7]:443 failed. | |
Sep 11 21:51:26 lvs01 Keepalived_healthcheckers[2052]: TCP connection to [172.16.1.7]:80 failed. | |
Sep 11 21:51:27 lvs01 Keepalived_healthcheckers[2052]: TCP connection to [172.16.1.7]:443 failed. | |
Sep 11 21:51:27 lvs01 Keepalived_healthcheckers[2052]: Check on service [172.16.1.7]:443 failed after 1 retry. | |
Sep 11 21:51:27 lvs01 Keepalived_healthcheckers[2052]: Removing service [172.16.1.7]:443 from VS [172.16.1.100]:443 | |
Sep 11 21:51:27 lvs01 Keepalived_healthcheckers[2052]: TCP connection to [172.16.1.7]:80 failed. | |
Sep 11 21:51:27 lvs01 Keepalived_healthcheckers[2052]: Check on service [172.16.1.7]:80 failed after 1 retry. | |
Sep 11 21:51:27 lvs01 Keepalived_healthcheckers[2052]: Removing service [172.16.1.7]:80 from VS [172.16.1.100]:80 | |
#3. 检查 ipvsadm -L -n 节点信息 | |
[root@lvs01 ~]# ipvsadm -L -n | |
IP Virtual Server version 1.2.1 (size=4096) | |
Prot LocalAddress:Port Scheduler Flags | |
-> RemoteAddress:Port Forward Weight ActiveConn InActConn | |
TCP 172.16.1.100:80 rr | |
-> 172.16.1.8:80 Route 1 0 11 | |
TCP 172.16.1.100:443 rr | |
-> 172.16.1.8:443 Route 1 0 0 | |
[root@lb02 ~]# ipvsadm -L -n | |
IP Virtual Server version 1.2.1 (size=4096) | |
Prot LocalAddress:Port Scheduler Flags | |
-> RemoteAddress:Port Forward Weight ActiveConn InActConn | |
TCP 172.16.1.100:80 wlc | |
-> 172.16.1.8:80 Route 1 0 0 | |
TCP 172.16.1.100:443 rr | |
-> 172.16.1.8:443 Route 1 0 0 | |
#4. 检查应用服务是否正常 | |
[root@client ~]# curl -HHost:lvs.hmallleasing.com http://192.168.40.200 | |
web02 Real Server | |
[root@client ~]# curl -HHost:lvs.hmallleasing.com http://192.168.40.200 | |
web02 Real Server |
2. 如果 ds 服务器故障,能否切换到备用节点
#1. 停止 Master 节点 keepalived | |
[root@lvs01 ~]# systemctl stop keepalived | |
#2. 查看备节点 VIP 是否漂移 | |
[root@lb02 ~]# ip addr | grep 172.16.1.100 | |
inet 172.16.1.100/32 scope global eth1 | |
#3. 查看备节点 IPVS 规则 | |
[root@lb02 ~]# ipvsadm -L -n | |
IP Virtual Server version 1.2.1 (size=4096) | |
Prot LocalAddress:Port Scheduler Flags | |
-> RemoteAddress:Port Forward Weight ActiveConn InActConn | |
TCP 172.16.1.100:80 wlc | |
-> 172.16.1.7:80 Route 1 0 0 | |
-> 172.16.1.8:80 Route 1 0 0 | |
TCP 172.16.1.100:443 rr | |
-> 172.16.1.7:443 Route 1 0 0 | |
-> 172.16.1.8:443 Route 1 0 0 | |
[root@lvs01 ~]# ipvsadm -L -n | |
IP Virtual Server version 1.2.1 (size=4096) | |
Prot LocalAddress:Port Scheduler Flags | |
-> RemoteAddress:Port Forward Weight ActiveConn InActConn | |
#4. 测试服务是否可用 | |
[root@client ~]# curl -HHost:lvs.hmallleasing.com http://192.168.40.200 | |
web01 Real Server | |
[root@client ~]# curl -HHost:lvs.hmallleasing.com http://192.168.40.200 | |
web02 Real Server |
# 5. LVS 持久连接实践
# 5.1 什么是持久化连接
LVS persistence 持久连接,无论使用任何调度算法,在一段时间内(默认 300s), 能够实现将来自同一地址的请求始终发往同一个 RS,常用于 SSL、FTP 等协议。
# 5.2 持久化连接配置
[root@lvs01 ~]# ipvsadm -E -t 172.16.1.100:80 -p 30 | |
[root@lvs01 ~]# ipvsadm -L -n |
# 5.3 持久化连接测试
客户端请求后,可以登陆 LVS 节点查看,是否有一个连接处于连接状态。(需要每个请求 TIME-WAIT 结算,才会断开连接)。
[root@lvs01 ~]# ipvsadm -L -n -c |
# 6. LVS 调度算法详解
LVS 根据后端服务的负载,或其他的计算标准,判断挑选那台 RS 来进行请求处理。调度算法主要分为 “静态调度算法”,“静态调度算法”。
静态调度算法:RR、WRR、SH、DH
静态调度算法:LC、WLC、SED、NQ、LBLC、LBLCR
# 6.1 LVS 静态调度算法
静态:仅根据算法本身进行调度,不考虑后端实际负载情况。
# 6.1.1 RR
RR:round robin 轮询调度算法,将每一次用户的请求,轮流分配给 Real Server 节点。
[root@lvs01 ~]# ipvsadm -E -t 172.16.1.100:80 -s rr | |
[root@lvs01 ~]# ipvsadm -L -n |
# 6.1.2 WRR
WRR:weighted round robin 加权轮询调度算法,根据服务器的硬件情况、以及处理能力,为每台服务器分配不同的权值,使其能够接受相应权值的请求。
[root@lvs01 ~]# ipvsadm -E -t 172.16.1.100:80 -s wrr | |
[root@lvs01 ~]# ipvsadm -e -t 172.16.1.100:80 -r 172.16.1.7:80 -g -w 5 | |
[root@lvs01 ~]# ipvsadm -e -t 172.16.1.100:80 -r 172.16.1.8:80 -g -w 1 | |
[root@lvs01 ~]# ipvsadm -L -n |
# 6.1.3 SH
SH:Source Hashing 源地址 hash 算法,将请求的源 IP 地址进行 Hash 运算,得到一个具体的数值,同时对后端服务器进行编号,按照运算结果将请求分发到对应编号的服务器上。
1. 可以实现不同涟源 IP 的请求进行负载分发;
2. 同时还能实现相同来源 IP 的请求始终被派发至某一台特定的节点;
[root@lvs01 ~]# ipvsadm -E -t 172.16.1.100:80 -s sh | |
[root@lvs01 ~]# ipvsadm -L -n |
# 6.1.4 DH
DH:destination hash 目标地址 hash 将客户端的请求,始终发往同一个 RS。
应用场景:LVS-cache - 源站,使用调度至指定的 cache,,加速用户体验。

[root@lvs01 ~]# ipvsadm -E -t 172.16.1.100:80 -s dh | |
[root@lvs01 ~]# ipvsadm -L -n |
# 6.2 LVS 动态调度算法
动态:根据算法及 RS 节点负载状态进行调度,较小的 RS 将被调度。
# 6.2.1 LC
LC:Least-Connection 最少连接数调度算法,那台 RS 连接数少就将请求调度至哪台 RS。
算法:Overhead = (Active * 256 + Inactive 仅连接) 一个活动连接相当于 256 个非活动连接。

# 6.2.2 WLC
WLC:Weighted Least-Connection 加权最小连接数(默认调度算法),在服务器性能差异较大的情况下,采用 “加权最少连接” 调度算法优化负载均衡性能,权值较高的 RS 节点,将承受更多的连接;负载均衡可以自动问询 RS 节点服务器的负载状态,通过算法计算当前连接数最少的节点,而后将新的请求调度至该节点。
算法:Overhead = (Active * 256 + Inactive) /weigth

# 6.2.3 SED
SED: Shortest Expected Delay 最短期望延迟,尽可能让权重高的优先接收请求,不在考虑非活动状态,把当前出于活动状态的数据 + 1,通过算法计算当前连接数最少的节点,而后将新的请求调度至该节点。
算法:在 WLC 基础上改进,Overhead = (ACTIVE* 256 + 1) /Weight

# 6.2.4 NQ
NQ:Never Queue 永不排队 / 最少队列调度
原理:SED 算法由于某台服务器的权重较小,比较空闲,甚至接收不到请求,而权重打的服务器会很忙,而 NQ 算法是说不管权重多大都会被分配到请求。简答来说,就是无需队列,如果有 Real Server 的连接数为 0 会直接分配过去,后续采用 SED 算法。
算法:Overhead = (ACTIVE + 1) * 256/Weight
# 6.2.5 LBLC
LBLC:Locality-Based Least-connection 动态目标地址 hash 调度算法,解决 DH 调度算法负载不均衡。
应用场景:LVS-cache - 源站,此前 DH 算法始终调度到后端 cache1 节点,会造成 cache1 负载过高,LBLC 会根据负载均衡动态调度到后端其他 cache 节点。

# 6.2.6 LBLCR
LBLCR:Locality-Based Least-connection with Replication 带复制功能的 LBLC 算法,解决 LBLC 负载不均衡的问题,从负载重的复制到负载轻的 RS。
应用场景:LVS-cache - 源站,此前 LBLC 算法始终调度到后端 Cache1 节点,会造成 Cache1 负载过高,会根据负载均衡动态调度到后端其他 Cace 节点,同时也会将缓存数据同步一份至 Cace1、Cace2 节点。

