在Linux配置LVS实现负载均衡

发布时间 2023-04-05 18:36:46作者: 我有八千部下

前言

这篇主要是讲LVS配置来实现负载均衡,步骤非常简单,只不过为了解释配置的目的增加了一些文字解释,而显得内容很多。

LVS(Linux Virtual Server)是章文嵩博士成立的自由软件项目。Linux将其作为内核的一部分,命名为IPVS(IP Virtual Server)。

配置简介

在一台作为负载均衡服务器DS(Director Server)上绑定VIP(Virtual Internet Protocol)并配置IPVS,客户端通过VIP来访问这台服务器。

IPVS中配置映射N个处理请求真实服务器(Real Server)的IP地址RIP(Real Internet Protocol),指定合适的负载均衡算法(如随机、加权轮询等),DS会根据算法规则将客户端的数据包转发到其中1台RS处理。

在这个调用链路中DS只负责转发数据包,网络连接实际上是建立在客户端与RS上的,只不过对客户端来说RS是透明,不知道它的存在,客户端只需要统一访问DS就可以了。

我们通过三台服务器来搭建一套负载均衡服务,使用三种模式(DR、NAT、TUN)中性能最好的直接路由模式(Direct Routing),响应结果由RS直接返回给客户端,VIP为192.168.252.100。

下面是三个服务器节点信息:

  • node1(DS):IP为192.168.252.131

  • node2(RS):IP为192.168.252.132

  • node3(RS):IP为192.168.252.133

下图是在这套环境下,数据传输链路:

image-20211122144516619

搭建步骤

这些步骤操作结果都是临时的,重启会消失,如果想复原不需要手动清除,文后有相关步骤的持久化配置方式。

查看网卡信息

查看服务器网卡信息,一般会有物理的网卡(如ens33或eth0)和虚拟回环网卡(lo,Local Loopback)。

ifconfig

image-20211119115200199

配置真实服务器(RS)

要注意的是,要先改ARP配置,再配置VIP,不然有可能会在配置ARP之前暴露VIP地址。

  • 修改内核地址解析协议(Address Resolution Protocol,ARP)内核参数映射文件让其他网卡不暴露VIP,保证VIP对内(本机)可见,对外隐藏
echo "给ens33网卡接口配置" > /dev/null
echo 1 > /proc/sys/net/ipv4/conf/ens33/arp_ignore 
echo 2 > /proc/sys/net/ipv4/conf/ens33/arp_announce 

echo "为了方便,给所有网卡接口配置" > /dev/null
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore 
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

arp_ignore配置收到ARP请求的响应级别,我们设置成1,这样网卡只会响应跟自己接口匹配的地址,外界无法通过它们获得VIP的地址:【0】(默认)本机有相应配置就给予响应;【1】只响应与接口匹配的地址,如果请求本机其他接口的MAC地址会忽略。

arp_announce配置地址通告级别。我们设置成2,这样只会向匹配的网络(同一网段)通告自己的地址,而不会通告VIP的地址:【0】将本地所有接口的地址向外通告;【1】向相匹配的网络通告本地所有与其相匹配的接口地址【2】向相匹配的网络通告自己的接口地址。

地址是指MAC地址,同一局域网是通过MAC地址来访问的,本地ARP缓存中会记录IP对应的MAC地址。

  • 我们对虚拟环回网卡配置子接口,绑定VIP,并设置掩码为255.255.255.255,让RS能处理请求并能直接返回
ifconfig lo:2 192.168.252.100 netmask 255.255.255.255

image-20211122143916518

为什么RS也要绑定VIP?因为DS传过来的数据包的目标IP地址是VIP,想使RS让能处理这个数据包就得有IP相匹配的网卡接口,否则数据包会被丢弃。

为什么绑定在虚拟环回网卡上而不是真实网卡?最终目的是让外界不知道RS这个VIP的存在,让他们无法直接通过VIP来访问RS,否则就会和DS冲突。因为环回网卡是虚拟网卡,没有对外通信的通道,它本身不会将VIP对应的MAC地址广播给外界,外界也无法直接向它发送ARP请求来获得MAC地址,这样就保证了对外隐藏。不过还需要修改内核ARP配置,防止其他网卡将VIP暴露出去。

