LVS简介

LVS(Linux Virtual Server),即Linux上虚拟的服务器集群系统。其实LVS就是一个前端的负载调度器,它在软件层次上实现了负载均衡,将接收到的请求均衡地转移至多个不同的服务器上运行,用较低的成本实现了将一组服务器构建成高性能、高可用的服务器集群。


LVS由两部分组成ipvsadm和ipvs,ipvsadm工作于用户空间,用于编写集群服务。ipvs工作于内核空间。ipvsadm编写的集群服务交由ipvs来具体实现。ipvs是基于netfilter实现的,它工作在input链上,当有报文经过input链时,ipvs查看其目标IP及请求的端口,若请求的是集群服务,则通过指定的算法在服务器集群中选择一台服务器,然后将报文发送给该服务器。


lvs的术语

Director Server     # 调度器,即实现负载均衡的地方

Real Server           # 正真能够提供服务的服务器

VIP                       # Director上用于接收用户请求的IP

DIP                       # Director上用于和Real Server交互的IP

RIP                       # Real Server上的IP

CIP                       # 客户端IP


ipvsadm配置集群服务

在用ipvsadm配置Director之前,需要先安装ipvsadm。

语法:ipvsadm [options] -t|-u|-f service-address [options]

定义一个集群服务:

ipvsadm -A|-E -t|-u|-f service-address [-s scheduler]

-A    # 添加一个集群服务

-E     # 修改一个集群服务

-s     # 指定调度用的算法

-t|-u     # service-address为VIP:port

-f          # service-address为防火墙标记


向集群服务中添加RS:

ipvsadm -a|e -t|u|f service-address -r server-address [options]

-a                             # 添加一个RS

-e                             # 修改一个RS

service-address       # 已定义过的集群服务

-r                             # 指定RS地址

-w,weight             # 指定该real server的权重,这个设为0表示禁用该realserver。


指定LVS的类型:

-g,--gatewaying         # direct routing(DR模型,默认选项)

-m,--masquerading    # masquerading(NAT模型)

-i,--ipip                       #ipip encapsulation(tun类型)


scheduler(LVS算法)

ipvs在调度时所使用的算法,添加集群服务时通过“-s”指定。一个内置了10种算法(这个由内核中的ipvs代码提供)

[root@CentOS-6 ~]# grep -i 'VS' /boot/config-version

/boot/config-version为当前操作系统内核编译时使用的配置文件,使用这条语句可查看内核当中ipvs的代码支持哪些算法。


静态方法:仅根据算法本身进行调度,不考虑后端服务器的负载

rr       # round robin,轮询

wrr    #  weighted round robin, 加权轮询(根据添加RS时指定的权重进行调度,权重越大,调度

          # 的次数越多)

sh      # source hashing,表示来源于同一个CIP的请求将始终被定向至同一个RS(SESSION保持)

dh:     # destination hashing,只要访问同一个地址,就调度到同一个real server


动态方法:根据算法及各RS当前的负载状况进行调度

lc       # least connection,调度给当前连接数最少的RS

        Overhead=Active*256+Inactive   # Active:活动状态连接数,Inactive:非活动状态连接数。                                                                 # 这个值越小就挑哪个

wlc     # weighted lc,默认使用这种算法,这个更容易保证调度公平

        Overhead=(Active*256+Inactive)/weight      #weight:权重

sed     # shortest expection delay

        Overhead=(Active+1)*256/weight

nq       # Never Queue,现将请求分配给所有的空闲服务器,没有空闲的服务器了之后,再根据sed

           # 算法进行调度

lblc     # Locality-Based Least Connection             

           #适用于后端服务器为缓存服务器的场景,动态的DH,很少用到

lblcr    # Replicated lblc   #带复制功能的lblc


LVS的模型介绍

LVS有4种模型:NAT,DR,tun,fullnat。常用的是前两者。


NAT模型

LVS详解及基于DR模型的案例_LVS


工作原理:Director的DIP和各RIP必须得在同一个网段中且应该使用私有IP,各个Real Server的网关必须指向Director的RIP。Director在接收到客户端请求报文(目标地址VIP,源地址CIP)后,根据算法从后面的集群中选出一台Real Server,将报文的目标IP改成这台Real Server的RIP,然后发送。Read Server在构建响应报文时,源IP为自己的RIP,目标为CIP,发送至Director,Director再将报文的源IP改成VIP发送给客户端。

使用NAT模型的缺点在于请求报文和响应报文都要经过Director,在高负载额场景中,Director很容易成为系统性能的瓶颈。


实现方式

Direcor:

    vip:192.168.1.118

    dip:192.168.2.8

Real Server:

    192.168.2.5

    192.168.2.6

    192.168.2.7

Real Server上:

每个Real server上都配置好默认路由,指向dip

[root@node1 ~]# ip route add default via 192.168.2.8

Direcor上:

集群服务配置:

[root@vm1 ~]# ipvsadm -A -t 192.168.1.118:80 -s rr
[root@vm1 ~]# ipvsadm -a -t 192.168.1.118:80 -r 192.168.2.5 -m
[root@vm1 ~]# ipvsadm -a -t 192.168.1.118:80 -r 192.168.2.6 -m
[root@vm1 ~]# ipvsadm -a -t 192.168.1.118:80 -r 192.168.2.7 -m

确保路由转发功能打开:

