LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。
特点:三种负责均衡技术
VS/NAT: 网络地址转换模式, 进站/出站的数据流量经过分发器
VS/DR: 直接路由模式,只有进站的数据流量经过分发器
调度器和真实服务器必须在同一网段VS/TUN: 隧道模式,只有进站的数据流量经过分发器
核心技术:调度器
1. 轮叫调度(Round Robin)(简称rr)
调度器通过“轮叫”调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,它均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。
2. 加权轮叫(Weighted Round Robin)(简称wrr)
调度器通过“加权轮叫”调度算法根据真实服务器的不同处理能力来调度访问请求。这样可以保证处理能力强的服务器能处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
3. 最少链接(Least Connections)(LC)
调度器通过“最少连接”调度算法动态地将网络请求调度到已建立的链接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用 “最小连接” 调度算法可以较好地均衡负载。
4.加权最少链接(Weighted Least Connections)(WLC)
在集群系统中的服务器性能差异较大的情况下,调度器采用“加权最少链接”调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负
载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。
5. 基于局部性的最少链接(Locality-Based Least Connections)(LBLC)
“基于局部性的最少链接”调度算法是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。该算法根据请求的目标IP地址找出该目标IP地址最近使用的
服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用“最少链接”
的原则选出一个可用的服务器,将请求发送到该服务器。
6. 带复制的基于局部性最少链接(Locality-Based Least Connections with Replication)(LBLCR)
“带复制的基于局部性最少链接”调度算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。它与LBLC算法的不同之处是它要维护从一个目标
IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。该算法根据请求的目标IP地址找出该目标IP地址对应的服务器组,按
“最小连接”原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载,则按“最小连接”原则从这个集群中选出一台
服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复
制的程度。
7. 目标地址散列(Destination Hashing)(DH)
“目标地址散列”调度算法根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
8. 源地址散列(Source Hashing)(SH)
“源地址散列”调度算法根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
9. 最短的期望的延迟(Shortest Expected Delay Scheduling SED)(SED)
基于wlc算法。这个必须举例来说了
ABC三台机器分别权重123 ,连接数也分别是123。那么如果使用WLC算法的话一个新请求进入时它可能会分给ABC中的任意一个。使用sed算法后会进行这样一个运算
A(1+1)/1
B(1+2)/2
C(1+3)/3
根据运算结果,把连接交给C。
10.最少队列调度(Never Queue Scheduling NQ)(NQ)
无需队列。如果有台 realserver的连接数=0就直接分配过去,不需要在进行sed运算
LVS终极手册
1 集群模式-配置(单台)
a) 安装系统和工具
参见lvs-fullnat-synproxy.tar中的README, 包括 LVS kernel和keepalived等的编译方法;
b) 内核启动参数
在kernel一行中,添加“nohz=off”
注:如果不关闭nohz,大压力下CPU0可能会消耗过高,压力不均匀;
c) S****ysctl配置
路径:/etc/sysctl.conf
configure for lvs
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.core.netdev_max_backlog = 500000
d) 配置网卡参数
路径:/etc/rc.local
关闭网卡LRO和GRO
ethtool -K eth0 gro off
ethtool -K eth0 lro off
绑定网卡中断
set_irq_affinity eth0 #脚本参见附录,该脚本是ixgbe/igb driver网卡
e) 关闭系统参数
路径:/etc/rc.local
关闭irqbalance
service irqbalance stop
chkconfig --level 2345 irqbalance off
f) LocalAddress配置
路径:/etc/rc.local
Local address绑定到内网(下联)网卡上
ip addr add 192.168.100.1/32 dev eth1
ip addr add 192.168.100.2/32 dev eth1
ip addr add 192.168.100.3/32 dev eth1
ip addr add 192.168.100.4/32 dev eth1
ip addr add 192.168.100.5/32 dev eth1
g) Z****ebra.conf
路径:/etc/quagga/zebra.conf
启动方式:/usr/sbin/zebra -d -f /etc/quagga/zebra.conf
hostname lvs-route-4
password 8 123456
enable password 8 123456
log file /var/log/zebra.log
service password-encryption
h) O****spf.conf
路径:/etc/quagga/ospf.conf
启动方式:/usr/sbin/ospfd -d -f /etc/quagga/ospf.conf
hostname lvs-4-ospfd
password 8 123456
enable password 8 123456
log file /var/log/ospf.log
log stdout
log syslog
service password-encryption
interface eth0 //上连网卡号
ip ospf message-digest-key 8 md5 123456
ip ospf hello-interval 3
ip ospf dead-interval 12
router ospf
ospf router-id 192.168.0.14 //route id配置为 上连网卡接口ip
log-adjacency-changes
auto-cost reference-bandwidth 1000
network 1.1.1.0/24 area 0.0.0.11 // VIP网段
network 192.168.0.12/30 area 0.0.0.11 // 上连IP网段
area 0.0.0.11 authentication message-digest
area 0.0.0.11 stub no-summary
i) K****eepalived.conf
启动:service keepalived start
更新:service keepalived reload
停止:service keepalived stop
Keepalived的配置包含2个文件,以taobao业务为例:
说明:一个集群内的所有LVS配置文件基本相同,区别的地方见红色区域
i. 主配置文件keepalived.conf
路径:/etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
abc@taobao.com
}
notification_email_from abc@taobao.com
smtp_server 192.168.200.1
smtp_connect_timeout 40
}
local_address_group laddr_g1 {
192.168.100.1
192.168.100.2
192.168.100.3
192.168.100.4
192.168.100.5
}
! include virtual server configure file
include taobao.conf
ii. 业务配置文件 ****“业务名.conf”
路径:/etc/keepalived/taobao.conf
virtual_server_group taobao {
1.1.1.1 80 //vip1
1.1.1.2 80 //vip2
}
!for taobao.com
virtual_server group taobao {
delay_loop 7
lb_algo rr
lb_kind FNAT
protocol TCP
syn_proxy
laddr_group_name laddr_g1
alpha //启动alpha模式,以便自动绑定vip
omega // 启动omega模式,以便自动解除vip
quorum 1
hysteresis 0
quorum_up " ip addr add 1.1.1.1/32 dev lo; ip addr add 1.1.1.2/32 dev lo;"
quorum_down " ip addr del 1.1.1.1/32 dev lo; ip addr del 1.1.1.2/32 dev lo;"
/* healthcheck for L4 */
real_server 192.168.1.1 80 {
weight 100
inhibit_on_failure
TCP_CHECK {
connect_timeout 5
}
}
/* healthcheck for L7 */
real_server 192.168.1.2 80 {
weight 100
inhibit_on_failure
HTTP_GET {
url {
path /index.html
status_code 200
}
connect_timeout 3
nb_get_retry 2
delay_before_retry 5
}
}
}
j) 环境检查
i. 重要性高
在LVS刚部署完毕,或者运维操作完毕时,都必须检查以下配置;
l 命令ip addr list,查看后端VIP是否绑定正确, 查看local address是否绑定正确
l 命令ipvsadm –ln,查看流量是否过来,各RS上流量是否均匀,流量大小是否符合预期;
l 命令ps aux | grep keepalived,查看keepalived进程个数是否正确
l 命令tcpdump –i any –nnn | grep OSPF, 查看ospf心跳是否正常
l 命令route –n, 查看ospf生成的路由是否正常
l 命令tail –n 1000 /var/log/message, 查看keepalived启动日志是否异常
ii. 重要性低
除了检查“3.1 重要性高”的点,还需要检查以下信息:
l 执行cat /proc/interrupts | grep ethx,其中ethx为万兆网卡,查看网卡中断是否被正确地绑定在N个核上;
l 在client上curl vip,在lvs上curl rs_ip,查看能否curl通;
2 主备模式-配置(单台)
a) 安装系统和工具
参见lvs-fullnat-synproxy.tar中的README,包括 LVS kernel和keepalived等的编译方法;
b) 内核启动参数
在kernel一行中,添加“nohz=off”
注:如果不关闭nohz,大压力下CPU0可能会消耗过高,压力不均匀;
c) S****ysctl配置
路径:/etc/sysctl.conf
configure for lvs
net.core.netdev_max_backlog = 500000
d) 配置网卡参数
路径:/etc/rc.local
关闭网卡LRO和GRO
ethtool -K eth0 gro off
ethtool -K eth0 lro off
绑定网卡中断
set_irq_affinity eth0 #脚本参见附录,该脚本是ixgbe/igb driver网卡
e) 关闭系统参数
路径:/etc/rc.local
关闭irqbalance
service irqbalance stop
chkconfig --level 2345 irqbalance off
f) LocalAddress配置
路径:/etc/rc.local
Local address绑定到内网(下联)网卡上
ip addr add 192.168.100.1/32 dev eth1
ip addr add 192.168.100.2/32 dev eth1
ip addr add 192.168.100.3/32 dev eth1
ip addr add 192.168.100.4/32 dev eth1
ip addr add 192.168.100.5/32 dev eth1
g) K****eepalived.conf
启动:service keepalived start
更新:service keepalived reload
停止:service keepalived stop
Keepalived的配置包含2个文件,以taobao业务为例:
说明:一个集群内的所有LVS配置文件基本相同,区别的地方见红色区域
i. 主配置文件keepalived.conf
路径:/etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
abc@taobao.com
}
notification_email_from abc@taobao.com
smtp_server 192.168.200.1
smtp_connect_timeout 40
}
local_address_group laddr_g1 {
192.168.100.1
192.168.100.2
192.168.100.3
192.168.100.4
192.168.100.5
}
! include virtual server configure file
include taobao.conf
ii. 业务配置文件 ****“业务名.conf”
路径:/etc/keepalived/taobao.conf
virtual_server_group taobao {
1.1.1.1 80 //vip1
1.1.1.2 80 //vip2
}
vrrp_instance VI_1 {
state MASTER/BACKUP
interface eth0
virtual_router_id 200
priority 150/90
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
1.1.1.1
1.1.1.2
}
}
!for taobao.com
virtual_server group taobao {
delay_loop 7
lb_algo rr
lb_kind FNAT
protocol TCP
syn_proxy
laddr_group_name laddr_g1
/* healthcheck for L4 */
real_server 192.168.1.1 80 {
weight 100
inhibit_on_failure
TCP_CHECK {
connect_timeout 5
}
}
/* healthcheck for L7 */
real_server 192.168.1.2 80 {
weight 100
inhibit_on_failure
HTTP_GET {
url {
path /index.html
status_code 200
}
connect_timeout 3
nb_get_retry 2
delay_before_retry 5
}
}
}
3 RS配置
a) 安装系统
参见lvs-fullnat-synproxy.tar中的README,其中有TOA(RS内核)的patch;
b) 加载TOA模块,命令:# modprobe toa
vim /etc/rc.local
添加 modproble toa
4日常操作(以集群模式为例)
4.1 添加/删除realserver
如果添加,请确保realserver的监听的port是打开的(可以telnet连接该端口)。
- 第1步,配置realserver,具体参见附录5.1;
更新内核版本,加载相应的TOA模块:
modprobe ttm.ko
vim /etc/rc.local
添加 modproble toa
- 第2步,修改keepalived的配置,注意所有LVS上都得修改;
例如realserver的IP为10.251.X.X,业务名taobao
vim /etc/keepalived/taobao.conf
virtual_server group taobao {
……
real_server 10.251.X.X 80 {
weight 1
TCP_CHECK {
connect_timeout 4
}
}
}
- 第3步,发送HUP信号给keepalived,使配置修改生效;
service keepalived reload
- 第4步,检查realserver是否操作成功
在LVS上,分别运行ipvsadm -ln观察该realserver的健康检查是否成功,并在LVS查看session分配是否均匀。
4.2添加/删除vip
假设新添vip为1.1.1.3,业务名称taobao;
- 修改keepalived配置文件,添加如下内容;
第一步,创建业务配置文件;
vim /etc/keepalived/taobao.conf
virtual_server_group taobao {
1.1.1.3 80 //vip1
}
virtual_server group taobao {
delay_loop 6
lb_algo rr
lb_kind FNAT
protocol TCP
syn_proxy
laddr_group_name laddr_g1
alpha //启动alpha模式,以便自动绑定vip
quorum 1
hysteresis 0
quorum_up " ip addr add 1.1.1.3/32 dev lo;"
quorum_down " ip addr del 1.1.1.3/32 dev lo;"
……
}
第二步,修改keepalived配置文件;
vim /etc/keepalived/keepalived.conf
……
! include virtual server configure file
include www.conf
include taobao.conf
- 发送HUP信号给keepalived,使配置修改生效;
service keepalived reload
- 检查vip配置是否生效;
ipvsadm –ln //查看vip是否已经配置到lvs中
ip addr list //查看lo上vip是否绑定成功
模拟用户访问vip,结果是否正确
4.3 添加/删除local address
注:local address和内网接口ip绝对不能重合;
以添加/删除192.168.100.4为例,其内网网卡为eth1,需要配置2个地方:
1. 修改/etc/rc.local
添加ip addr add 192.168.100.4/32 dev eth1
2. 修改/etc/keepalived/keepalived.conf
vim /etc/keepalived/keepalived.conf
local_address_group laddr_g1 {
……
192.168.100.4
}
3. 发送HUP信号给keepalived,使配置修改生效;
service keepalived reload
4. 检查local address配置是否生效;
ip addr list //查看网卡上是否已经绑定ip
ipvsadm –G //查看vip上是否已经绑定ip
5 set_irq_affinity脚本(源自intel 82599 driver)
setting up irq affinity according to /proc/interrupts
2008-11-25 Robert Olsson
2009-02-19 updated by Jesse Brandeburg
> Dave Miller:
(To get consistent naming in /proc/interrups)
I would suggest that people use something like:
char buf[IFNAMSIZ+6];
sprintf(buf, "%s-%s-%d",
netdev->name,
(RX_INTERRUPT ? "rx" : "tx"),
queue->index);
Assuming a device with two RX and TX queues.
This script will assign:
eth0-rx-0 CPU0
eth0-rx-1 CPU1
eth0-tx-0 CPU0
eth0-tx-1 CPU1
set_affinity()
{
if [ $VEC -ge 32 ]
then
MASK_FILL=""
MASK_ZERO="00000000"
let "IDX = $VEC / 32"
for ((i=1; i<=$IDX;i++))
do
MASK_FILL="${MASK_FILL},${MASK_ZERO}"
done
let "VEC -= 32 * $IDX"
MASK_TMP=$((1<<$VEC))
MASK=printf "%X%s" $MASK_TMP $MASK_FILL
else
MASK_TMP=$((1<<$VEC))
MASK=printf "%X" $MASK_TMP
fi
printf "%s mask=%s for /proc/irq/%d/smp_affinity\n" $DEV $MASK $IRQ
printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity
}
if [ "$1" = "" ] ; then
echo "Description:"
echo " This script attempts to bind each queue of a multi-queue NIC"
echo " to the same numbered core, ie tx0|rx0 --> cpu0, tx1|rx1 --> cpu1"
echo "usage:"
echo " $0 eth0 [eth1 eth2 eth3]"
fi
check for irqbalance running
IRQBALANCE_ON=ps ax | grep -v grep | grep -q irqbalance; echo $?
if [ "$IRQBALANCE_ON" == "0" ] ; then
echo " WARNING: irqbalance is running and will"
echo " likely override this script's affinitization."
echo " Please stop the irqbalance service and/or execute"
echo " 'killall irqbalance'"
fi
Set up the desired devices.
for DEV in $*
do
for DIR in rx tx TxRx
do
MAX=grep $DEV-$DIR /proc/interrupts | wc -l
if [ "$MAX" == "0" ] ; then
MAX=egrep -i "$DEV:.*$DIR" /proc/interrupts | wc -l
fi
if [ "$MAX" == "0" ] ; then
echo no $DIR vectors found on $DEV
continue
fi
for VEC in seq 0 1 $MAX
do
IRQ=cat /proc/interrupts | grep -i $DEV-$DIR-$VEC"$" | cut -d: -f1 | sed "s/ //g"
if [ -n "$IRQ" ]; then
set_affinity
else
IRQ=cat /proc/interrupts | egrep -i $DEV:v$VEC-$DIR"$" | cut -d: -f1 | sed "s/ //g"
if [ -n "$IRQ" ]; then
set_affinity
fi
fi
done
done
done
这里涵盖的知识比较多,但如果你接触IT这一行,服务方面的知识迟早会用到。负载均衡或者冗余链路这种思想,是每个公司的要求。
毕竟如果机器或者服务器宕掉,生产的业务怎么办?存储的数据怎么办?随便一种都是大事件。