LVS两段式介绍
ipvs:工作在内核空间,TCP/IP协议栈INPUT钩子函数上的框架(Linux2.5内核之后内置ipvs代码,LVS跟netfilter不能同时使用)。
ipvsadm:工作在用户空间,负责管理集群服务编写规则的命令行工具,需要手动安装。
1 |
$ yum install ipvsadm |
ipvsadm管理命令
一、管理集群服务
1)添加集群
1 |
ipvsadm -A -t|u|f service-address [-s scheduler] |
2)修改集群
1 |
ipvsadm -E -t|u|f service-address [-s scheduler] |
3)删除集群
1 |
ipvsadm -D -t|u|f service-address |
参数解释:
1 2 3 4 |
-t #TCP协议集群,如[IP:PORT]; -u #UDP协议集群,如[IP:PORT]; -f #FWM防火墙标记,如[MARK NUMBER]; -s #调度算法,如[rr|wrr|sh|dh|lc|wlc|lblc|lblcr]; |
使用示例:
1 2 3 4 5 6 7 8 |
# 添加一个VIP为172.29.32.205:80的集群,调度算法为wrr加权轮询; $ ipvsadm -A -t 172.29.32.205:80 -s wrr # 修改VIP的端口为8080; $ ipvsadm -E -t 172.29.32.205:8080 -s wrr # 删除集群; $ ipvsadm -D -t 172.29.32.205:80 |
二、管理集群中的RealServer
1)添加RealServer
1 |
ipvsadm -a -t|u|f service-address -r service-address [-g|-i|-m] [-w weight] |
2)修改RealServer
1 |
ipvsadm -e -t|u|f service-address -r service-address [-g|-i|-m] [-w weight] |
3)删除RealServer
1 |
ipvsadm -d -t|u|f service-address -r service-address |
参数解释:
1 2 3 4 5 6 7 8 |
-t|u|f service-address #这个地址是前面创建好的集群服务; -r service-address #定义RealServer地址,在NAT模式中可使用端口映射; -g #表示使用DR模型; -i #表示使用TUN模型; -m #表示使用NAT模型; -w #定义权重值,如果使用加权轮询,LVS会根据权限比例分配客户端连接请求; -p #定义tcp超时时间,默认为120秒; --set 900 120 300 #定义tcp/tcpfin/udp的超时时间,默认为900/120/300秒; |
使用示例:
1 2 3 4 5 6 7 8 |
# 添加一条RealServer,地址为172.29.32.201:80,调度模式为DR,权重为5; $ ipvsadm -a -t 172.29.32.205:80 -r 172.29.32.201:80 -g -w 5 # 修改RealServer条目的端口为8080; $ ipvsadm -e -t 172.29.32.205:80 -r 172.29.32.201:8080 -g -w 5 # 删除RealServer条目; $ ipvsadm -d -t 172.29.32.205:80 -r 172.29.32.201:80 |
三、查看集群状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# 查看集群状态,包含RealServer条目; $ ipvsadm -L # 显示为数字格式,但必须配合-L一块使用且-L必须在-n前面,也可以合并使用,如-Ln; $ ipvsadm -Ln # 显示当前连接数; $ ipvsadm -Lnc # 显示统计数据 $ ipvsadm -Ln --stats # 显示速率; $ ipvsadm -Ln --rate # 显示tcp/tcpfin/udp的会话超时时长,默认是900、120/300; $ ipvsadm -Ln --timeout # 显示进程状态; $ ipvsadm -Ln --daemon # 对集群服务做排序默认升序; $ ipvsadm -Ln --sort |
四、清空所有集群服务
1 |
$ ipvsadm -C |
五、导入导出ipvs规则
1 2 3 4 5 |
# 导出ipvs规则; $ ipvsadm -S > /PATH # 导入ipvs规则; $ ipvsadm -R < /PATH |
六、查看ipvsadm版本号
1 |
$ ipvsadm --version |
LVS DR模式介绍
DR模型是通过路由技术实现的负载均衡技术,而这种模型与NAT模型不同的地方是,负载均衡器接收到数据请求报文后通过改写用户请求报文中的MAC地址为所挑选的RealServer即可。并不修改报文的源地址(CIP)和目标地址(VIP),并将请求报文发送到RealServer, 而RealServer(RS服务器必须额外配置VIP的地址,并关闭所有对VIP发送ARP广播的数据包响应,这样上端路由器发送ARP报文解析VIP地址时只有调度器才能响应并接收ARP数据包而所有的Realserver虽然也有VIP但是不会响应目标地址为VIP的ARP数据包)接收到报文后发现目标地址(VIP)就是自己后直接响应用户,这样就大大的减少负载均衡器的压力,在生产环境中DR模型也是用的最多的一种LVS调度模式,比NAT模型快10倍不止。
为了避免RealServer的VIP地址响应上端ARP报文请求在Linux内核中引入了一种机制,对于Linux系统而言IP地址是系统的而不是网卡的,所以可以最简单的实现方式也就是把RIP地址设置在对外提供服务的网卡上,如ETH0。VIP地址设置在loopback的别名上loopback:0上,然后通过调整Linux内核ARP栈在响应外部数据包请求的规则,如果接收的ARP报文目标地址不是Eth0上的RIP地址主机就不予相应。
需调整以下4个内核参数:
all_ignore
arp_ignore:定义接收到app请求时的响应级别,默认是0。
0:表示只要本地配置的有相应地址就给与响应。
1:表示仅在请求的目标地址配置请求到达的接口上的时候才给与相应。
all_announce
arp_announce:定义将自己地址向外通告时的通告级别,默认是0。
0:表示将本地任何接口的任何地址向外通告。
1:表示尽可能试图仅向目标网络通告与其网络匹配的地址。
2:表示仅向与本地接口上地址匹配的网络进行通告。
注意:Linux路由策略上默认有这样一种行为,响应报文的源地址一般会配置为报文流出接口的地址,这样一来客户端访问的目标地址是VIP经过调度器转发给RealServer后,如果响应的目标地址是Eth0接口的RIP,而客户端没有访问RIP所以拒绝接收相应数据包,所以还需要一种路由策略,必须保证访问数据包的目的地址如果是VIP,那么RealServer响应数据包的目标地址就必须是loopback上的VIP地址。这就需要额外配置一条独特的路由条目明确说明响应地址是VIP。
1 |
$ route add –host VIP dev lo:0 |
DR模型的特点如下:
1)所有的集群节点都必须同一个物理网络中。
2)RIP可以是公有IP也可以是私有IP。
3)负载均衡器只响应进站请求,RealServer自己响应出站请求,从而大大地减少调度器压力,因为进站请求数据包一般都很小而出站才是核心。
4)不支持端口映射。
LVS DR模式实验配置
1)环境配置
Client一台,地址为172.16.16.10。
Directory一台,地址为172.16.16.1。
RealServer1一台,安装HTTP服务,地址为172.16.16.2。
RealServer2一台,安装HTTP服务,地址为172.16.16.3。
PS:LVS DR模式下,调度服务器和realserver必须在同一个网段。
2) Directory配置
清空iptables规则避免影响ipvsadm
1 2 |
$ iptables -F $ service iptables save |
设置VIP地址
1 |
$ ifconfig eth0:1 172.16.16.1/16 |
打开路由功能
1 |
$ echo 1 > /proc/sys/net/ipv4/ip_forward |
配置集群管理为加权轮询
1 |
$ ipvsadm -A -t 172.16.16.1:80 -s wrr |
添加RealServer条目
1 2 |
$ ipvsadm -a -t 172.16.16.1:80 -r 172.16.16.2:80 -g -w 5 $ ipvsadm -a -t 172.16.16.1:80 -r 172.16.16.3:80 -g -w 5 |
查看配置信息
1 2 3 4 5 6 7 |
$ ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 172.16.16.1:80 wrr -> 172.16.16.2:80 Route 5 0 0 -> 172.16.16.3:80 Route 5 0 0 |
3)RealServer1配置
安装nginx
1 2 3 |
$ yum install nginx $ nginx $ echo 172.16.16.2 > /usr/share/nginx/html/index.html |
设置RIP地址
1 |
$ ifconfig eth0 172.16.16.2/16 |
调整网卡响应机制(目标地址不是ETH0接口地址统统拒绝响应)
1 2 3 4 |
$ sysctl -w net.ipv4.conf.eth0.arp_announce=2 $ sysctl -w net.ipv4.conf.all.arp_announce=2 $ echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore $ echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore |
在loopback上设置VIP地址只用于响应数据包
1 |
$ ifconfig lo:0 172.16.16.1 broadcast 172.16.16.1 netmask 255.255.255.255 |
设置路由策略如果目标地址访问的是VIP那么响应地址就设为lo:0的地址
1 |
$ route add -host 172.16.16.1 dev lo:0 |
4)Realserver2配置
安装nginx
1 2 3 |
$ yum install nginx $ nginx $ echo 172.16.16.3 > /usr/share/nginx/html/index.html |
设置RIP地址
1 |
$ ifconfig eth0 172.16.16.3/16 |
调整网卡响应机制(目标地址不是ETH0接口地址统统拒绝响应)
1 2 3 4 |
$ sysctl –w net.ipv4.conf.eth0.arp_announce=2 $ sysctl –w net.ipv4.conf.all.arp_announce=2 $ echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore $ echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore |
在loopback上设置VIP地址只用于响应数据包
1 |
$ ifconfig lo:0 172.16.16.1 broadcast 172.16.16.1 netmask 255.255.255.255 |
设置路由策略如果目标地址访问的是VIP那么响应地址就设为lo:0的地址
1 |
$ route add –host 172.16.16.1 dev lo:0 |
5)测试效果
可以使用客户端访问172.16.16.1查看轮询访问变化,如下:
1 2 3 4 5 6 7 8 |
$ curl http://172.16.16.1 172.16.16.2 $ curl http://172.16.16.1 172.16.16.3 $ curl http://172.16.16.1 172.16.16.2 $ curl http://172.16.16.1 172.16.16.3 |
或者使用ab压力测试访问172.16.16.1查看加权轮询变化。
1 |
$ ab -n 10000 -c 100 http://172.16.16.1 |
查看当前连接数
1 2 3 4 5 6 7 |
$ ipvsadm -L -n -c IPVS connection entries pro expire state source virtual destination TCP 01:51 FIN_WAIT 172.16.16.10:55867 172.16.16.1:80 172.16.16.2:80 TCP 01:51 FIN_WAIT 172.16.16.10:55866 172.16.16.1:80 172.16.16.3:80 TCP 14:57 ESTABLISHED 172.16.16.10:55875 172.16.16.1:80 172.16.16.2:80 TCP 14:59 ESTABLISHED 172.16.16.10:55874 172.16.16.1:80 172.16.16.3:80 |
查看统计信息
1 2 3 4 5 6 7 |
$ ipvsadm -L -n --stats IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes -> RemoteAddress:Port TCP 172.16.16.1 :80 37 239 0 46426 0 -> 172.16.16.2:80 18 168 0 41733 0 -> 172.16.16.3:80 19 71 0 4693 0 |
由于是DR模式,所以当访问几次之后,可以看到,指标Conns、InPkts、InBytes都有数据,而OutPkts、OutBytes没有数据。因为DR模式下进数据包是经过调度器,而出去的包是realserver直接跟client响应的。而DR模式则不然。
最后,还可以更改RealServer的权重,再使用AB压力测试一下,看看统计信息是否跟权重调整的对比。
PS:你在测试过程中,当LVS调度算法使用轮询或加权轮询默认时,如果你使用浏览器(同一个IP)访问VIP,可能会出现跟你想象的轮询调度不一样的结果,那就是一直刷新网页却无法轮询,每次都需要等待2分钟才有轮询效果。而如果你使用curl这种工具进行访问VIP则可以每次都轮询,主要因为浏览器默认使用了keepalive,而curl没有使用,当然这是LVS的默认特性,详情请看LVS负载均衡—tcp keepalive问题分析?
DR模式服务控制脚本
Director脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
#!/bin/bash # # LVS script for VS/DR . /etc/rc.d/init.d/functions VIP=172.16.16.1 RIP1=172.16.16.2 RIP2=172.16.16.3 PORT=80 INT=eth0 case "$1" in start) /sbin/ifconfig $INT:1 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev $INT:1 # Since this is the Director we must be able to forward packets echo 1 > /proc/sys/net/ipv4/ip_forward # Clear all iptables rules. /sbin/iptables -F # Reset iptables counters. /sbin/iptables -Z # Clear all ipvsadm rules/services. /sbin/ipvsadm -C # Add an IP virtual service for VIP 192.168.0.219 port 80 # In this recipe, we will use the round-robin scheduling method. # In production, however, you should use a weighted, dynamic scheduling method. /sbin/ipvsadm -A -t $VIP:80 -s wrr # Now direct packets for this VIP to # the real server IP (RIP) inside the cluster /sbin/ipvsadm -a -t $VIP:80 -r $RIP1 -g -w 5 /sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -g -w 5 /bin/touch /var/lock/subsys/ipvsadm &> /dev/null ;; stop) # Stop forwarding packets echo 0 > /proc/sys/net/ipv4/ip_forward # Reset ipvsadm /sbin/ipvsadm -C # Delete lock file /bin/rm -f /var/lock/subsys/ipvsadm echo "ipvs is stopped..." ;; status) if [ ! -e /var/lock/subsys/ipvsadm ]; then echo "ipvsadm is stopped ..." else echo "ipvs is running ..." ipvsadm -L -n fi ;; *) echo "Usage: $0 {start|stop|status}" ;; esac |
RealServer脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#!/bin/bash # # Script to start LVS DR real server. # description: LVS DR real server # . /etc/rc.d/init.d/functions VIP=192.168.0.219 case "$1" in start) # Start LVS-DR real server on this machine. /sbin/ifconfig lo up echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce /sbin/ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev lo:0 ;; stop) # Stop LVS-DR real server loopback device(s). /sbin/ifconfig lo:0 down echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce ;; status) # Status of LVS-DR real server. islothere=`/sbin/ifconfig lo:0 | grep $VIP` isrothere=`netstat -rn | grep "lo:0" | grep $VIP` if [ ! "$islothere" -o ! "isrothere" ];then # Either the route or the lo:0 device # not found. echo "LVS-DR real server Stopped." else echo "LVS-DR real server Running." fi ;; *) # Invalid entry. echo "$0: Usage: $0 {start|status|stop}" exit 1 ;; esac |
LVS DR模式实验至此结束。
私网地址DR模式图