lvs学习笔记

一、简要概述

LVS(Linux Virtual Server)是在 LInux 中的一种基于网络层的高性能负载均衡技术。

  • LVS 的核心模块(即 ipvs)已被集成到 Linux 内核中。
  • LVS 是章文嵩博士主导的开源的负载均衡项目。

注意:LVS 是基于网络层的负载均衡解决方案,通过 IP 数据包转发实现负载均衡。HAProxy 和 Nginx 是基于应用层的负载均衡解决方案,通过代理请求和响应来实现负载均衡。LVS 由于是基于网络层的且直接在内核层进行操作的,故相对于对于 Nginx 具有更佳的性能和吞吐量。但由于其基于网络层无法处理数据报文以导致无法像 Nginx 那样基于 URL 做负载均衡,故在实际生产环境下通常同时使用 LVS + Nginx 共同实现负载均衡需求(即 LVS 负责 IP 流量分流到 Nginx,Nginx 负责根据数据报文(如:URL等)进行连接分流),这样的组合架构充分发挥了LVS的性能优势和Nginx的高级功能,满足了不同层次的负载均衡需求。

二、LVS 工作模式

LVS(Linux Virtual Server)是一个开源的负载均衡解决方案,它提供了多种工作模式来实现负载均衡和高可用性。LVS有三种主要工作模式,即:NAT 模式、TUN 模式、DR 模式。每种工作模式都有其适用的场景和特点,选择合适的模式取决于具体的需求和环境。,通常 NAT 模式、尤其是 DR 模式是应用比较多的两种模式。

提示:一般而言,NAT模式和DR模式下的LVS工作在网络层,而TUN模式下的LVS工作在传输层

NAT 模式

NAT(Network Address Translation)模式:也称网络地址转换模式。在NAT模式下,LVS作为一个网络层的负载均衡器,将客户端请求的数据包的目标IP地址和端口修改为后端服务器的IP地址和端口,然后将数据包转发给后端服务器。当后端服务器返回响应时,LVS再将响应的数据包的源IP地址和端口修改为负载均衡器的IP地址和端口,再将响应发送给客户端。NAT模式适用于负载均衡和网络地址转换的场景。

image-20230607005049517

NAT 模式集群网络拓扑类似于 Nginx。但 LVS 和 Nginx 的实现原理不同,Nginx 的实现原理是代理,而 LVS NAT模式的实现原理是流量(数据包)转发,可以理解 LVS 为路由器。

代理和数据包转发的区别:

代理和数据包转发是两种不同的网络通信方式,它们在实现原理和功能上有一些区别。

(1)概念:

  • 代理是一种通过中间服务器来转发网络请求和响应的方式。当客户端发送请求时,请求首先发送给代理服务器,然后代理服务器再将请求发送到目标服务器,并将响应返回给客户端。代理服务器在请求和响应的传递过程中可以对数据进行修改、过滤或缓存,还可以实现负载均衡和内容路由等功能。代理通常工作在应用层,例如 HTTP 代理(如 Nginx、Apache)、反向代理等。

  • 数据包转发是一种直接将网络数据包从源地址转发到目标地址的方式。数据包转发通常在网络层进行,通过路由器或交换机等网络设备进行数据包的转发。数据包转发是基于 IP 地址和端口号来决定转发路径的,它不会修改请求和响应的内容,只负责将数据包从源设备转发到目标设备。常见的数据包转发技术包括 IP 路由、网络地址转换(NAT)等。

(2)区别:

  • 代理是在应用层工作,可以对数据进行处理和修改,可以实现更灵活的功能,如负载均衡、缓存、安全过滤等。数据包转发是在网络层工作,主要负责将数据包从源地址转发到目标地址,不会对数据包进行修改。

  • 代理通常需要对请求进行解析和重新封装,因此会有一定的性能开销。数据包转发则更加直接和高效,因为它只涉及数据包的转发。

  • 代理通常工作在边缘节点,直接与客户端和服务器交互,可以在两者之间起到中间层的作用。数据包转发通常在网络设备上进行,作用于整个网络中的数据包转发过程。

