查看原文
其他

LVS 3种工作模式实战及Q&A!

肖邦Linux DevOps技术栈 2022-11-10

作者:肖邦Linux
博客地址:https://blog.csdn.net/liwei0526vip


通过上一篇的内容我们大概对 LVS 有了直观认识,理解了 LVS 的一些基本工作原理。这篇文章通过实践操作的方式,搭建实际测试环境,一步一步配置 LVS 的几种模式。

上一篇:LVS 工作原理图文讲解,非常详细!


我们知道 LVS 工作模式有 DR、NAT、Tunnel 模式,这篇文章中会针对每个模式进行实践操作,通过实验来更深入理解工作原理。我们需要至少 4 台服务器来进行模拟实验。

  • 操作系统:CentOS release 6.5 (Final)

  • 内核版本:2.6.32-754.15.3.el6.x86_64

  • 相关服务器:1 台客户端服务器,1 台负载均衡服务器,2 台后端真实服务器(模拟负载均衡调度)

注:为了简单,我的几台服务器都是在都一个二层网络,如果有条件的话可以模拟更逼真一些。


再了解下本章用到的两个组件:


  • IPVS。LVS 是基于内核态的 netfilter 框架实现的 IPVS 功能,工作在内核态。那么用户是如何配置 VIP 等相关信息并传递到 IPVS 呢,就需要用到了 ipvsadm 工具。

  • ipvsadm 工具。ipvsadm 是 LVS 用户态的配套工具,可以实现 VIP 和 RS 的增删改查功能。它是基于 netlink 或 raw socket 方式与内核 LVS 进行通信的,如果 LVS 类比于 netfilter,那么 ipvsadm 就是类似 iptables 工具的地位。


一、DR 模式操作实践

1.1 实验环境

客户端:10.211.102.46

负载均衡:VIP=10.211.102.47 DIP=172.16.100.10

后端1:172.16.100.20

后端2:172.16.100.30


1.2 载均衡服务器配置

安装 ipvsadm 工具:

$ yum install ipvsadm


配置vip服务:


$ vim lvs_dr.sh
# 内容如下:
vip=10.211.102.47
rs1=172.16.100.20
rs2=172.16.100.30
/sbin/ipvsadm -C # 清除原有规则
/sbin/ipvsadm -A -t $vip:8088 -s rr # 添加vip:8088的tcp服务
/sbin/ipvsadm -a -t $vip:8088 -r $rs1:8088 -g # 添加rs1服务器
/sbin/ipvsadm -a -t $vip:8088 -r $rs2:8088 -g # 添加rs2服务器

# 执行脚本
$ /bin/bash lvs_dr.sh


查看服务配置情况:


$ ipvsadm -ln -t 10.211.102.47:8088
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.211.102.47:8088 rr
-> 172.16.100.20:8088 Route 1 0 0
-> 172.16.100.30:8088 Route 1 0 0


1.3 后端服务器配置

后端服务器需要安装 nginx 服务:

# 安装 nginx 启动并侦听 8088 端口
$ yum install nginx

# rs 配置 lo 和其它内核参数
$ vim rs_dr.sh # 内容如下:
vip=10.211.102.47
ifconfig lo:0 $vip broadcast $vip netmask 255.255.255.255 up
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce


执行脚本:


$ /bin/bash rs_dr.sh
$ ifconfig lo:0 # 查看rs的lo:0接口配置信息
lo:0 Link encap:Local Loopback
inet addr:10.211.102.47 Mask:255.255.255.255
UP LOOPBACK RUNNING MTU:16436 Metric:1


注:这些步骤需要在两个 RS 上都进行相关操作。


1.4 测试

上述所有步骤执行完毕后,如果一切都顺利的话,执行测试命令会出现如下结果:

$ curl 10.211.102.47:8088
hello from rs1...
$ curl 10.211.102.47:8088
hello from rs2...


实验成功!两次请求分别被调度到了两台的后端服务器上了。感兴趣的话,在后端服务器上抓包观测实际数据包的各个字段是否符合预期。


1.5 常见问题


通过上述步骤,完成最简单的 DR 模式配置。在负载均衡服务器上配置的信息容易理解,而在后端服务器上配置了 lo 和内核参数,下边以问题的方式来解释清楚这些含义。


Q:为什么需要在 lo 接口配置 vip ?

A:我们知道如果服务器收到的数据包 IP 地址不是本机地址(没开启转发模式),就会丢弃。后端服务器收到 DR 模式的数据包,此时目标 IP 是 VIP,服务器会认为此数据包不是发送给本机的,会丢弃。而我们在 lo 接口上配置 VIP 后,服务器就能够正常接收此数据包,发送给相应的应用程序了。因此,在 lo 上配置 vip 能够完成接收数据包并将结果返回给 client。


Q:为什么需要配置 arp_ignore 参数?

