设为首页 收藏本站
查看: 1380|回复: 0

[经验分享] lvs使用和管理

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-8-22 10:48:10 | 显示全部楼层 |阅读模式
lvs是由章文嵩开发出来的,以开源软件的方式,提供负载均衡,其工作方式与iptables非常相似。当用户请求的数据到达本机,经过PREROUTING,来到INPUT表,ipvs会查看所有报文,如果发现请求的是已经定义好的集群服务的规则,不会让数据报文进入用户空间,而是强行修改报文,把数据经过FORWARD转发到后端的real server,从而完成调度。同时的lvs的负载能力也确实是非常高,据说可以达到400WPV的负载能力,且集群配置较为简单
lvs和iptables有很多相似的地方:
iptables:
iptables: 用户空间规则管理工具;
netfilter:内核空间让规则生效的组件;一共有三种流向:
PREROUTING --> INPUT  到本机内部的
PREROUTING --> FORWARD--> POSTROUTING  经由本机转发
OUTPUT --> POSTROUTING   本机内部转发出去的

DNAT:PREROUTING;将目标主机转换为后端的某一主机既要在到达本机路由器前进行跳转;但是ipvs不是这样工作的,
ipvs确实类似与netfilter,但是依附在在netfilter上的INPUT链上面的组件,而不是PREROUTING


lvs管理工具
ipvsadm/ipvs  组件
ipvsadm:用户的空间的命令行工具,规则管理器,用于管理集群服务及RealServer;
ipvs:工作于内核空间的netfilter的INPUT钩子之上的框架,可接收来ipvsadm的管理命令;

ipvs支持的服务:支持基于TCP、UDP、SCTP、AH、ESP、AH_ESP等 协议进行调度;
注:lvs的ipvs通常和ipbtales的filter不能一起工作,这里主要是值iptbles的INPUT链,因为用的是一个链,很有可能iptables把lvs的规则就给阻断了,因此用lvs最好在防火墙的INPUT就不要再做其他设置了后者关闭防火墙,因为现在企业大多数有硬件防火墙,这里的风险还是比较小的。

lvs集群的常用术语:
vs: virutal server, 也叫Director(调度器), Dispatcher(分发器),Balancer(均衡器)
rs: real server, 也叫backend server(反向服务器), upstreamserver(上游服务器)

CIP: Client IP   (客户端IP)
VIP: Virtual Server IP (lvs前端的ip,它是负责往里面转的,同时也是用户的目标地址)
DIP: Director IP    (跟realserver交互)
RIP: Real Server IP
整个用户的请求的流程是:
CIP <--> VIP <--> DIP <--> RIP

lvs集群类型(四种):
lvs-nat:
多目标IP的DNAT,通过将请求报文中的目标地址和目标端口修改为某挑出的RS的RIP和PORT实现转发;
要求:
(1) RIP和DIP必须在同一个IP网络,且应该使用私网地址;RS的网关要指向DIP;
(2)请求报文和响应报文都必须经由Director转发;Director易于成为系统瓶颈;(一个directory可带5-10台RS)
(3) 支持端口映射;VIP上的端口和RIP上的端口不必非得是同一个;
(4) vs必须是Linux系统,rs可以是任意系统;
wKioL1e2_WnSCAncAABynUym-rM546.jpg
lvs-dr:(默认模型)
Direct Routing:直接路由;
通过为请求报文重新封装一个MAC首部进行转,源MAC是DIP所在的接口的MAC,目标MAC是某挑选出的RS的RIP所在接口的MAC地址;源IP/PORT,以及目标IP/PORT均保持原状;
(1) 确保前端路由器将目标IP为VIP的请求报文发往Director:(有三种解决方法)
(a) 在前端路由器绑定;  此方法不太可取
(b) 在RS使用arptables;
(c) 在RS上修改内核参数限制通告及应答级别;
arp_announce    通告
arp_ignore            应答响应
(2) RS的RIP可以私网地址,也可是公网地址;RIP与DIP在同一个IP网络;
(3) RS跟Director要在同一个物理网络,以实现基于MAC地址的转发;
(4) 请求报文要经由Director,但响应不能经由Director;
(5) 不支持端口映射;
wKiom1e2_WrisNQQAADsO7RNLwQ789.jpg
lvs-tun:tunnel,隧道; (为了解决lvs和real server 必须在同一网络,不能异地部署问题而出现)
注:此功能容易出现大数据帧,MTU为1500,超过了就要切片,因此此功能很少用
转发方式:不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而是在IP报文之外再封装一个IP首部(源IP是DIP,目标IP是RIP),将报文发往挑选出的目标RS;
要求:
(1) DIP, VIP, RIP应该都是公网地址;
(2) RS网关必须不能指向DIP;
(3) 请求报文要经由Director,但响应不能经由Director,而是直接发往CIP;
(4) 不支持端口映射;
(5) RS必须支持隧道功能;
wKioL1e2_WrBj225AADgrGXWd5w023.jpg
注:无论是ipvs-dr和ipvs-tun中的DIP、RIP和VIP不在同一网关没有任何问题;因为对外响应的报文只管目标地址,不管原地址