[root@vm1 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward


DR模型

LVS详解及基于DR模型的案例_LVS_02

DR模型在实现过程中,VIP、DIP、RIP必须在同一个物理网络中,中间不能有路由器拆分包信息。

DR模型的工作原理与NAT模型的区别在于Director在收到请求报文后没有修改目标地址,而是仅修改了报文的目标MAC地址(为某一台Real Server的MAC地址),直接发送给Real Server。Real Server为了接收这个目标地址为VIP的报文,需要在本地配置一个VIP,这个VIP地址一般配置在lo接口的别名(lo:0)上,这个VIP地址不向外通告,也不响应ARP请求。当发送响应报文时,响应报文不会经过Director,而是直接发往客户端。所以响应报文的目标IP为CIP,源IP为VIP。为了确保源IP为VIP,需要让报文先经过lo:0接口,再由eth0转发出去。


实现方式

路由器1:

    eth0:192.168.1.118

    eth1:192.168.2.8

路由器2:

    eth0:192.168.1.119

    eth1:192.168.2.9

Direcor:

    vip:  eth0:0,192.168.2.100

    dip:  eth0,192.168.2.7

Real Server:

    192.168.2.5

    192.168.2.6


Direcor上:

添加vip

[root@node3 ~]# ip addr add 192.168.2.100/24 label eth0:0 dev eth0
[root@node3 ~]# ip route add 192.168.2.100 dev eth0:0


Real Server上:

在每个Real Server执行(这些可以写成脚本)

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

arp_ignore       # 是否响应ARP地址请求,默认0。

0     # 回复本机的所有ip地址(不管地址在哪里)。

1     # 请求从哪个网卡接口进来,就响应该接口上的地址。

arp_announce  # 限制本机如何通告本地地址,默认0。

通告级别:

0     # 通高所有本机ip地址。

1     # 尽量使用2这个级别,但有时候会有意外。

2     # 仅通知最佳的本地地址进行通告。

       # 例如某个IP地址处在某个网段,那么仅用这个接口的地址通告该网段。


在lo上添加vip

[root@node3 ~]# ip addr add 192.168.2.100/32 label lo:0 brd 192.168.2.100 dev lo
[root@node3 ~]# ip route add 192.168.2.100 dev lo:0


在Direcor上:

添加集群服务

[root@node3 ~]# ipvsadm -A -t 192.168.2.100:80 -s rr
[root@node3 ~]# ipvsadm -a -t 192.168.2.100:80 -r 192.168.2.5 -g
[root@node3 ~]# ipvsadm -a -t 192.168.2.100:80 -r 192.168.2.6 -g
[root@node3 ~]# 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.2.100:80 rr
  -> 192.168.2.5:80               Route   1      0          0         
  -> 192.168.2.6:80               Route   1      0          0

最后Director上不要忘了网关的配置。


基于LVS-DR模型部署discuz

LVS详解及基于DR模型的案例_LVS_03

实验环境:

路由器:

    eth0:192.168.1.118

    eth1:192.168.2.8

Direcor:

    vip:  eth0:0,192.168.2.100

    dip:  eth0,192.168.2.7

Real Server:

    192.168.2.5

    192.168.2.6

PHP服务器:192.168.2.10

NFS:192.168.2.10

MySQL服务器:192.168.2.3


LVS的环境的实现与上述DR模型中的实现方式一致。
在NFS服务器上创建共享目录

[root@www ~]# mkdir /httpd_dir
[root@www ~]# vim /etc/exports
/httpd_dir 192.168.2.0/24(rw,no_root_squash)
[root@www ~]# service nfs status

Real Server上挂载共享目录

[root@node1 ~]# showmount -e 192.168.2.10
Export list for 192.168.2.10:
/httpd_dir 192.168.2.0/24
[root@node1 ~]# mount -t nfs 192.168.2.10:/httpd_dir /httpd_dir

配置httpd:

[root@node1 httpd]# vim httpd.conf 
#DocumentRoot "/httpd"                      #使用虚拟主机需要注释这一项
...
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so  
....
<IfModule dir_module>
    DirectoryIndex index.php index.html
</IfModule>
    ......
    AddType application/x-httpd-php .php                #支持识别php格式的页面
    AddType application/x-httpd-php-source .phps
    ......
Include /etc/httpd/extra/httpd-vhosts.conf

虚拟主机:

<VirtualHost *:80>
    ServerAdmin baby@xiaoxiao.com
    DocumentRoot "/httpd_dir"
    ProxyRequests Off
    ProxyPassMatch ^/(.*\.php)$ fcgi://192.168.2.10:9000/httpd_dir/$1
    <Directory "/httpd_dir">
        Options none
        AllowOverride none
        Require all granted
    </Directory>
</VirtualHost>

配置完成之后,将配置文件同步至其他各节点。

在NFS服务器上部署discuz

[root@www ~]# unzip Discuz_7.2_FULL_SC_GBK.zip 
[root@www ~]# mv upload/* /httpd_dir/
[root@www ~]# cd /httpd_dir/
[root@www httpd_dir]# chown -R nobody:nobody ./*

由于应用的需要在php的配置文件中将这一项打开

[root@www httpd_dir]# vim /etc/php.ini
short_open_tag = On


在数据库中创建数据库和对应的用户,然后授权

MariaDB [(none)]> create database discuz;
Query OK, 1 row affected (0.02 sec)
 
MariaDB [(none)]> grant all on discuz.* to discuz@'192.168.%.%' identified by 'discuz';
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)


最后打开http://192.168.2.100/install/index.php,安装一下数据库即可。

LVS详解及基于DR模型的案例_nat模型_04

LVS详解及基于DR模型的案例_dr模型_05LVS详解及基于DR模型的案例_dr模型_06

完成发帖.................^_^