一、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"