lvs-fullnat:
通过同时修改请求报文的源IP地址和目标IP地址进行转发;
cip -源修改成-> dip      源
vip -目标修改成-> rip       目标
(1)VIP是公网地址,RIP和DIP是私网地址,且通常不在同一IP网络;(与nat的不同点)
(2) RS收到的请求报文源地址为DIP,应响应给DIP即可;
(3) 请求和响应报文都经由Director;
(4) 支持端口映射;
fullnat注意:默认不支持;需要定制版的内核

ipvs scheduler:调度算法
根据其调度时是否考虑各RS当前的负载状态,可分为静态方法和动态方法;(10种)

静态方法:仅根据算法本身进行调度,注重起点公平;
RR
:roundrobin,轮询;
WRR
:WeightedRR,加权轮询;针对不同的服务器本来负载能力就不同,负载能力强的权重大,负载能力小的权重小
SH
SourceHashing,源地址哈希,(在指定的时间内)将来自于同一个IP地址的请求始终发往第一次挑中的RS,从而实现了会话绑定;
会话不会丢失,但是就怕服务器宕机;还有就是现在上网都是通过nat实现内网上网,很多用户访问一个网页会形成一个ip,这样大量的请求就指向了同一台服务器,绑定力度太粗糙(有人会说绑定cookie,问题就在这,ipvs基于iso第四层网络传输层,不属于应用层,所有无法实现
DHDestinationHashing,目标地址哈希,将发往同一个目标地址的请求,始终转发至第一次挑中的RS;不管是谁访问的,只要访问的资源为同一个资源,都发往同一个server,常用于正向代理当中
动态方法:主要根据每RS当前的负载状态进行调度,注重结果公平;
负载计算方式:
Overhead = activeconns*256+inactiveconns   活动数*256+非活动数
LC
least connections,最少连接,谁的小就让请求谁 (如果一开始一样就自上而下以此调度)
Overhead= activeconns*256+inactiveconns
WLC
WeightedLC, 加权最少连接,默认算法
Overhead = (activeconns*256+inactiveconns)/weight    ;一般权重大的,值比较小,因此会先会被调度;会有一个问题:当响应比较少的时候,最好是让权重比较大的相应,但是这个算法不太好控制
SED
ShortestExpection Delay,最短期望延迟;让系统最好的服务器来响应
Overhead=(activeconns+1)*256/weight    这样权重越大,所得的值越小,因此越先被调度,但是又出了新的问题:权重大的要先响应,而权重小的先不响应,造成了先没事儿干的情况
NQNever Queue    永不排队,不让一个服务器有队列,而另一个服务器没有请求等情况发生,就是先一人来一个,之后按照SED的算法继续最短期望延迟算法进行后续调度,这个是上一个改进版
LBLC
Locality-BasedLeast connections,基于本地的最少连接;动态的DH算法;
主要节约的问题吧DH换成动态的,能让同一个网页再访问量比较大的时候,让新的同一网页的请求调度到其他服务器上
LBLCRLBLCwith Replication,带复制的基于本地的最少连接;如果服务器负载过大,把访问同一目标地址的请求分发的别的服务器,并把缓存也复制过去


搭建lvs-nat模式
搭建lvs-nat模式集群,后端web服务器两台,都跑着php+nginx,后端mysql作为数据共享,搭建wordprss
负载均衡php应用,测试保持会话有无的区别

wKiom1e2_Wuj9jFgAAChmonK6A8173.jpg
首先根据图中的拓扑图,将各服务器的ip设定完毕,内网的网关执向设定好;
两台web服务器安装上yum install -y nginx php-fpm php-mysql,并置好相关的网页根目录(/data/www)
把nginx和php的连接配置设置好,并测试成功(详见lnmp的相关配置)
准备好数据库(192.168.1.123)
[iyunv@haizei ~]# yum install mariadb-server
[iyunv@haizei ~]# vim /etc/my.cnf
[mysqld]
socket=/var/lib/mysql/mysql.sock
datadir = /data/mariadb
innodb_file_per_table = ON
skip_name_resolve = ON
[iyunv@haizei ~]# mkdir /data/mariadb
[iyunv@haizei /]# chown mysql.mysql /data/mariadb
[iyunv@haizei ~]# systemctl start mariadb

MariaDB [(none)]> grant all on *.* to 'zou'@'192.168.1.%'identified by '123.comer';
MariaDB [(none)]> create database wordpress;
MariaDB [(none)]> grant all on wordpress.* to'wpuser'@'192.168.1.%' identified by 'wppasswd';
MariaDB [(none)]> flush privileges;

准备好wordpress网页 (192.168.1.20   和 30)
[iyunv@localhost wordpress]# cp wp-config-sample.phpwp-config.php
[iyunv@localhost wordpress]# vim wp-config.php
define('DB_NAME', 'wordpress');
define('DB_USER', 'wpuser');
define('DB_PASSWORD', 'wppasswd');
define('DB_HOST', '192.168.1.123');

创建集群
[iyunv@localhost ~]# ipvsadm -A -t 172.16.1.7:80 -s rr
[iyunv@localhost ~]# ipvsadm -a -t 172.16.1.7:80 -r192.168.1.20:80 -m -w 2
[iyunv@localhost ~]# ipvsadm -a -t 172.16.1.7:80 -r192.168.1.30:80 -m -w 1
[iyunv@localhost ~]# ipvsadm -L
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  ->RemoteAddress:Port           ForwardWeight ActiveConn InActConn
TCP  172.16.1.7:http rr
  -> 192.168.1.20:http            Masq    2     0          0         
  ->192.168.1.30:http            Masq    1     0          0  
开启路由转发:
[iyunv@localhost ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

在浏览器输入172.16.1.7/wordpress  即可进入安装界面

wKioL1e2_WvwBMuDAAB_tbw7FQI155.jpg
之后点击浏览网页的各个资源,并做先关测试
[iyunv@localhost ~]# ipvsadm -L --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts OutPkts  InBytes OutBytes
  ->RemoteAddress:Port
TCP 172.16.1.7:http                   24      757      194   50738  1634852
  ->192.168.1.20:http                 12       40        8    2710     1445
  ->192.168.1.30:http                 12      717      186   48028  1633407
[iyunv@localhost ~]# ipvsadm -L --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts OutPkts  InBytes OutBytes
  ->RemoteAddress:Port
TCP 172.16.1.7:http                   31     1389      405  131549  3104513
  ->192.168.1.20:http                 15       47        8    3074     1445
  ->192.168.1.30:http                 16     1342      397  128475  3103068
从上面的数据我们可以看出,这个服务器均有响应,
好了我们清空一下计数,准备一下,保持会话,会有什么变化
[iyunv@localhost ~]# ipvsadm -Z
修改为保持会话
[iyunv@localhost ~]# ipvsadm -E -t 172.16.1.7:80 -s sh
查看状态:
[iyunv@localhost ~]# ipvsadm -L --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts OutPkts  InBytes OutBytes
  ->RemoteAddress:Port
TCP 172.16.1.7:http                   17     1560      542  117187  3717381
  ->192.168.1.20:http                  5        7        0     420        0
  ->192.168.1.30:http                 12     1553      542  116767  3717381
[iyunv@localhost ~]# ipvsadm -L --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts OutPkts  InBytes OutBytes
  ->RemoteAddress:Port
TCP 172.16.1.7:http                   28     2172      845  166410  5117125
  ->192.168.1.20:http                  7        9        0     540        0
  ->192.168.1.30:http                 21     2163      845  165870  5117125
在这里的数据可以看到ipv的会话绑定在让相同的ip的来源,请求大多都跑向了192.168.1.30

下面我们继续吧调度算法调回rr,轮训,不管权重,同时清空计数
[iyunv@localhost ~]# ipvsadm -Z
[iyunv@localhost ~]# ipvsadm -E -t 172.16.1.7:80 -s rr

之后我们去设置php的的会话保持,修改php.ini配置文件
这里在(192.168.1.20  和192.168.1.30的两台php服务器上设置)
[iyunv@luffy ~]# vim /etc/php.ini
[Session]
session.save_handler = files #session的存储方式
session.use_cookies= 1 #使用cookies在客户端保存会话
session.use_only_cookies = 1 #去保护URL中传送session id的用户
session.name = PHPSESSID #session名称(默认PHPSESSID)
session.auto_start = 0 #不启用请求自动初始化session
session.cookie_lifetime = 0 #cookie存活时间(0为直至浏览器重启,单位秒)
session.cookie_path = / #cookie的有效路径
session.cookie_domain = #cookie的有效域名
session.cookie_httponly = #httponly标记增加到cookie上(脚本语言无法抓取)
session.serialize_handler = php #PHP标准序列化

session.gc_probability =1
session.gc_divisor =1000 #建议设置1000-5000
#概率=session.gc_probability/session.gc_divisor(1/1000)
#页面访问越频繁概率越小
session.gc_maxlifetime =1440 #过期时间(默认24分钟,单位秒)

session.bug_compat_42 = off #全局初始化session变量
session.bug_compat_warn = off
session.referer_check = #防止带有ID的外部URL
session.entopy_length = 0 #读取的字节
session.cache_limiter = {nocache,private,pblic} #HTTP缓冲类型
session.cache_expire = 180 #文档过期时间(分钟)
session.use_trans_sid = 1 #trans_sid支持(默认0)
session.hash_function = 0 #hash方法{0:md5(128 bits),1:SHA-1(160 bits)}
session.hash_bits_per_character = 5 #当转换二进制hash数据奥可读形式是,每个字符保留位数
session.save_path = "/tmp" #session id存放路径
~】# nginx -s reload
~】# systemctl reload php-fpm

默认的,php会将session保存在/tmp目录下,文件名为这个样子:sess_01aab840166fd1dc253e3b4a3f0b8381。每一个文件对应了一个session(会话)。
[iyunv@localhost ~]# ipvsadm -L --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts OutPkts  InBytes OutBytes
  ->RemoteAddress:Port
TCP 172.16.1.7:http                    1       96       85   34881    18312
  ->192.168.1.20:http                  0        2        2      80       80
  ->192.168.1.30:http                  1       94       83   34801    18232
[iyunv@localhost ~]# ipvsadm -L --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts OutPkts  InBytes OutBytes
  ->RemoteAddress:Port
TCP 172.16.1.7:http                    1      148      134   55902    29343
  ->192.168.1.20:http                  0        2        2      80       80
  ->192.168.1.30:http                  1      146      132   55822    29263
这两个数据是在开启了php缓存的状态下测试的,这个时候是轮训状态,请求的是index.php网页,两个web上main的网页内容不同,在浏览器上测试的时候,绝大多数网页是在一个上面停留的,在连接上面显示的只有一个,但是在测试的时候刷新了很多次浏览器,我们可以在INpkts可以看出数据是不断上涨的,这就是php的session的作用;造成了lvs的轮训没有启动作用
一下为停隔了一段时间,继续测试的
[iyunv@localhost ~]# ipvsadm -L --stats
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port               Conns   InPkts OutPkts  InBytes OutBytes
  ->RemoteAddress:Port
TCP 172.16.1.7:http                    4      195      167   63912    62631
  ->192.168.1.20:http                  2       21       15    2494    26119
  ->192.168.1.30:http                  2      174      152   61418    36512
可以看出两个网页有循环,但是主要在一个网页上停留;而这个php上面的session已经开启
wKiom1e2_WuDbx_YAAAO62DpJLg733.jpg

配置lvs-dr:direct routing

dr模型中,各主机上均需要配置VIP;解决地址冲突的方式有三种:
(1) 在前端网关做静态绑定;
(2) 在各RS使用arptables;
(3) 在各RS修改内核参数,来限制arp响应和通告的级别;
限制响应级别:arp_ignore
0:使用本地任意接口上配置的地址进行响应;
1:仅在请求的目标IP配置在本地主机的接收报文接口上时,才给予响应;
2-8:(不怎么使用,记住0和1即可)
限制通告级别:arp_announce
0:默认,把本机所有接口的信息向每个接口上的网络通告;
1:尽量改名向非本网络通告;(意思是有时可以通告)
2:必须避免向非本网络通告;
wKioL1e2_WzRJMjCAACZJo7wtas729.jpg
ipvs主机上面(设置好VIP为172.16.1.7,网关指向172.16.0.1),之后还要设置DIP(这里用一个网卡即可,别名)
[iyunv@localhost network-scripts]# vim ifcfg-eno16777736
TYPE=Ethernet
BOOTPROTO=none
NAME=eno16777736
DEVICE=eno16777736
ONBOOT=yes
IPADDR=172.16.1.17         DIP地址,
PREFIX=16
GATEWAY=172.16.0.1
IPADDR0=172.16.1.7         设置该网卡上的面的第二个地址,
PREFIX0=32                            掩码为32位,全为255,因为这里vip不用于对外通信,因此这样就好
BROADCAST=172.16.1.7     广播只能广播给自己
[iyunv@localhost network-scripts]# systemctl restart network
[iyunv@localhost network-scripts]# ip addr show eno16777736
    inet 172.16.1.7/16brd 172.16.255.255 scope global eno16777736
    inet 172.16.1.17/32brd 172.16.1.17 scope global eno16777736

其他两个Real server 上面的网络设置:
ip设置为172.16.1.1,网关执向172.16.0.1
ip设置为172.16.1.5,网关指向172.16.0.1
1.5设置限制响应级别和通告
[iyunv@zhi ~]# echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
[iyunv@zhi ~]# echo 1 >/proc/sys/net/ipv4/conf/lo/arp_ignore
[iyunv@zhi ~]# echo 2 >/proc/sys/net/ipv4/conf/lo/arp_announce
[iyunv@zhi ~]# echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce
在real server 上面配置VIP
[iyunv@zhi ~]# ifconfig lo:0 172.16.1.7netmask 255.255.255.255 broadcast 172.16.1.7 up

1.1设置限制响应级别和通告(其实只设置all就可以了,但是为了保险起见,lo或者eno1677736选一个设置)
[iyunv@luffy ~]# echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
[iyunv@luffy ~]# echo 1 >/proc/sys/net/ipv4/conf/lo/arp_ignore
[iyunv@luffy ~]# echo 2 >/proc/sys/net/ipv4/conf/lo/arp_announce
[iyunv@luffy ~]# echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce
在real server 上面配置VIP  (这个上面没有ifconfig,于是用了ip,跟上面起到的作用一样)
[iyunv@luffy ~]# ip addr add 172.16.1.7/32 broadcast 172.16.1.7 dev lo label lo:0

在lvs服务器设置集群:
[iyunv@localhost ~]# ipvsadm -A -t 172.16.1.7:80 -s rr
[iyunv@localhost ~]# ipvsadm -a -t 172.16.1.7:80 -r172.16.1.1:80 -g -w 1
[iyunv@localhost ~]# ipvsadm -a -t 172.16.1.7:80 -r172.16.1.5:80 -g -w 2
[iyunv@localhost ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  ->RemoteAddress:Port           ForwardWeight ActiveConn InActConn
TCP  172.16.1.7:80 rr
  ->172.16.1.1:80                Route   1     0          0        
  ->172.16.1.5:80                Route   2     0          0      
在其他主机客户端测试lvs的调度,
[iyunv@haizei ~]# for i in {1..10}; do curl http://172.16.1.7/index.html; done
this is web from 172.16.1.5
this is web from 172.16.1.1
this is web from 172.16.1.5
this is web from 172.16.1.1
this is web from 172.16.1.5 .....

限制Real sever 每一个经由RS直接响应给客户端的的报文,应该经由本地回环接口(不做也可以)
[iyunv@luffy www]# ip route add172.16.1.7 dev lo:0
[iyunv@zhi www]# route add-host 172.16.1.7 dev lo:0   
以上两条命令达到的效果是相同的,只不过使用的命令不同





运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-261339-1-1.html 上篇帖子: LVS高性能集群 下篇帖子: LVS-DR配置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表