一、LVS相关概念简介
LVS:Linux Virtual Server 负载调度器,集成于内核
作者:章文嵩
官网:http://www.linuxvirtualserver.org/
VS: Virtual Server ,Director Server(DS) ,Dispatcher(调度器),Load Balancer 负责调度
RS: Real Server(lvs),upstream server(nginx),backend server(haproxy) 真正提供服务器
L4:四层路由器或交换机
工作原理:VS根据请求报文的目标IP和目标协议及端口将其调度转发至某RS,根据调度算法来挑选RS
lvs:ipvsadm/ipvs
- ipvsadm:用户空间的命令行工具,规则管理器,用于管理集群服务及RealServer
- ipvs:工作于内核空间netfilter的INPUT钩子上的框架
lvs集群的类型:
- lvs-nat:修改请求报文的目标IP ,多目标IP的DNAT
- lvs-dr:操纵封装新的MAC地址
- lvs-tun:在原请求IP报文之外新加一个IP首部
- lvs-fullnat:修改请求报文的源和目标IP
二、LVS-NAT地址转换模式
nat模式的本质是多目标IP的DNAT,通过将请求报文中的目标地址和目标端口修改为某挑出的RS的RIP和PORT实现转发
特性:
- 集群节点和director应该在同一个IP网络中
- RIP地址通常都是私有地址,仅用于各集群节点之间通信
- director位于client和real server之间,并负责处理进出的所以通信
- real server必须将网关指向DIP
- director支持端口映射
- real server可以使用任意操作系统
- 较大规模应用场景中,director易成为整个集群的瓶颈,大约10个real server
lvs-NAT架构的实现:
1)client 最后测试
[root@centos7 ~]# for i in {1..10}; do curl 172.20.127.114 ;done
wolcome to rs1
wolcome to rs3
wolcome to rs2
wolcome to rs1
wolcome to rs3
wolcome to rs2
wolcome to rs1
wolcome to rs3
wolcome to rs2
wolcome to rs1
2)DS
[root@ds ~]# echo net.ipv4.ip_forward = 1 >> /etc/sysctl.conf
[root@ds ~]# sysctl -p
[root@ds ~]# yum install ipvsadm -y
[root@ds ~]# ipvsadm -A -t 172.20.127.114:80 -s rr
[root@ds ~]# ipvsadm -a -t 172.20.127.114:80 -r 192.168.0.10 -m
[root@ds ~]# ipvsadm -a -t 172.20.127.114:80 -r 192.168.0.11 -m
[root@ds ~]# ipvsadm -a -t 172.20.127.114:80 -r 192.168.0.12 -m
[root@ds ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.20.127.114:80 rr
-> 192.168.0.10:80 Masq 1 0 0
-> 192.168.0.11:80 Masq 1 0 0
-> 192.168.0.12:80 Masq 1 0 0
RS状态检测脚本
#!/bin/bash
#
rip1=192.168.0.10
rip2=192.168.0.11
rip3=192.168.0.12
vip=172.20.127.114
scheduler=rr
port=80
testsite="index.html"
timeinterval=1
lvstart() {
echo 1 > /proc/sys/net/ipv4/ip_forward
ipvsadm -A -t $vip:$port -s $scheduler
ipvsadm -a -t $vip:$port -r $rip1 -m
ipvsadm -a -t $vip:$port -r $rip2 -m
ipvsadm -a -t $vip:$port -r $rip3 -m
}
lvstop() {
echo 0 > /proc/sys/net/ipv4/ip_forward
ipvsadm -C
}
check() {
while :; do
nowtime=`date +%S |awk -F '' '{print $2}'`
for i in $rip1 $rip2 $rip3; do
if curl http://$i/$testsite &>/dev/null; then
[ "$nowtime" -eq 0 ] && echo "`date +%F-%T` $i online" >> /var/log/lvs_rs_state.log
ipvsadm -Ln |grep -q $i || ipvsadm -a -t $vip:$port -r $i -m
else
[ "$nowtime" -eq 0 ] && echo "`date +%F-%T` $i offline" >> /var/log/lvs_rs_state.log
ipvsadm -Ln |grep -q $i && ipvsadm -d -t $vip:$port -r $i
fi
done
sleep $timeinterval
done
}
case $1 in
start) lvstart;;
stop) lvstop;;
check) check;;
*) echo "Usage: `basename $0` start|stop|check"
esac
3)RS1
[root@r1 ~]# yum install httpd -y
[root@r1 ~]# systemctl enable httpd
[root@r1 ~]# echo "wolcome to rs1" > /var/www/html/index.html
[root@r1 ~]# systemctl start httpd
4)RS2
[root@r2 ~]# yum install httpd -y
[root@r2 ~]# systemctl enable httpd
[root@r2 ~]# echo "wolcome to rs2" > /var/www/html/index.html
[root@r2 ~]# systemctl start httpd
5)RS3
[root@r3 ~]# yum install httpd -y
[root@r3 ~]# systemctl enable httpd
[root@r3 ~]# echo "wolcome to rs3" > /var/www/html/index.html
[root@r3 ~]# systemctl start httpd
三、LVS-DR直接路由模式
Direct Routing,直接路由,LVS默认模式,应用最广泛,通过为请求报文重新封装一个MAC首部进行转发,源MAC是DIP所在的接口的MAC,目标MAC是某挑选出的RS的RIP所在接口的MAC地址;源IP/PORT,以及目标IP/PORT均保持不变
特性:
- 集群节点跟director必须在同一个物理网络中
- RIP可以不用是私有地址了
- director只负责处理入站请求,响应报文则由real server直接发往客户端
- real server不能将网关指向DIP
- director不支持端口映射
- 大多数的操作系统都可以用于real server,因为需要具有隐藏VIP的功能
- 可以支持的real server是NET模型的数十倍
确保前端路由器将目标IP为VIP的请求报文发往Director的方法:
- 在前端网关做静态绑定VIP和Director的MAC地址
- 在RS上使用arptables工具
- 在RS上修改内核参数以限制arp通告及应答级别
/proc/sys/net/ipv4/conf/all/arp_ignore
/proc/sys/net/ipv4/conf/all/arp_announce
限制ARP响应/通告级别:
限制响应级别:arp_ignore
- 0:默认值,表示可使用本地任意接口上配置的任意地址进行响应
- 1: 仅在请求的目标IP配置在本地主机的接收到请求报文的接口上时,才给予响应
限制通告级别:arp_announce
- 0:默认值,把本机所有接口的所有信息向每个接口的网络进行通告
- 1:尽量避免将接口信息向非直接连接网络进行通告
- 2:必须避免将接口信息向非本网络进行通告
lvs-DR架构的实现:
1)client
# firefox http://11.11.11.11
2)router-1
[root@router-1 ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
[root@router-1 ~]# sysctl -p
[root@router-1 ~]# iptables -t nat -A POSTROUTING -s 172.16.0.0/16 ! -d 172.16.0.0/16 -j SNAT --to-source 10.0.0.100
3)DNS
[root@dns ~]# yum install bind -y
[root@dns ~]# vim /etc/named.conf
options {
// listen-on port 53 { 127.0.0.1; };
// listen-on-v6 port 53 { ::1; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
// allow-query { localhost; };
recursion yes;
dnssec-enable yes;
dnssec-validation yes;
bindkeys-file "/etc/named.iscdlv.key";
managed-keys-directory "/var/named/dynamic";
pid-file "/run/named/named.pid";
session-keyfile "/run/named/session.key";
};
[root@dns ~]# vim /etc/named.rfc1912.zones
zone "dongfei.tech" IN {
type master;
file "dongfei.tech.zone";
};
[root@dns ~]# vim /var/named/dongfei.tech.zone
@ IN SOA dns.dongfei.tech. admin.dongfei.tech. ( 1 1D 1H 1W 3H )
NS dns
dns A 10.0.0.114
www A 11.11.11.11
4)router-2
[root@router-2 ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
[root@router-2 ~]# sysctl -p
5)DS
[root@ds ~]# ip a a 11.11.11.11/32 dev eth0
[root@ds ~]# yum install ipvsadm -y
[root@ds ~]# ipvsadm -A -t 11.11.11.11:80 -s rr
[root@ds ~]# ipvsadm -a -t 11.11.11.11:80 -r 192.168.0.13
[root@ds ~]# ipvsadm -a -t 11.11.11.11:80 -r 192.168.0.14
6)httpd-1
[root@httpd-1 ~]# yum install httpd php-fpm php-mysql -y
[root@httpd-1 ~]# systemctl enable httpd php-fpm
[root@httpd-1 ~]# vim /etc/httpd/conf.d/fcgi.conf
DirectoryIndex index.php
ProxyRequests Off
ProxyPassMatch ^/(.*.php)$ fcgi://127.0.0.1:9000/var/www/html/$1
[root@httpd-1 ~]# systemctl start httpd php-fpm
[root@httpd-1 ~]# yum install nfs-utils -y
[root@httpd-1 ~]# vim /etc/fstab
192.168.0.15:/data/www /var/www/html/ nfs defaults,rw 0 0
[root@httpd-1 ~]# mount -a
[root@httpd-1 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@httpd-1 ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@httpd-1 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@httpd-1 ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@httpd-1 ~]# ip a a 11.11.11.11/32 dev lo
7)httpd-2
[root@httpd-2 ~]# yum install httpd php-fpm php-mysql -y
[root@httpd-2 ~]# systemctl enable httpd php-fpm
[root@httpd-2 ~]# vim /etc/httpd/conf.d/fcgi.conf
DirectoryIndex index.php
ProxyRequests Off
ProxyPassMatch ^/(.*.php)$ fcgi://127.0.0.1:9000/var/www/html/$1
[root@httpd-2 ~]# systemctl start httpd php-fpm
[root@httpd-2 ~]# yum install nfs-utils -y
[root@httpd-2 ~]# vim /etc/fstab
192.168.0.15:/data/www /var/www/html/ nfs defaults,rw 0 0
[root@httpd-2 ~]# mount -a
[root@httpd-2 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@httpd-2 ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@httpd-2 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@httpd-2 ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@httpd-2 ~]# ip a a 11.11.11.11/32 dev lo
8)NFS
[root@nfs ~]# yum install nfs-utils -y
[root@nfs ~]# vim /etc/exports
/data/www *(rw)
[root@nfs ~]# mkdir -p /data/www
[root@nfs ~]# chmod 777 /data/www/
[root@nfs ~]# systemctl enable nfs-server
[root@nfs ~]# systemctl start nfs-server
[root@nfs ~]# unzip wordpress-4.9.4-zh_CN.zip
[root@nfs ~]# mv wordpress/* /data/www/
9)mariadb
[root@mariadb ~]# yum install mariadb-server -y
[root@mariadb ~]# systemctl enable mariadb
[root@mariadb ~]# systemctl start mariadb
MariaDB [(none)]> CREATE wpdb;
MariaDB [(none)]> GRANT ALL ON wpdb.* TO wpuser@'192.168.0.%' IDENTIFIED BY 'wppass';
四、LVS-TUN隧道模式
不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而在原IP报文之外再封装一个IP首部(源IP是DIP,目标IP是RIP),将报文发往挑选出的目标RS;RS直接响应给客户端(源IP是VIP,目标IP是CIP)
特性:
- DIP, VIP, RIP都应该是公网地址
- RS的网关一般不能指向DIP
- 请求报文要经由Director,但响应不能经由Director
- 不支持端口映射
- RS的OS须支持隧道功能
五、LVS-FULLNAT模式
通过同时修改请求报文的源IP地址和目标IP地址进行转发
特性:
-
VIP是公网地址,RIP和DIP是私网地址,且通常不在同一IP网络;因此,RIP的网关一般不会指向DIP
-
RS收到的请求报文源地址是DIP,因此,只需响应给DIP;但Director还要将其发往Client
-
请求和响应报文都经由Director
-
支持端口映射
注意:此类型kernel默认不支持
六、scheduler 调度算法
根据其调度时是否考虑各RS当前的负载状态分为动态调度算法和静态调度算法
静态方法:
仅根据算法本身进行调度
1、RR:roundrobin,轮询
2、WRR:Weighted RR,加权轮询
3、SH:Source Hashing,源地址哈希;实现session sticky,源IP地址hash;将来自于同一个IP地址的请求始终发往第一次挑中的RS,从而实现会话绑定
4、DH:Destination Hashing,目标地址哈希;将发往同一个目标地址的请求始终转发至第一次挑中的RS,典型使用场景是正向代理缓存场景中的负载均衡
动态方法:
主要根据每RS当前的负载状态及调度算法进行调度Overhead=value较小的RS将被调度
1、LC:least connections,适用于长连接应用;Overhead=activeconns256+inactiveconns
2、WLC:Weighted LC,默认调度方法;Overhead=(activeconns256+inactiveconns)/weight
3、SED:Shortest Expection Delay,初始连接高权重优先;Overhead=(activeconns+1)*256/weight
4、NQ:Never Queue 永不排队;第一轮均匀分配,后续SED
5、LBLC:Locality-Based LC,动态的DH算法,使用场景:根据负载状态实现正向代理
6、LBLCR:LBLC with Replication,带复制功能的LBLC 解决LBLC负载不均衡问题,从负载重的复制到负载轻的RS
七、ipvsadm/ipvs
ipvs集成kernel中
管理工具包:ipvsadm
主程序:/usr/sbin/ipvsadm
规则保存工具:/usr/sbin/ipvsadm-save -n > ipvs.txt
规则重载工具:/usr/sbin/ipvsadm-restore < ipvs.txt
配置文件:/etc/sysconfig/ipvsadm-config
ipvsadm命令:
增加/修改集群服务:
ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]]
删除集群服务:
ipvsadm -D -t|u|f service-address
- -t:TCP协议的端口,VIP:TCP_PORT
- -u:UDP协议的端口,VIP:UDP_PORT
- -f:firewall MARK,防火墙标记,一个数字
- -s:指定调度方法,默认为wlc
- -p:指定长连接时间
增加/修改RS:
ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight]
删除RS:
ipvsadm -d -t|u|f service-address -r server-address
- -r:指定rs的地址
- -g:gateway, dr类型,默认
- -i:ipip,tun类型
- -m:masquerade,nat类型
- -w:指定权重
清空ipvs规则:
ipvsadm -C
清空计数器:
ipvsadm -Z [-t|u|f service-address]
查看ipvs工作状态:ipvsadm -L|l [options]
- --numeric, -n:以数字形式输出地址和端口号
- --exact:扩展信息,精确值
- --connection,-c:当前IPVS连接输出
- --stats:统计信息
- --rate :输出速率信息
ipvs规则:/proc/net/ip_vs
ipvs连接:/proc/net/ip_vs_conn
八、FireWall Mark
MARK target 可用于给特定的报文打标记,--set-mark value
,其中:value 可为0xffff格式,表示十六进制数字
借助于防火墙标记来分类报文,而后基于标记定义集群服务;可将多个不同的应用使用同一个集群服务进行调度
iptables -t mangle -A PREROUTING -d VIP -p PROTOCOL –m multiport --dports $port1,$port2,… -j MARK --set-mark NUMBER
ipvsadm -A -f NUMBER [options]
实现:
[root@ds ~]# iptables -t mangle -A PREROUTING -d 11.11.11.11 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 10
[root@ds ~]# ipvsadm -A -f 10 -s wlc
[root@ds ~]# ipvsadm -a -f 10 -r 192.168.0.13 -w 2
[root@ds ~]# ipvsadm -a -f 10 -r 192.168.0.14 -w 2
九、持久连接
session 绑定:对共享同一组RS的多个集群服务,需要统一进行绑定,lvs sh算法无法实现
持久连接( lvs persistence )模板:实现无论使用任何调度算法,在一段时间内(默认360s ),能够实现将来自同一个地址的请求始终发往同一个RS
持久连接实现方式:
- 每端口持久(PPC):每个端口对应定义为一个集群服务,每集群服务单独调度
- 每防火墙标记持久(PFWMC):基于防火墙标记定义集群服务;可实现将多个端口上的应用统一调度,即所谓的port Affinity
- 每客户端持久(PCC):基于0端口(表示所有服务)定义集群服务,即将客户端对所有应用的请求都调度至后端主机,必须定义为持久模式
十、ldirectord
监控和控制LVS守护进程,可管理LVS规则
/etc/ha.d/ldirectord.cf 主配置文件
/usr/share/doc/ldirectord-3.9.6/ldirectord.cf 配置模版
/usr/lib/systemd/system/ldirectord.service 服务
/usr/sbin/ldirectord 主程序
/var/log/ldirectord.log 日志
/var/run/ldirectord.ldirectord.pid pid文件
[root@ds ~]# yum install ldirectord-3.9.6-0rc1.1.1.x86_64.rpm
[root@ds ~]# cp /usr/share/doc/ldirectord-3.9.6/ldirectord.cf /etc/ha.d/
[root@ds ~]# vim /etc/ha.d/ldirectord.cf
# Global Directives
checktimeout=3
checkinterval=1
fallback=127.0.0.1:80
#fallback6=[::1]:80
autoreload=yes
logfile="/var/log/ldirectord.log"
#logfile="local0"
#emailalert="admin@x.y.z"
#emailalertfreq=3600
#emailalertstatus=all
quiescent=no
# Sample for an http virtual service
virtual=11.11.11.11:80
real=192.168.0.13:80 gate 1
real=192.168.0.14:80 gate 2
service=http
scheduler=wrr
#persistent=600
#netmask=255.255.255.255
protocol=tcp
checktype=negotiate
checkport=80
request="test.html"
receive="Test Page"
[root@ds ~]# yum install httpd -y
[root@ds ~]# systemctl enable httpd
[root@ds ~]# systemctl start httpd
在每个rs的站点目录下创建test.html测试网页文件,内容为"Test Page"