# 企业级负载均衡 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 组成部分

1.png

  • 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 基础图解

1.png

# 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.png

# 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 架构规划

NAT-实现架构图.jpg

角色主机名称外网地址内网地址
客服端clienteth0:192.168.40.41/
路由器routeeth0:192.168.40.200eth1:172.16.1.200
LVSlb01/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 基础图解

1.png

# 3.2 DR 底层实现

2.png

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 架构规划

DR实现架构图.jpg

角色主机名称外网地址内网地址
客服端clienteth0:192.168.40.10/
路由器routeeth0:192.168.40.200eth1:172.16.1.200
LVSlb01/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,,加速用户体验。

2.png

[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 个非活动连接。

1.png

# 6.2.2 WLC

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

算法:Overhead = (Active * 256 + Inactive) /weigth

3.png

# 6.2.3 SED

SED: Shortest Expected Delay 最短期望延迟,尽可能让权重高的优先接收请求,不在考虑非活动状态,把当前出于活动状态的数据 + 1,通过算法计算当前连接数最少的节点,而后将新的请求调度至该节点。

算法:在 WLC 基础上改进,Overhead = (ACTIVE* 256 + 1) /Weight

1.png

# 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 节点。

1.png

# 6.2.6 LBLCR

LBLCR:Locality-Based Least-connection with Replication 带复制功能的 LBLC 算法,解决 LBLC 负载不均衡的问题,从负载重的复制到负载轻的 RS。

应用场景:LVS-cache - 源站,此前 LBLC 算法始终调度到后端 Cache1 节点,会造成 Cache1 负载过高,会根据负载均衡动态调度到后端其他 Cace 节点,同时也会将缓存数据同步一份至 Cace1、Cace2 节点。

2.png

此文章已被阅读次数:正在加载...更新于

请我喝[茶]~( ̄▽ ̄)~*

Xu Yong 微信支付

微信支付

Xu Yong 支付宝

支付宝