1,LVS介绍:

LVS是Linux Virtual Server的缩写,翻译过来的话,是linux 虚拟服务器,但是这个虚拟机没什么关系,他是用作负载均衡,软负载的解决方案之一,既然有"软件方案",那么肯定有对应的"硬件方案",但是,硬件方案所需的成本比较高,我们需要购买特定的负载均衡硬件设备,以达到负载均衡的目的,比较知名的负载均衡硬件设备厂商有F5、Citrix等,但是硬件方案并不是此处讨论的重点,我们了解即可。而能够实现负载均衡之目的软件也不只有LVS一种,我们也可以通过nginx、haproxy等软件实现负载均衡的目的。

2,LVS 负载均衡模式

LVS 负载均衡有三种模式可供选择,下面我们来了解一下这三个模式的原理:

1)NAT(网络地址转换)模式(生产环境几乎不用):

NAT(Network Address Translation)是一种外网和内网地址映射的技术。每台Real Server的网关将是LVS服务器的地址,用户请求的数据进出都要经过LVS(所以它容易成为瓶颈)。当LVS服务器收到用户请求时会进行目标地址转换(DNAT),将请求IP修改为后端Real Server的IP,此时客户端IP不变,目标IP是VIP。Real Server响应用户请求时,需要再让LVS做源地址转换(SNAT),将返回的数据包源地址改为VIP。此时目标IP是客户端IP,而源IP是VIP,可以正常响应客户端请求。而对客户端来说仿佛是LVS进行的响应,无法感知到后端Real Server的存在。

 

 

 

 

如上图所示,客户端的请求会发往LVS主机,此时,客户端请求报文的源IP为CIP,目标IP为LVS的VIP,当LVS收到客户端的请求报文时,会将请求报文中的目标IP修改为后端某个RealServer的RIP,就以上图为例,当LVS收到客户端的请求报文时,会将报文中的VIP修改为RIP1或者RIP2,具体将VIP修改为哪个RealServer的RIP,取决于LVS使用的具体算法,最好理解的负载均衡算法就是轮询算法了,用大白话说,轮询算法就是如果这次将报文的目标IP修改为RIP1,那么下次就将目标IP修改为RIP2,再下次就再将目标IP修改为RIP1,以此类推,当然,除了轮询算法,还有很多别的算法可供我们选择,但是此处我们暂时先不考虑这么多,当客户端请求报文的目标IP被修改为对应的RIP后,请求报文的源IP为CIP,目标IP已经改为RIP,那么报文自然会被LVS转发到对应的RealServer中,当RealServer收到对应的请求报文时,会发现报文的目标IP就是自己的RIP,于是就会接收报文,处理后进行响应,因为RealServer收到请求报文时,源IP为CIP,目标IP为RIP,所以RealServer在进行响应时,响应报文的源IP则为RIP,目标IP则为CIP,但是CIP对于RealServer来说肯定不在一个网络内,因为CIP是一个公网IP,所以,我们要将所有RealServer的网关指向DIP,当RealServer产生响应报文时,会将响应报文发往网关DIP,而DIP就是LVS的内网IP,当LVS收到对应的响应报文时,响应报文的源IP为RIP,目标IP为CIP,此时,LVS会将响应报文的源IP修改为VIP,修改后的响应报文的源IP为VIP,目标IP为CIP,于是响应报文被发往客户端,客户端则会收到响应报文,其实上述整个过程是一个DNAT的过程,所以,此种LVS模型被称之为LVS-NAT模型。

NAT模式的集群节点需要跟director在同一网络;RIP通常是私有地址,仅用于各集群节点间的通信;RealServer的网关应该指向DIP;支持端口映射(转发);用户发起的请求由调度器向Real Server提交,Real Server再把数据经过调度器传给用户。相比DR模式的话,这样安全性高,但是效率低,瓶颈会出现在调度器上,生产环境几乎不用。

 

2)DR(直接路由)模式(生产环境中使用最多的):

客户端请求依然由LVS接受,但是最终数据包由Real Server传输给用户,不再经过LVS转发,避免了NAT模式的瓶颈问题。DR模式的工作过程比较复杂:

