lvs(linux virtual server)是工做在netfiler之上的,netfilter是在内核中tcp/Ip协议栈上选择了5个位置看成卡钩: PREROUTING --> INPUT --> FORWARD --> OUTPUT --> POSTROUTINGhtml
lvs代码也分为两段,跟iptables同样,一段工做在内核中的一个框架ipvs,根据你所定义的规则可以实现转发,一段工做在用户空间中的程序ipvsadm,写入规则后能够送到内核空间上去。前端
ipvs不是工做在prerouting上,而是工做在input链上,ipvs会发现用户请求是一个集群服务,是一个向后端转发的服务,因此ipvs在此处强行把请求转走,送往postrouting出去,进而转发到后端主机上。node
http://www.netfilter.org/documentation/HOWTO//netfilter-hacking-HOWTO-3.htmllinux
lvs的术语:算法
IP:windows
ViP: virtual ip 为虚拟服务器提供虚拟服务的ip后端
Dip:director ip 用于实现跟内部主机通讯的ip缓存
Rip:realserver ip 后端真实服务器的ipbash
Cip:client ip 客户端ip服务器
Director中内核tcp/ip协议栈简单网络转发结构
lvs按照其工做架构有三种不一样的工做类型
lvs-nat Network Address Translation 网络地址转换
lvs-dr Direct Routing 直接路由
lvs-tun tunneling 隧道
nat类型的特性:修改请求报文的目标ip地址(ip和port)
请求ip段的状态
CIP:VIP -> CIP:RIP1(挑选出来)
响应ip段的状态
RIP:CIP -> VIP:CIP
1.RS(realserver)应用使用私有地址;RS的网关必须指向DIP
2.请求和响应都要通过Director;高负载场景中,Director易成为性能瓶颈
3.支持端口映射
4.RS可使用任意OS
解决Director压力过大而使用的类型
dr类型的特性:只用来接收请求和分发,未改目标ip,只是修改了报文的目标mac地址改成了realserver网卡的mac地址,响应报文不通过Director,而是直接经过realserver响应给客户端。
1. 保证前端路由将目标地址为VIP的报文通通发往Director,而不能是RS;
解决方案:
(1) 静态地址绑定:在前端路由器上操做 配置静态VIP
存在的问题:未必有路由操做权限
(2) 使用arptables(arp解析时作防火墙规则的),须要写规则
(3) 修改RS上内核参数,将RS上的VIP配置在lo接口的别名上,并限制其不能响应对VIP地址解析请求
2. RS可使用私有地址,但也可使用公网地址,此时可经过互联网经过RIP对其直接访问
3. RS跟Director必须在同一个物理网络中
4. 请求报文经由Director,但响应报文不能通过Director
5. 不支持端口映射
6. RS能够是大多数常见的OS
7. RS的网关决不容许指向Dip
tun类型的特性:隧道类型 ip隧道(在ip外部在封装一个ip首部,存在的问题:会致使ip首部变大,各RIP须要支持隧道的功能)
1. RIP、VIP、DIP所有是公网地址
2. RS的网关不会也不可能指向DIP
3. 请求报文经由Director,但响应报文必须不能通过Director
4. 不支持端口映射
5. RS的OS必须支持隧道功能
其中nat在小规模场景中会使用;绝大部分都是选择dr类型;隧道机制在异地容灾中会是一种选择;
lvs scheduler(lvs调度方法),挑选标准有10种
# grep -i 'vs' /boot/config-3.10.0-327.el7.x86_64
…
# IPVS transport protocol load balancing support 传输层协议负载均衡的支持
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
CONFIG_IP_VS_PROTO_AH_ESP=y
CONFIG_IP_VS_PROTO_ESP=y
CONFIG_IP_VS_PROTO_AH=y
CONFIG_IP_VS_PROTO_SCTP=y
# IPVS scheduler ipvs调度算法
CONFIG_IP_VS_RR=m
CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
CONFIG_IP_VS_SH=m
CONFIG_IP_VS_SED=m
CONFIG_IP_VS_NQ=m
…
静态方法:仅根据调度算法自己进行调度,不考虑后端节点的负载
rr:round robin 轮询、轮流、轮叫 根据添加RS的顺序进行顺序调度
wrr:weighted round robin 加权轮询 对于性能更好的主机,设置权重大一些,将承担更多负载
sh:source hashing 源地址hash 为了session持久功能,表示来源于同一个cip的请求将始终被定向至同一个RS
dh:destination hashing 目标地址hash 通常是后端为多个缓存服务器时,根据目标ip地址经过散列函数将目标ip与服务器创建映射关系,出现服务器不可用或负载太高的状况下,发往该目标ip的请求会固定发给该服务器。
动态方法:根据算法以及各RS当前负载情况进行调度
lc:least connection 最少链接
overhead(当前的负载情况)=(全部链接中处于活动状态的链接)active*256 + inactive(非活动状态链接数) 根据overhead进行比较来作最少链接
wlc:weighted lc 加权最小链接
overhead=((活动链接数)active*256 + inactive)/weight(权重)
sed:shortest expection delay 最少指望延迟 第一次请求时必定是权重大的来处理
overhead = (active + 1)*256/weight
nq:never queue 永不排队 第一次请求来了后,前后端主机各一个,然后再计算
lblc:locality-based least connection 基于局部性最少链接调度算法 动态dh,请求数据包目标ip地址的一种调度算法,该算法先根据请求的目标IP地址寻找最近该目标IP地址所使用的服务器,若是这台服务器依然可用,而且有能力处理该请求,调度器会尽可能选择相同的服务器,不然会继续选择其余可行的服务器。
lblcr:replicated lblc 带复制功能的lblc 记录的不是一个目标ip一台服务器之间链接记录,它会维护一个目标ip到一组服务器之间的映射关系,防止单点服务器负载太高。
这里以lvs的dr类型举例
安装ipvsadm程序
# yum install –y ipvsadm # base源已经提供了
# rpm -ql ipvsadm |less
/etc/rc.d/init.d/ipvsadm
/etc/sysconfig/ipvsadm-config
/sbin/ipvsadm
/sbin/ipvsadm-restore
/sbin/ipvsadm-save
。。。。
定义集群服务或修改集群服务
ipvsadm - Linux Virtual Server administration
详细使用可用
man ipvsadm
ipvsadm –A|E –t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask] [--pe persistence_engine] 调度器默认是wlc
添加或修改一个集群服务
ipvsadm –a|e –t|u|f service-address –r server-address [options] 定义好的集群服务中添加或修改realserver
查看已经定义的集群服务及RS:
ipvsadm –L –n(数字格式显示) -c: 查看各链接
--stats: 统计数据 --rate: 速率
--exact: 精确值
从集群服务中删除RS:
ipvsadm –d –t|u|f service-address –r server-address
删除集群服务
ipvsadm –D –t|u|f service-address
清空全部的集群服务
ipvsadm –C
保存集群服务定义:
ipvsadm –S > /path/to/some_rule_file
ipvsadm-save > /path/to/some_rule_file
service ipvsadm save
让规则文件中的规则生效:
ipvsadm –R < /path/to/some_rule_file
ipvsadm-restore < /path/to/some_rule_file
session持久机制:
1. session绑定:始终未来自同一个源ip的请求定向至同一个RS;没有容错能力;有损均衡效果;(若是RS故障了,那么此前在RS上的会话都会丢失)
2. session复制:在RS之间同步session,每一个RS拥有集群中的全部session;对大规模集群不适用;
3. session服务器:利用单独部署的服务器统一管理集群中的session;
lvs dr:Director和realserver在同一个物理网络中,转发时Director上修改目标mac为rip的mac,rip和dip不在同一个网络中时,须要配置路由信息,让各rip经过路由访问互联网
Director配置两个地址:dip、VIP
RS须要配置:rip、VIP
RS配置内核参数
arp_ignore:如何响应ARP地址的广播请求;默认0所有响应;1表示仅在请求的地址配置在请求报文的接口进行响应;全部接口都要这样配置
arp_announce:如何响应通告本地地址;默认0全部地址都会通告;2表示仅通告网络直连的接口的地址;全部接口都要这样的配置
# echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
# echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
注意:须要先配置内核参数再改ip地址
Director和realserver安装好httpd而且启动
node4提供的访问页面为
<h1>node4</h1>
node5提供的访问页面为
<h1>node5</h1>
RS:首先配置内核参数
配置VIP时使用以下格式:
ifconfig lo:0 vip netmask 255.255.255.255 broadcast vip up (只广播给本身不广播给其余任何人)
route add –host vip dev lo:0 若是请求的是realserver上的VIP,那么必须通告lo:0出去
node3
# echo 1 > /proc/sys/net/ipv4/ip_forward
# ifconfig eth0:0 192.168.21.190/24 up
node4
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
# echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
# echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce
# ifconfig lo:0 192.168.21.190 netmask 255.255.255.255 broadcast 192.168.21.190 up
# route add –host 192.168.21.190 dev lo:0
node5
# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
# echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore
# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
# echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce
# ifconfig lo:0 192.168.21.190 netmask 255.255.255.255 broadcast 192.168.21.190 up
# route add –host 192.168.21.190 dev lo:0
windows上操做
node3
# ipvsadm –A –t 192.168.21.190:80 –s rr
# ipvsadm –a –t 192.168.21.190:80 –r 192.168.21.230 –g –w 1
# ipvsadm –a –t 192.168.21.190:80 –r 192.168.21.222 –g –w 2
# 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.21.190:80 rr
-> 192.168.21.222:80 Route 2 0 0
-> 192.168.21.230:80 Route 1 0 0
由于是rr模型的,给定权重也不起做用的
让DIP和VIP不在统一网段,中间须要加一个路由设备
Director脚本:
#!/bin/bash
#
# LVS script for VS/DR
#
. /etc/rc.d/init.d/functions
#
VIP=192.168.0.210
RIP1=192.168.0.221
RIP2=192.168.0.222
PORT=80
#
case "$1" in
start)
/sbin/ifconfig eth0:1 $VIP broadcast $VIP netmask 255.255.255.255 up
/sbin/route add -host $VIP dev eth0: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 wlc
# 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 1
/sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -g -w 2
/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
# Bring down the VIP interface
/sbin/ifconfig eth0:1 down
/sbin/route del $VIP
/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脚本:
#!/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
host=`/bin/hostname`
case "$1" in
start)
# Start LVS-DR real server on this machine.
/sbin/ifconfig lo down
/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