为什么网掩码是255.255.255.255?如果设置成物理网卡一样为255.255.255.0会导致数据包发不出去成死循环。以node2服务器配置为例,下图是路由表信息,配置的接口为物理网卡ens33。往外发数据包的流程是拿数据包目的地IP地址与掩码做按位与运算,比如目的地IP为192.168.255.22,与255.255.255.0的运算结果为192.168.255.0,路由表有想匹配的规则发到网关0.0.0.0,最终数据包走0.0.0.0相匹配的网关192.168.252.2发出去。如果环回接口VIP也配置为255.255.255.0,会导致走环回接口也能这样出去,而且环回接口优先级高所以一定会走它,但环回接口是内核虚拟接口,发出去包会当成接收到的包,最后成死循环。如果配置成255.255.255.255,与运算结果为192.168.255.22,匹配不上网关转而交给其他网卡处理,这样就能正常发出去了。

image-20211122141645062

配置负载均衡服务器(DS)

配置VIP,创建物理网卡的子网卡命名为ens33:2,绑定我们的VIP,指定掩码为255.255.255.0。

ifconfig ens33:2 192.168.252.100/24

安装ipvsadm来配置IPVS,命令ipvsadm -help可以看到各选项作用。

echo "安装ipvs管理工具" > /dev/null
yum install ipvsadm -y

echo "添加(-A)TCP(-t)虚拟服务,指定IP和端口号分别为VIP和80,指定负载均衡算法(-s)为轮询(rr)" > /dev/null
ipvsadm -A -t 192.168.252.100:80 -s rr

echo "为上面的虚拟服务添加真实服务地址(-r),使用DR模式(-g),并指定权重(-w)" > /dev/null
ipvsadm -a -t 192.168.252.100:80 -r 192.168.252.132 -g -w 1
ipvsadm -a -t 192.168.252.100:80 -r 192.168.252.133 -g -w 1

echo "查看IPVS配置" > /dev/null
ipvsadm -ln

image-20211119170033136

测试

给RS安装httpd

安装启动httpd。

echo "安装" > /dev/null
yum -y install httpd

echo "启动" > /dev/null
service httpd start

给两台RS(node2、node3)分别指定httpd主页内容,测试时好区分。

echo 'node2' > /var/www/html/index.html

通过浏览器验证

通过浏览器访问VIP(http://192.168.252.100/)可以看到结果在两个节点间切换。不过浏览器GET请求可能有缓存,导致多次请求实际只发了一次,如果没有切换就间隔几秒,等缓存过期。

image-20211119171700722

image-20211119172725974

查看IPVS连接记录

在DS上查看连接记录,可以看到请求轮询转发到了RS。

echo "列出(-l)当前IPVS连接记录(c),显示数值型的(n)目标服务(virtual)和真实服务(destination)地址" > /dev/null
ipvsadm -lcn

image-20211119174312324

查看socker连接

查看各节点socket连接信息。可以发现TCP连接都建立在RS上,没有与DR建立连接。参考菜鸟教程 - Linux netstat命令

netstat -natp

image-20211119175759873

image-20211119175819192

其他相关操作

  • 保存IPVS规则到文件,不然重启规则就丢失了
ipvsadm -S > ~/IPVS

image-20211119181524832

  • 清空IPVS规则
ipvsadm -C
  • 加载文件中的IPVS规则
ipvsadm -R < ~/IPVS
  • RS修改内核地址解析协议(Address Resolution Protocol,ARP)让其他网卡不暴露VIP。修改/etc/sysctl.conf可以永久生效
echo "追加ARP配置到/etc/sysctl.conf" > /dev/null
echo '
net.ipv4.conf.ens33.arp_ignore=1
net.ipv4.conf.ens33.arp_announce=2

net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2' >> /etc/sysctl.conf

echo "刷新配置"
sysctl -p
  • 通过cat命令可以查看内核地址协议配置结果。
cat /proc/sys/net/ipv4/conf/ens33/arp_ignore 
cat /proc/sys/net/ipv4/conf/ens33/arp_announce 
cat /proc/sys/net/ipv4/conf/all/arp_ignore 
cat /proc/sys/net/ipv4/conf/all/arp_announce
  • 关闭网卡
ifconfig lo:2 down
  • 查看路由表条目
route -n

image-20211122115258100

  • 查看ARP缓存,从node1执行结果中可以看到node2和node3的IP地址对应的MAC地址,同一局域网内是通过MAC地址寻址的
arp -an

image-20211122115559435

参考链接

菜鸟教程 - Linux netstat命令