当用户发起请求时,源地址是客户端IP,目标地址是VIP;而LVS调度器将请求转发给Real Server处理后再发送给用户,这个时候源IP是RIP,目标地址是客户端IP,但是客户端一开始并没有请求RIP,而用RIP去响应请求时CIP是不会接受的,所以就需要用VIP响应请求。在DR模式下LVS和Real server都需要配备一样的VIP(VIP的MAC地址和物理网卡是一样的)(Real Server通过将VIP绑定在loopback实现)。由于一个网段内多台服务器出现同样IP地址会引起冲突,所以要在LVS服务器上设置一个VIP一个DIP,而每个Real Server也有一个RIP和一个VIP,并且将Real Server的VIP地址做了隐藏和ARP抑制,不会应答广播,只在响应CIP时作为源地址使用。当产生请求时LVS将目标MAC地址修改为某台Real Server的MAC,该包就会被转发到相应的Real Server处理,此时源IP和目标IP都没变。Real Server收到LVS转发来的包时发现MAC是自己的,IP也是自己的,于是这个包被合法地接受。当Real Server返回响应时,只要直接向CIP返回即可,不再经过LVS。 

 

 RealServer推荐使用公网IP;RealServer的网关地址不能指向DIP;RealServer和调度器需要在同个物理网络(同个机房),DIP和RIP应该在同一网段;入站数据经过调度器转发到RealServer,出站数据由RealServer直接发给客户端,不再经过调度器;不能做端口转发。

 

3)TUN隧道模式:

也叫作隧道模式,构建和DR模式一样,相比DR模式服务器间可以不在同一个网络,可以实现异地传输,但是RealServer需要支持隧道功能。

这个模式比较少用,所以暂时忽略,以后有用到了再加上。

3,LVS的安装及常用操作:

1)安装:

LVS由两部分组成,ipvs与ipvsadm

ipvs是与netfilter结合在一起使用的,2.4.X版本以后的内核中,ipvs作为netfilter的模块存在。

ipvsadm是ipvs的管理工具,相当于iptables 和 netfilter关系一样。

既然上面讲过ipvs已经作为linux内核的一部分,我们直接安装管理工具即可对ipvs规则的操作,下面是安装方式:

最简单的方式就是yum 安装:

直接运行下面的命令即可完成安装:

yum install ipvsadm -y

完成后我们可以使用一下命令尝试查看是否安装成功和查看是否有规则已经存在:

ipvsadm -ln
[root@nginxhost ~]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.56.135:9999 rr
  -> 192.168.71.3:8601            Masq    1      0          0         
  -> 192.168.71.3:8602            Masq    1      0          0         
[root@nginxhost ~]# 

我这里已经有了 规则,但是你的里面不一定有。只要出现server version的字样表名安装成功可以使用了。

源码安装请参考:http://www.linuxe.cn/post-192.html

2)保存规则及恢复规则

添加完规则后,重启服务器后,这些规则就会消失,怎么能让他们永久存在呢,下面我们来介绍小保存规则的命令:

centos6使用下面的命令:

service ipvsadm save  # 此命令会将规则保存在/etc/sysconfig/ipvsadm文件中

重启后可以使用下面命令重新加载使之重新生效:

service ipvsadm reload

除了使用上述方法,还能够使用如下方法,将LVS规则保存于指定的文件中,比如保存LVS规则到 /testdir/lvsrules文件中。

ipvsadm -S > /testdir/lvsrules

重载:

ipvsadm -R < /testdir/lvsrules

centos7可以使用 -S -R 的办法来保存规则和重载规则

3)命令选项解释

-A:增加LVS的VIP记录
-a:增加real server记录
-E:修改LVS记录
-e:修改real server列表信息
-D:删除一条LVS记录
-d:删除real server列表信息
-R:恢复虚拟服务器规则
-S:保存虚拟服务器规则,或者server  ipvsadm  save,和iptables一样
ipvsadm -Sn > /root/lvsrules.txt  #保存规则
cat /root/lvsrules.txt | ipvsadm -R  #恢复规则
-C:清除虚拟服务器列表所有记录
-L:显示列表信息,和iptables一样
-t | u:指定LVS提供tcp或者是udp服务,后面常跟选项 real-server-ip:port或者virtual-server-ip:port
-s:指定LVS的负载调度算法,后面接详细的调度算法,如-s  rr | wrr | lc | wlc,不指定的话默认是wlc
-p  [timeout]:指定一个服务持续时间,用于会话保持,当同个用户重复请求时,给同一个real server处理,默认是300秒
-r:指定real server的ip地址
-i:LVS工作在隧道模式下
-m:LVS工作在NAT模式下
-g:LVS工作在DR模式下
-w:指定real server的权重
-n:不进行dns解析

 