(3)适用场景:选择使用代理还是数据包转发取决于具体的需求和场景。代理适合需要对请求和响应进行处理和修改的场景,而数据包转发适合需要直接转发网络数据包的场景。

TUN 模式

TUN(Tunneling)模式:也称 IP 隧道模式。 在TUN模式下,LVS将客户端请求的数据包封装成IP隧道,在传输层(TCP/UDP)上进行负载均衡。LVS将隧道数据包转发给后端服务器,后端服务器进行解封装并处理请求。后端服务器将响应的数据包返回给LVS,LVS再将响应封装成隧道数据包发送给客户端。TUN模式适用于需要在传输层进行负载均衡的场景。

image-20230607164605148

TUN 模式有个硬性的要求是真实服务器需要暴露在公网环境下(即网卡 IP 需要暴露在公网环境),这样会存在比较大的安全隐患,故而真实生产环境下用的比较少。

DR 模式

DR(Direct Routing)模式: 也称直接路由模式。在DR模式下,LVS作为一个二层负载均衡器,客户端请求的数据包到达负载均衡器后,负载均衡器会直接将数据包转发给后端服务器,不对数据包的IP地址和端口进行修改。后端服务器将响应直接发送给客户端,绕过了负载均衡器。DR模式适用于高性能的负载均衡需求。

image-20230606225212479

DR 模式下真实服务器可以在私网环境,而不需要暴露在公网环境下,真实服务器响应时只需经路由器返回给客户端即可(多个真实服务器可以统一使用一个路由器,但为了提升响应吞吐性能也可以考虑为每个真实服务器配置单独的路由器,具体实现待研究学习(TODO)…)。

提示:如果仅是实验测试,客户端、LVS、真实服务器网络连通,可以不为真实服务器配置路由器而是直接返回给客户端。

三、LVS NAT 模式集群

1. 准备环境

(1)LVS 服务器:

  • DIP:192.168.60.101
  • VIP:192.168.17.101(提供给客户端访问的 IP)

(2)Real Server1:

  • RIP:192.168.60.201(必须配置网关为 DIP)

(2)Real Server2:

  • RIP:192.168.60.202(必须配置网关为 DIP)

注意:如以上环境为 Vmware 虚拟机,DIP 、VIP、RIP 的 Vmware 网卡网络连接方式可为任意网络模式,但需要注意,DIP 和 RIP 需要是同一网段(即同一网卡),而 VIP 需要是另一网段(即另一个网卡)。本次实验对几个虚拟机的网卡设定为:DIP 和 RIP 使用 VMnet8 网卡(NAT模式),而 VIP 使用新增的 VMnet1 网卡(仅主机模式)。Vmware 虚拟机配置如下:

image-20230607155759994

2. 真实服务器配置

1)网络配置

Real Server1 网络配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#配置RIP并设置网关为DIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens33 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens33"
UUID="4f676de2-5673-431b-b8fc-2dc4ad9accfc"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.60.201"
GATEWAY="192.168.60.101"
NETMASK="255.255.255.0"
#DNS1="8.8.8.8"
EOF

#重启网络
service network restart

注意:以上 GATEWAY 需要配置为 DIP 的值。

Real Server2 网络配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#配置RIP并设置网关为DIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens33 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens33"
UUID="4f676de2-5673-431b-b8fc-2dc4ad9accfc"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.60.202"
GATEWAY="192.168.60.101"
NETMASK="255.255.255.0"
#DNS1="8.8.8.8"
EOF

#重启网络
service network restart

2)部署web服务(Nginx)

在 Real Server1 和 Real Server2 两台真实服务器上执行以下步骤操作:

1
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
#拉取(下载)镜像
docker pull nginx:latest
#首先简单运行一个nginx临时容器,用于复制容器内部的一些nginx相关重要文件到宿主机
docker run -d --name nginx nginx:latest
#创建映射目录
mkdir -p /opt/nginx/{conf,html,logs}
#复制容器内部的一些nginx相关重要文件到映射目录中(注意命令中的末尾的点,它表示复制目录中的所有内容而不是整个目录本身)
docker cp nginx:/etc/nginx/. /opt/nginx/conf
docker cp nginx:/usr/share/nginx/html/. /opt/nginx/html
docker cp nginx:/var/log/nginx/. /opt/nginx/logs
#删除nginx临时容器
docker rm -f nginx