A:我们在 lo 上配置了 vip,正常情况下,其它设备发送 vip 的 arp 请求时,除了负载均衡设备会响应 arp 请求之外,后端服务器也会响应 vip 的 arp 请求,这样请求设备不知道哪个是准确的了,反正就是乱了。我们在参数中配置 arp_ignore=1 之后,后端服务器只会响应目的 IP 地址为接收网卡上的本地地址的 arp 请求。由于 vip 配置了在 lo 上,所以其它接口收到相关的 arp 请求都会忽略掉,这样保证了 arp 请求正确性。这也说明了为什么 vip 必须配置在 lo 接口上而不是其它接口上了。


Q:为什么需要配置 arp_announce 参数?

A:当后端服务器向客户端发送响应数据包时,源地址和目的地址确定,通过目标地址查找路由后,发送网卡也是确认的,也就是源 MAC 地址是确认的,目的 MAC 地址还不确定,需要获取下一跳 IP 对应的 MAC 地址,就需要发送 arp 请求了。发送的 arp 请求目的 IP 就是下一跳的地址,而源 IP 是什么呢?系统通常默认会取数据包的源 IP 作为 arp 的源 IP。我们认真想一下,源 IP 不就是 VIP 么,假设以 VIP 为源 IP 发送 arp 请求,那下一跳(路由器)学习到的 MAC 地址和 IP 地址对应关系就会错乱,因为负载均衡设备上的 VIP 对应的 MAC 地址肯定与这个不同,导致整个系统 arp 紊乱。

而我们配置参数 arp_announce=2 后,操作系统在发送 arp 请求选择源 IP 时,就会忽略数据包的源地址,选择发送网卡上最合适的本地地址作为 arp 请求的源地址。


二、NAT 模式操作实践


2.1 实验环境

客户端:10.211.102.46

负载均衡:VIP=10.211.102.47 DIP=172.16.100.10

后端1:172.16.100.20

后端2:172.16.100.30


2.2 负载均衡服务器配置

安装 ipvsadm 并执行相关配置:

$ yum install ipvsadm
$ vim lvs_nat.sh # 内容如下
echo 1 > /proc/sys/net/ipv4/ip_forward
vip=10.211.102.47
rs1=172.16.100.20
rs2=172.16.100.30
/sbin/ipvsadm -C
/sbin/ipvsadm -A -t $vip:8088 -s rr
/sbin/ipvsadm -a -t $vip:8088 -r $rs1:8088 -m
/sbin/ipvsadm -a -t $vip:8088 -r $rs2:8088 -m

# 执行脚本
$ /bin/bash lvs_nat.sh


查看服务配置信息:


$ ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.211.102.47:8088 rr
-> 172.16.100.20:8088 Masq 1 0 0
-> 172.16.100.30:8088 Masq 1 0 0


2.3 后端服务器配置

后端服务器安装和配置如下:

$ yum install nginx # 安装 nginx,启动并侦听 8088 端口
# vim rs_nat.sh # 如下内容
route add default gw 172.16.100.10 dev eth0 # 默认网关配置为负载均衡的 DIP

# 执行脚本(两个rs都需要执行)

$ /bin/bash rs_nat.sh


2.4 测试

上述所有步骤执行完毕后,如果一切都顺利的话,执行测试命令会出现如下结果:

$ curl 10.211.102.47:8088
hello from rs1...
$ curl 10.211.102.47:8088
hello from rs2...


实验成功!两次请求分别被调度到了两台的后端服务器上了。感兴趣的话,在后端服务器上抓包观测实际数据包的各个字段是否符合预期。


2.5 常见问题


Q:在后端服务器为何要设置默认网关指向负载均衡设备?

A:由于 NAT 模式是双向流量都经过 LVS 设备,所以后端服务器需要将响应报文发送给 LVS 设备,不过此时的数据包目的 IP 是客户端的 IP,可能是外网的任何一个网段,需要通过设置路由的方式,将数据包转发给 LVS ,因为不可能穷举所有的网段地址,所以必须要设置默认的网关来指向 LVS。最后也要强调一下,负载均衡设备需要开启 ipv4 的 forward 参数。

三、Tunnel 模式操作实践

3.1 实验环境

客户端:10.211.102.46

负载均衡:VIP=10.211.102.47 DIP=172.16.100.10

后端1:172.16.100.20 ,注,rs 与 DIP 可以不在一个网段,只要三层通就行。

后端2:172.16.100.30


3.2 负载均衡服务器配置

安装 ipvsadm 并执行相关配置:

$ yum install ipvsadm
$ vim lvs_tunnel.sh # 内容如下
vip=10.211.102.47
rs1=172.16.100.20
rs2=172.16.100.30
/sbin/ipvsadm -C
/sbin/ipvsadm -A -t $vip:8088 -s rr
/sbin/ipvsadm -a -t $vip:8088 -r $rs1:8088 -i
/sbin/ipvsadm -a -t $vip:8088 -r $rs2:8088 -i