4,调度算法:

大方向上分为动态和静态两种调度算法,静态算法是当用户连接进来后,按设置的算法进行处理,不会判断后端服务器的繁忙情况,而动态算法则会判断后端服务器繁忙状态,然后酌情调度

1)、静态算法详细分类
轮询调度(RR):轮流分配请求,不管服务器繁忙程度
加权轮询(WRR):后端服务器配置越好,分配到的请求越多,权重设置比较敏感。如A、B两台服务器,A的权重为1,B的为10,那么当B要处理了10个用户请求后才会分配让A处理一个
目标地址散列(DH):同一IP过来的请求永远分配给同一个Real Server,这样可以利用缓存加速

源地址散列(SH)

2)、动态算法详细分类:
最小连接(LC):当客户端发起请求时调度器会计算后端服务器的开销,将请求转发给开销小的服务器。计算公式:活动链接数x256+非活动连接数
加权最小连接(WLC):默认算法,也是使用最多的算法,计算公式:(活动链接数x256)/权重+非活动连接数
还有其他的一些补充算法,如最短期望延迟(SED)、最小队列调度(NQ)、基于局部的最小连接(LBLC)、带复制的基于局域的最小连接(LBLCR),可以网上查询具体含义。

5,地址类型说明

VIP:虚拟IP,并不是提供真实服务的IP,而是通过这个IP转发到后方

DIP:LVS服务器本身的IP,通过这个IP和RIP连接,DIP通常和Real Server的IP在一个网段

RIP:真实服务器的IP地址

CIP:客户端请求时用户的IP

6,ipvs在netfilter中所处的位置

 

 当客户端访问服务时,会访问VIP+端口,所以,客户端的请求报文会发往调度器,请求报文会先经过PREROUTING链,然后进行路由判断,由于此刻报文的目标IP为VIP,而VIP对于调度器来说,就是本身的IP,所以报文会经过INPUT链,此刻,如果IPVS发现报文访问的VIP+端口与我们定义的LVS集群规则相符,ipvs则会根据定义好的规则与算法,将报文直接发往POSTROUTING链,然后报文则会发出,最后到达后端的RealServer中。

6,NAT和DR模式实验:

NAT实验:

实验环境准备:

CIP 192.168.0.142

VIP 192.168.56.135

DIP 192.168.71.4

RIP 192.168.71.3

其VIP和DIP是在一台机器上的不同网卡,71.0 网段的都属于内网,我这里没有公网地址,所以就用两个处于不同网段的机器扮演lvs server和real server, 其中lvs server 包含两张网卡,地址分别是VIP 和 DIP,CIP是我的物理机的局域网ip地址,lvs server和 real server 都是vbox虚拟主机,并且都是host-only模式的 

路由配置:

lvs server 一开始就可以ping 通 real server, 所以这里不需要配置,

real server 一开始不能ping通 lvs 的192.168.56.135  这个IP地址,所以我们需要添加一个路由条目

route add -host 192.168.56.135 gw 192.168.71.4

这样再次ping 192.168.56.135时就能ping通了,其中我们得提前关闭lvs server 和real server的防火墙 和开启lvs  server 内核的地址转发功能。

sysctl -w net.ipv4.ip_forward=1

现在准备工作已经做完了,开始添加lvs规则;

我在real server上起了两个springboot 服务端口号分别是8601,8602

ipvsadm -A -t 192.168.56.135:9999 -s rr
ipvsadm -a -t 192.168.56.135:9999 -r 192.168.71.3:8601 -m
ipvsadm -a -t 192.168.56.135:9999 -r 192.168.71.3:8602 -m

添加完成后我们查看下:

[root@nginxhost conf]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.56.135:9999 rr
  -> 192.168.71.3:8601            Masq    1      0          0         
  -> 192.168.71.3:8602            Masq    1      0          0         
[root@nginxhost conf]# 

现在我们可以尝试在lvs server上访问http://192.168.56.135:9999试试