#生产环境下运行nginx容器
#(1)使用host网络模式直接使用宿主机网络IP地址和端口(可以避免每次配置新的监听端口都需要重新docker run映射端口)
#(2)限制内存上限为200MB
#(3)指定时区并同步宿主机和容器的时间
#(4)映射几个主要的nginx相关目录
docker run -d --name nginx \
--net=host \
-m 200m \
-e TZ=Asia/Shanghai \
-v /etc/localtime:/etc/localtime:ro \
-v /opt/nginx/conf:/etc/nginx \
-v /opt/nginx/html:/usr/share/nginx/html \
-v /opt/nginx/logs:/var/log/nginx \
nginx:latest

#防火墙设置(开放nginx默认配置的80端口)
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload


#备份nginx访问首页文件
cp /opt/nginx/html/index.html /opt/nginx/html/index.old.html
#将宿主机默认网卡的IP写到nginx访问首页文件
ip route get 8.8.8.8 | grep -oP 'src\s+\K\S+' > /opt/nginx/html/index.html

3. LVS 服务器配置

1)网络配置

1
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
#配置DIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens33 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens33"
UUID="4f676de2-5673-431b-b8fc-2dc4ad9accfc"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.60.101"
GATEWAY="192.168.60.2"
NETMASK="255.255.255.0"
#DNS1="8.8.8.8"
EOF

#配置VIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens36 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens36"
UUID="73c77ea7-8794-4f1b-8773-88ccd2348a8b"
DEVICE="ens36"
ONBOOT="yes"
IPADDR="192.168.17.101"
GATEWAY="192.168.17.1"
NETMASK="255.255.255.0"
DNS1="8.8.8.8"
EOF

#重启网络
service network restart

提示:以上配置 DIP 的 GATEWAY 值为 VMnet8 网卡的默认网关 IP(可以在 vmware 的“虚拟网络编辑器”中查看)。配置 VIP 的 GATEWAY 值为 VMnet8 网卡在物理机分配的 IP。

新增的 VMware 网卡后,Linux 会自动多出一个网络接口,可通过 ip addr 或者 ls /sys/class/net 查看新增的网卡名称(如:ens36

2)配置服务器允许路由转发功能

1
2
3
4
5
6
7
8
#修改内核参数,配置LVS服务器允许路由转发功能,1为开启,0为关闭(默认)
cat >> /etc/sysctl.conf << 'EOF'
net.ipv4.ip_forward = 1
EOF
#使sysctl.conf配置修改生效
sysctl -p
#查看配置是否生效
cat /proc/sys/net/ipv4/ip_forward #注意不要直接修改这个文件的值,因为这个文件时临时文件,重启系统后将会被还原,所以应该是修改sysctl.conf来实现永久生效

3)配置LVS-NAT集群

(1)安装LVS集群管理工具
1
yum install -y ipvsadm
(2)配置NAT集群
1
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
#操作前最好清空所有集群规则(防止操作过影响实验结果)
ipvsadm -C

#创建集群 -t 指定VIP地址和端口作为集群ID标识,-s指定负载均衡策略(rr表示轮询)
ipvsadm -A -t 192.168.60.101:80 -s rr

#添加真实服务器 -r指定RIP;-m指定LVS工作模式为NAT模式
ipvsadm -a -t 192.168.60.101:80 -r 192.168.17.201 -m
ipvsadm -a -t 192.168.60.101:80 -r 192.168.17.202 -m

#查看集群规则
#-L:参数表示列出当前的 IPVS 配置。
#-n:参数表示以数字形式显示 IP 地址和端口号,而不进行 DNS 解析。
#-c:参数表示连续显示 IPVS 的状态信息,而不进行分页显示。
ipvsadm -Ln
#查看集群连接状态
ipvsadm -Lnc

#防火墙设置
##方式1:关闭防火墙
#关闭firewalld防火墙
systemctl stop firewalld
systemctl disable firewalld
#清空当前的iptables规则,使防火墙恢复到默认状态。即:允许所有的网络流量通过,不进行任何过滤或限制
#iptables -F

