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模型
工作原理: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模型
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
实验环境:
路由器:
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,安装一下数据库即可。
完成发帖.................^_^