[root@nginxhost conf]# curl http://192.168.56.135:9999
i am 8601[root@nginxhost conf]# curl http://192.168.56.135:9999
i am 8602[root@nginxhost conf]# curl http://192.168.56.135:9999
i am 8601[root@nginxhost conf]# curl http://192.168.56.135:9999
i am 8602[root@nginxhost conf]# curl http://192.168.56.135:9999
i am 8601[root@nginxhost conf]# curl http://192.168.56.135:9999
i am 8602[root@nginxhost conf]# 

下面我们通过物理机的浏览器试试,

 

 这是发现不能访问,目前我也不知道为什么不能访问,有知道的朋友可以帮我看看,万分感谢,这种办法不行,我想到既然可以在lvs 正常访问,我们是不是可以做lvs的反向代理来解决这个问题,下面是解决办法:

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;


    server {
        listen       8999;
        server_name  192.168.56.135;

        location / {
            proxy_pass http://192.168.56.135:9999;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

    }
}

让8999 端口代理192.168.56.135:9999,再次尝试用物理主机的浏览器去尝试访问。

 

 可以访问了

至此,我们可以看到lvs成功完成了负载均衡,虽然有些问题现在还不明白为什么,但是还是解决了正常访问的问题,这就是NAT 模式

DR实验:

先说说什么是arp抑制,在以太网通信 过程中我们实际上用的是mac地址来通信的,而我们在访问某一主机是用的是ip地址,那网络中怎么通过IP地址找到相应的mac地址呢,这就是arp广播,ARP广播会被所有局域网中的和通过路由器连接的不同局域网中的主机收到,然后回复自己的mac地址给需要的主机,而我们每台电脑都有一张ARP映射表,其中记录了ip地址和mac地址的对应关系,可以通过arp -a命令查看,那什么是arp抑制呢,其实就是主机1在询问主机2 的mac地址时,主机2 不做应答,上面的DR模式中已经介绍过,real server都会有vip并且将其绑定在lo网卡上,只会响应目标地址是vip的请求,下面我们来看看怎么配置arp抑制:

echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

其中也可以配置在/etc/sysctl.conf中,来永久生效。

以下是响应级别解释:

arp_ignore(接收到ARP请求后的响应级别):
0:本地所有网卡中,如果有对应的IP地址就会响应请求
1:只会响应目标IP为接收网卡所配置的IP地址的请求。以此实现后端服务器回环地址上的IP不去响应广播

arp_announce(向外回应自己网络地址):
0:本地所有网卡上的IP地址都可以向外响应
1:尽量使用与本地网卡所匹配的地址向外响应
2:只使用与本地接口匹配的网络地址向外响应,效果和arp_ignore类似也实现了避免响应

lvs server 配置:

准备三台机器,host-only模式及可,连接同一虚拟网卡

1, lvs server 192.168.56.135

2, real server 192.168.56.4

3, real server 192.168.56.5

 分别关闭三台主机的防火墙,selinux,清空iptables

iptables -F
setenforce 0
systemctl stop firewalld

real server 192.168.56.4 配置

绑定vip到lo网卡,并设置到VIP的路由

ip a a 192.168.56.200/32 dev lo
route add -host 192.168.56.200 dev lo

 

修改/etc/sysctl.conf 文件,抑制ARP

内容如下:

net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.default.arp_ignore = 1
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2

启动服务进程:

nohup java -jar nginxtest-0.0.1-SNAPSHOT.jar --server.port=9000 &

real server 192.168.56.5,参照192.168.56.4配置即可

lvs server 192.168.56.135 配置:

ip a a 192.168.56.200/24 dev enp0s3
ipvsadm -A -t 192.168.56.200:9000 -s rr
ipvsadm -a -t 192.168.56.200:9000 -r 192.168.56.4:9000 -g
ipvsadm -a -t 192.168.56.200:9000 -r 192.168.56.5:9000 -g

测试,进入宿主机,打开浏览器:输入http://192.168.56.200:9000

 

 以上就是lvs的NAT和DR模式,其中ipvsadm 的命令其实不难,难点在于网络部分,

 

 

 

 

 

 

 

 

 

 

 

 

参考文档:

http://www.zsythink.net/archives/2185

http://www.linuxe.cn/post-178.html

https://www.cnblogs.com/lyqlyqlyq/p/11641875.html

 

posted on 2021-01-06 10:25  EZgod  阅读(3129)  评论(0编辑  收藏  举报