##方式2:配置防火墙规则(TODO:未成功,尚未找到解决办法)
#firewall-cmd --permanent --add-port=80/tcp
#firewall-cmd --reload

注意:VIP 和 RIP 一定不能是一个网段,否则NAT转发失败。

4. 客户端测试

1
curl http://192.168.60.101:80

四、LVS DR 模式集群

1. 准备环境

(1)LVS 服务器:

  • DIP:192.168.60.101
  • VIP:192.168.60.100(提供给客户端访问的 IP)

(2)Real Server1:

  • RIP:192.168.60.201
  • VIP:192.168.60.100(响应客户端请求的 IP)

(2)Real Server2:

  • RIP:192.168.60.202
  • VIP:192.168.60.100(响应客户端请求的 IP)

说明:

  • DIP(Director IP):即 LVS 负载均衡器的 IP 地址
  • RIP(Real IP):即后端真实服务器的 IP 地址
  • VIP(Virtual IP):即 LVS 集群的虚拟 IP 地址

LVS 的 VIP 是用于接收客户端的请求,LVS 通过自身的 DIP 将请求负载均衡转发到后端真实服务器(Real Server)的 RIP 上,响应则是通过 Real Server 的 VIP 返回给客户端。

注意:如以上环境为 Vmware 虚拟机,DIP 、VIP、RIP 的 Vmware 网卡网络连接方式可为任意网络模式,但需要注意,DIP 和 RIP 需要是同一网段(即同一网卡),而 VIP 则通过网卡子接口的方式配置,无需增加网卡。

本次实验对几个虚拟机的网卡设定为:DIP 和 RIP 使用 VMnet8 网卡(NAT模式),而 VIP 通过网卡子接口的方式配置。Vmware 虚拟机配置如下:

image-20230607155646252

2. 真实服务器配置

1)网络配置

Real Server1 网络配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#配置RIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens33 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens33"
UUID="4f676de2-5673-431b-b8fc-2dc4ad9accfc"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.60.201"
GATEWAY="192.168.60.2"
NETMASK="255.255.255.0"
#DNS1="8.8.8.8"
EOF

#重启网络
service network restart

Real Server2 网络配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#配置RIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens33 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens33"
UUID="4f676de2-5673-431b-b8fc-2dc4ad9accfc"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.60.202"
GATEWAY="192.168.60.2"
NETMASK="255.255.255.0"
#DNS1="8.8.8.8"
EOF

#重启网络
service network restart

在 Real Server1 和 Real Server2 两台真实服务器上都执行以下步骤操作:

1
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
#配置VIP(通过配置lo回环网卡子接口设置VIP)
cat > /etc/sysconfig/network-scripts/ifcfg-lo:1 << 'EOF'
DEVICE=lo:1
IPADDR=192.168.60.100
NETMASK=255.255.255.255
NETWORK=192.168.60.100
BROADCAST=127.255.255.255
ONBOOT=yes
NAME=loopback
EOF

#由于LVS服务器和两台真实服务器存在相同的VIP,会产生IP地址冲突,解决办法是修改内核参数。如下:
#arp_ignore为1表示:当有arp广播问谁是VIP时,本机忽略掉ARP广播,不做任何回应
#arp_announce为2表示:本机不要向外宣告自己的lo回环地址是VIP
cat >> /etc/sysctl.conf << 'EOF'
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
EOF

#使sysctl.conf配置修改生效
sysctl -p

#重启网络
service network restart
#查看IP配置是否生效
ip addr

2)部署web服务(Nginx)

1
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
#拉取(下载)镜像
docker pull nginx:latest
#首先简单运行一个nginx临时容器,用于复制容器内部的一些nginx相关重要文件到宿主机
docker run -d --name nginx nginx:latest
#创建映射目录
mkdir -p /opt/nginx/{conf,html,logs}
#复制容器内部的一些nginx相关重要文件到映射目录中(注意命令中的末尾的点,它表示复制目录中的所有内容而不是整个目录本身)
docker cp nginx:/etc/nginx/. /opt/nginx/conf
docker cp nginx:/usr/share/nginx/html/. /opt/nginx/html
docker cp nginx:/var/log/nginx/. /opt/nginx/logs
#删除nginx临时容器
docker rm -f nginx