## 执行脚本
$ /bin/bash lvs_tunnel.sh


查看服务配置信息:


$ ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.211.102.47:8088 rr
-> 172.16.100.20:8088 Tunnel 1 0 0
-> 172.16.100.30:8088 Tunnel 1 0 0


3.3 后端服务器配置

后端服务器安装和配置如下:

$ yum install nginx # 安装 nginx,启动并侦听 8088 端口
# vim rs_tunnel.sh # 如下内容
vip=10.211.102.47
modprobe ipip
ifconfig tunl0 $vip broadcast $vip netmask 255.255.255.255 up
echo "0" > /proc/sys/net/ipv4/ip_forward
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
echo "0" > /proc/sys/net/ipv4/conf/all/rp_filter
echo "0" > /proc/sys/net/ipv4/conf/tunl0/rp_filter

# 执行脚本(两个rs都需要执行)
$ /bin/bash rs_tunnel.sh


3.4 测试

上述所有步骤执行完毕后,如果一切都顺利的话,执行测试命令会出现如下结果:

$ curl 10.211.102.47:8088
hello from rs1...
$ curl 10.211.102.47:8088
hello from rs2...


实验成功!两次请求分别被调度到了两台的后端服务器上了。感兴趣的话,在后端服务器上抓包观测实际数据包的各个字段是否符合预期。


3.5 常见问题


Q:为何需要设置 rp_filter 参数?

A:默认 rp_filter 参数设置为 1,Linux 会反向校验源 IP 的路由,如果源和目的 IP 路由出口不是一个网卡,就会被丢弃。因为数据包到后端服务器物理网卡后会被转发给虚拟网卡 tunl0 接口,这时进入的网卡是 tunl0,而源 IP 的路由出口网卡肯定不是 tunl0,所以数据包会被丢弃。配置 rp_filter 参数为 0,就相当于关闭了这个校验。


四、LVS 的几种调度算法


在上面的一些实验过程中,会发现 ipvsadm 命令最后边的 -s rr ,就表示的是调度算法,其中 rr 就是最简单的轮询调度算法,下边先简单介绍负载均衡 LVS 支持的几种调度算法,其中橙色标注为最常用的。


  • 轮询 rr - 这种算法是最简单的,就是按依次循环的方式将请求调度到不同的服务器上,该算法最大的特点就是简单。轮询算法假设所有的服务器处理请求的能力都是一样的,调度器会将所有的请求平均分配给每个真实服务器,不管后端 RS 配置和处理能力,非常均衡地分发下去。

  • 加权轮询 wrr - 这种算法比 rr 的算法多了一个权重的概念,可以给 RS 设置权重,权重越高,那么分发的请求数越多。实际生产环境的服务器配置可能不同,根据服务器配置适当设置权重,可以有效利用服务器资源。

  • 最少连接 lc - 这个算法会根据后端 RS 的连接数来决定把请求分发给谁,比如 RS1 连接数比 RS2 连接数少,那么请求就优先发给 RS1。

  • 加权最少链接 wlc - 这个算法比 lc 多了一个权重的概念。

  • 基于局部性的最少连接调度算法 lblc - 这个算法是请求数据包的目标 IP 地址的一种调度算法,该算法先根据请求的目标 IP 地址寻找最近的该目标 IP 地址所有使用的服务器,如果这台服务器依然可用,并且有能力处理该请求,调度器会尽量选择相同的服务器,否则会继续选择其它可行的服务器。

  • 复杂的基于局部性最少的连接算法 lblcr - 记录的不是要给目标 IP 与一台服务器之间的连接记录,它会维护一个目标 IP 到一组服务器之间的映射关系,防止单点服务器负载过高。

  • 目标地址散列调度算法 dh - 该算法是根据目标 IP 地址通过散列函数将目标 IP 与服务器建立映射关系,出现服务器不可用或负载过高的情况下,发往该目标 IP 的请求会固定发给该服务器。

  • 源地址散列调度算法 sh - 与目标地址散列调度算法类似,但它是根据源地址散列算法进行静态分配固定的服务器资源。


- END -

推荐阅读:

LVS 工作原理图文讲解,非常详细!

《运维三十六计》:运维生存必备宝典

运维工程师不得不看的经验教训和注意事项

一篇文章全面了解运维监控知识体系

服务器产生大量 TIME_WAIT 状态的排查过程

Nginx 性能优化有这篇就够了!

超全整理!Linux性能分析工具汇总合集

回顾 Kubernetes 最近 6 个版本重点更新

如何画出一张合格的技术架构图?

16 张图带你快速入门 Ansible

30个Linux Shell脚本经典案例(下)

10 个Linux Awk文本处理经典案例

Kubernetes 架构师的进阶之路



年轻时偷的懒,迟早是要还的。点亮

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存