#生产环境下运行nginx容器
#(1)使用host网络模式直接使用宿主机网络IP地址和端口(可以避免每次配置新的监听端口都需要重新docker run映射端口)
#(2)限制内存上限为200MB
#(3)指定时区并同步宿主机和容器的时间
#(4)映射几个主要的nginx相关目录
docker run -d --name nginx \
--net=host \
-m 200m \
-e TZ=Asia/Shanghai \
-v /etc/localtime:/etc/localtime:ro \
-v /opt/nginx/conf:/etc/nginx \
-v /opt/nginx/html:/usr/share/nginx/html \
-v /opt/nginx/logs:/var/log/nginx \
nginx:latest

#防火墙设置(开放nginx默认配置的80端口)
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload


#备份nginx访问首页文件
cp /opt/nginx/html/index.html /opt/nginx/html/index.old.html
#将宿主机默认网卡的IP写到nginx访问首页文件
ip route get 8.8.8.8 | grep -oP 'src\s+\K\S+' > /opt/nginx/html/index.html

3. LVS 服务器配置

在 LVS 服务器上执行以下步骤操作:

1)网络配置

1
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
#配置DIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens33 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens33"
UUID="4f676de2-5673-431b-b8fc-2dc4ad9accfc"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.60.101"
GATEWAY="192.168.60.2"
NETMASK="255.255.255.0"
#DNS1="8.8.8.8"
EOF

#配置VIP(通过配置网卡子接口设置VIP)
cat > /etc/sysconfig/network-scripts/ifcfg-ens33:1 << 'EOF'
BOOTPROTO="static"
DEVICE="ens33:1"
ONBOOT="yes"
IPADDR="192.168.60.100"
NETMASK="255.255.255.0"
EOF

#重启网络
service network restart
#查看IP配置是否生效
ip addr

2)配置LVS-DR集群

(1)安装LVS集群管理工具
1
yum install -y ipvsadm

提示:ipvsadm 并不是 LVS,ipvs 作为 LVS 的核心模块已经内置在了 Linux 内核中,但是由于不能直接操作内核,故才需要使用到 ipvsadm 作为 ipvs 的管理工具。

(2)配置DR集群
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#操作前最好清空所有集群规则(防止操作过影响实验结果)
ipvsadm -C

#创建集群 -t 指定VIP地址和端口作为集群ID标识,-s指定负载均衡策略(rr表示轮询)
ipvsadm -A -t 192.168.60.100:80 -s rr

#添加真实服务器 -r指定RIP;-g指定LVS工作模式为DR模式(DR为默认模式,可以不指定)
ipvsadm -a -t 192.168.60.100:80 -r 192.168.60.201 -g
ipvsadm -a -t 192.168.60.100:80 -r 192.168.60.202 -g

#存配置或规则(以上添加的集群配置在系统重启后将会丢失,如需持久化可如下操作:)
ipvsadm -S #或者:ipvsadm --save > /etc/sysconfig/ipvsadm

#查看集群规则
ipvsadm -Ln

#防火墙设置
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload

4. 客户端测试

1
curl http://192.168.60.100:80

参考

https://www.jianshu.com/p/2ed85a5204cc

五、Keepalived + LVS(DR 模式)+ Nginx 实现高可用负载均衡架构

Keepalived 默认就支持 LVS 集群规则自动化配置功能(而不需要使用 ipvsadm 来手动创建 LVS 集群规则),此外 Keepalived 还支持对真实服务器进行健康检查的,另外使用 Keepalived 配置虚拟 IP(VIP) 还能自动添加到系统网卡配置里,而无需再通过配置网卡子接口设置VIP。由于 Keepalived 对 LVS 的极佳支持,故而生产环境上更推荐使用 Keepalived 来完成 LVS 的集群配置。

keepalived-lvs-nginx

提示:ipvsadm 手动创建的 LVS 集群规则默认是不支持对真实服务器进行健康检查的,只能借助脚本来间接实现健康检查。

1. 准备环境

(1)LVS1 服务器:

  • DIP:192.168.60.101
  • VIP:192.168.60.100(keepalived 的 master节点,提供给客户端访问的 IP)

(2)LVS2 服务器:

  • DIP:192.168.60.102
  • VIP:192.168.60.100(keepalived 的 backup 节点,提供给客户端访问的 IP)

(3)Real Server1:

  • RIP:192.168.60.201
  • VIP:192.168.60.100(响应客户端请求的 IP)

(4)Real Server2:

  • RIP:192.168.60.202
  • VIP:192.168.60.100(响应客户端请求的 IP)

注意:如以上环境为 Vmware 虚拟机,配置可参考上文“LVS DR 模式集群”。

2. 真实服务器配置

1)网络配置

Real Server1 网络配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#配置RIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens33 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens33"
UUID="4f676de2-5673-431b-b8fc-2dc4ad9accfc"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.60.201"
GATEWAY="192.168.60.2"
NETMASK="255.255.255.0"
#DNS1="8.8.8.8"
EOF

#重启网络
service network restart

Real Server2 网络配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#配置RIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens33 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens33"
UUID="4f676de2-5673-431b-b8fc-2dc4ad9accfc"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.60.202"
GATEWAY="192.168.60.2"
NETMASK="255.255.255.0"
#DNS1="8.8.8.8"
EOF

#重启网络
service network restart

在 Real Server1 和 Real Server2 两台真实服务器上都执行以下步骤操作:

1
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
#配置VIP(通过配置lo回环网卡子接口设置VIP)
cat > /etc/sysconfig/network-scripts/ifcfg-lo:1 << 'EOF'
DEVICE=lo:1
IPADDR=192.168.60.100
NETMASK=255.255.255.255
NETWORK=192.168.60.100
BROADCAST=127.255.255.255
ONBOOT=yes
NAME=loopback
EOF

#由于LVS服务器和两台真实服务器存在相同的VIP,会产生IP地址冲突,解决办法是修改内核参数。如下:
#arp_ignore为1表示:当有arp广播问谁是VIP时,本机忽略掉ARP广播,不做任何回应
#arp_announce为2表示:本机不要向外宣告自己的lo回环地址是VIP
cat >> /etc/sysctl.conf << 'EOF'
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
EOF

#使sysctl.conf配置修改生效
sysctl -p

#重启网络
service network restart
#查看IP配置是否生效
ip addr

2)部署web服务(Nginx)

1
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
#拉取(下载)镜像
docker pull nginx:latest
#首先简单运行一个nginx临时容器,用于复制容器内部的一些nginx相关重要文件到宿主机
docker run -d --name nginx nginx:latest
#创建映射目录
mkdir -p /opt/nginx/{conf,html,logs}
#复制容器内部的一些nginx相关重要文件到映射目录中(注意命令中的末尾的点,它表示复制目录中的所有内容而不是整个目录本身)
docker cp nginx:/etc/nginx/. /opt/nginx/conf
docker cp nginx:/usr/share/nginx/html/. /opt/nginx/html
docker cp nginx:/var/log/nginx/. /opt/nginx/logs
#删除nginx临时容器
docker rm -f nginx

#生产环境下运行nginx容器
#(1)使用host网络模式直接使用宿主机网络IP地址和端口(可以避免每次配置新的监听端口都需要重新docker run映射端口)
#(2)限制内存上限为200MB
#(3)指定时区并同步宿主机和容器的时间
#(4)映射几个主要的nginx相关目录
docker run -d --name nginx \
--net=host \
-m 200m \
-e TZ=Asia/Shanghai \
-v /etc/localtime:/etc/localtime:ro \
-v /opt/nginx/conf:/etc/nginx \
-v /opt/nginx/html:/usr/share/nginx/html \
-v /opt/nginx/logs:/var/log/nginx \
nginx:latest

#防火墙设置(开放nginx默认配置的80端口)
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload


#备份nginx访问首页文件
cp /opt/nginx/html/index.html /opt/nginx/html/index.old.html
#将宿主机默认网卡的IP写到nginx访问首页文件
ip route get 8.8.8.8 | grep -oP 'src\s+\K\S+' > /opt/nginx/html/index.html

3. LVS 服务器配置

1)网络配置

LVS1 网络配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#配置DIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens33 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens33"
UUID="4f676de2-5673-431b-b8fc-2dc4ad9accfc"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.60.101"
GATEWAY="192.168.60.2"
NETMASK="255.255.255.0"
#DNS1="8.8.8.8"
EOF

#重启网络
service network restart

LVS2 网络配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#配置DIP
cat > /etc/sysconfig/network-scripts/ifcfg-ens33 << 'EOF'
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
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="ens33"
UUID="4f676de2-5673-431b-b8fc-2dc4ad9accfc"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.60.102"
GATEWAY="192.168.60.2"
NETMASK="255.255.255.0"
#DNS1="8.8.8.8"
EOF

#重启网络
service network restart

2)安装 LVS 集群管理工具

在 LVS1 和 LVS2 两台服务器上都执行以下步骤操作:

1
yum install -y ipvsadm

这里安装 ipvsadm 的目的主要是用于清空 LVS 集群配置规则以及查看 LVS 集群规则,而不需要使用来创建 LVS 集群规则。

3)清空 LVS 集群配置规则

1
2
#操作前最好清空所有集群规则(防止操作过影响实验结果)
ipvsadm -C

4)通过 Keepalived 配置 VIP 和 LVS 的 DR 模式集群

在 LVS1 和 LVS2 两台服务器上都执行以下步骤操作:

(1)安装 Keepalived
1
2
3
4
5
6
7
8
9
10
11
12
13
#安装编译依赖
yum -y install gcc curl openssl-devel libnl3-devel net-snmp-devel
#下载keepalived源码包
wget https://keepalived.org/software/keepalived-2.0.20.tar.gz
#解压源码包
tar -zxvf keepalived-2.0.20.tar.gz
#进入源码包解压目录
cd keepalived-2.0.20
#生成Makefile文件
./configure --prefix=/opt/keepalived
#可以通过指定--sysconf来指定配置文件的安装路径,如:./configure --prefix=/opt/keepalived --sysconf=/etc
#编译并安装
make && make install
(2)配置 Keepalived
1
vim /opt/keepalived/etc/keepalived/keepalived.conf

LVS1 服务器配置:

1
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
global_defs {
#运行keepalived服务器的一个标识(每个服务的不一样),可以用作发送邮件的主题信息
router_id lvs1
}

vrrp_instance VI_1 {
#初始化当前节点的默认主备类型,有两个值可选MASTER主 BACKUP备(可以都设置为BACKUP,让keepalived自己根据priority值大小自己选举MASTER)
state MASTER
#vrrp实例绑定的网卡接口名称(可以通过ifconfig命令查看),用于发送VRRP
interface ens33
#指定VRRP实例ID(相同虚拟ip的多个服务该值要相同),范围是0-255
virtual_router_id 51
#指定优先级,优先级高的将成为MASTER(注意:BACKUP节点的优先级应该要比MASTER的小)
priority 100
#指定发送VRRP通告的间隔,单位是秒
advert_int 1
authentication {
#指定认证方式。PASS简单密码认证(推荐)
auth_type PASS
#指定认证使用的密码,最多8位
auth_pass 1111
}
#虚拟IP地址设置虚拟IP地址(需要和以上interface网卡接口的真实ip在同一网段),供用户访问使用,可设置多个,一行一个
virtual_ipaddress {
192.168.60.100
}
}

##配置LVS的VIP规则
virtual_server 192.168.60.100 80 {
#健康检查的时间
delay_loop 6
#设置LVS调度算法为RR
lb_algo rr
#设置LVS的模式为DR
lb_kind DR
#开启后,客户端在一定时间内始终访问相同服务器
#persistence_timeout 50
#使用的协议
protocol TCP
#设置Real Server1的RIP
real_server 192.168.60.201 80 {
#设置权重为1
weight 1
#对后台real_server做健康检查
TCP_CHECK {
#每次连接的超时时间3s
connect_timeout 3
#失败以后,重复检查多少次
nb_get_retry 3
#每隔3s检查一下
delay_before_retry 3
}
}
#设置Real Server2的RIP
real_server 192.168.60.202 80 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}

LVS2 服务器配置:

1
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
global_defs {
#运行keepalived服务器的一个标识(每个服务的不一样),可以用作发送邮件的主题信息
router_id lvs2
}

vrrp_instance VI_1 {
#初始化当前节点的默认主备类型,有两个值可选MASTER主 BACKUP备(可以都设置为BACKUP,让keepalived自己根据priority值大小自己选举MASTER)
state BACKUP
#vrrp实例绑定的网卡接口名称(可以通过ifconfig命令查看),用于发送VRRP
interface ens33
#指定VRRP实例ID(相同虚拟ip的多个服务该值要相同),范围是0-255
virtual_router_id 51
#指定优先级,优先级高的将成为MASTER(注意:BACKUP节点的优先级应该要比MASTER的小)
priority 50
#指定发送VRRP通告的间隔,单位是秒
advert_int 1
authentication {
#指定认证方式。PASS简单密码认证(推荐)
auth_type PASS
#指定认证使用的密码,最多8位
auth_pass 1111
}
#虚拟IP地址设置虚拟IP地址(需要和以上interface网卡接口的真实ip在同一网段),供用户访问使用,可设置多个,一行一个
virtual_ipaddress {
192.168.60.100
}
}

##配置LVS的VIP规则
virtual_server 192.168.60.100 80 {
#健康检查的时间
delay_loop 6
#设置LVS调度算法为RR
lb_algo rr
#设置LVS的模式为DR
lb_kind DR
#开启后,客户端在一定时间内始终访问相同服务器
#persistence_timeout 50
#使用的协议
protocol TCP
#设置Real Server1的RIP
real_server 192.168.60.201 80 {
#设置权重为1
weight 1
#对后台real_server做健康检查
TCP_CHECK {
#每次连接的超时时间3s
connect_timeout 3
#失败以后,重复检查多少次
nb_get_retry 3
#每隔3s检查一下
delay_before_retry 3
}
}
#设置Real Server2的RIP
real_server 192.168.60.202 80 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}

keepalived 备节点配置和主节点差不多,只需要修改router_id、state、priority 即可。

(3)运行 keepalived
1
2
3
4
5
6
7
8
9
10
11
12
13
#启动运行keepalived(通过-f指定配置文件,如果不指定则默认使用的配置文件路径为:/etc/keepalived/keepalived.conf)
/opt/keepalived/sbin/keepalived -f /opt/keepalived/etc/keepalived/keepalived.conf

##防火墙配置
#放行keepalived主备检测
firewall-cmd --permanent --add-protocol=vrrp
firewall-cmd --reload
#放行LVS处理转发的端口
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload

#运行keepalived后,keepalived会自动添加LVS集群规则,可以通过如下命令验证查看集群规则
ipvsadm -Ln

4. 集群测试

1)负载均衡测试

客户端访问 VIP 观测是否实现负载均衡

1
curl http://192.168.60.100:80

2)LVS 服务器故障恢复主备切换测试

把 LVS1 的 keepalived 停掉后观测是否还能正常访问

1
2
ps -ef | grep keepalived
kill -9 进程号

然后在 LVS2 上通过 ip addr 命令查看是否发生 VIP “飘移”

3)真实服务器健康检查测试

关闭 Real Server1 的 Nginx 后观测是否不再转发到 Real Server1,再启动 Real Server1 的 Nginx 观测是否恢复转发到 Real Server1。

1
2
3
4
5
6
7
8
9
#在Real Server1上关闭nginx
docker stop nginx
#在任意一台LVS服务器上(如LVS1)执行如下命令查看是否自动移除Real Server1真实服务器配置规则
ipvsadm -Ln

#在Real Server1上启动nginx
docker start nginx
#在任意一台LVS服务器上(如LVS1)执行如下命令查看是否自动增加Real Server1真实服务器配置规则
ipvsadm -Ln


----------- 本文结束 -----------




如果你觉得我的文章对你有帮助,你可以打赏我哦~
0%