轉載:https://blog.csdn.net/moonpure/article/details/52839132
LVS之一:三種工作模式的優缺點比較(NAT/TUN/DR)
一、Virtual server via NAT(VS-NAT)
優點:集群中的物理服務器可以使用任何支持TCP/IP操作系統,物理服務器可以分配Internet的保留私有地址,只有負載均衡器需要一個合法的IP地址。
缺點:擴展性有限。當服務器節點(普通PC服務器)數據增長到20個或更多時,負載均衡器將成為整個系統的瓶頸,因為所有的請求包和應答包都需要經過負載均衡器再生。假使TCP包的平均長度是536字節的話,平均包再生延遲時間大約為60us(在Pentium處理器上計算的,采用更快的處理器將使得這個延遲時間變短),負載均衡器的最大容許能力為8.93M/s,假定每臺物理服務器的平臺容許能力為400K/s來計算,負責均衡器能為22臺物理服務器計算。
解決辦法:即使是是負載均衡器成為整個系統的瓶頸,如果是這樣也有兩種方法來解決它。一種是混合處理,另一種是采用Virtual Server via IP tunneling或Virtual Server via direct routing。如果采用混合處理的方法,將需要許多同屬單一的RR DNS域。你采用Virtual Server via IP tunneling或Virtual Server via direct routing以獲得更好的可擴展性。也可以嵌套使用負載均衡器,在最前端的是VS-Tunneling或VS-Drouting的負載均衡器,然后后面采用VS-NAT的負載均衡器。
二、Virtual server via IP tunneling(VS-TUN)
我們發現,許多Internet服務(例如WEB服務器)的請求包很短小,而應答包通常很大。
優點:負載均衡器只負責將請求包分發給物理服務器,而物理服務器將應答包直接發給用戶。所以,負載均衡器能處理很巨大的請求量,這種方式,一臺負載均衡能為超過100臺的物理服務器服務,負載均衡器不再是系統的瓶頸。使用VS-TUN方式,如果你的負載均衡器擁有100M的全雙工網卡的話,就能使得整個Virtual Server能達到1G的吞吐量。
不足:但是,這種方式需要所有的服務器支持"IP Tunneling"(IP Encapsulation)協議,我僅在Linux系統上實現了這個,如果你能讓其它操作系統支持,還在探索之中。
三、Virtual Server via Direct Routing(VS-DR)
優點:和VS-TUN一樣,負載均衡器也只是分發請求,應答包通過單獨的路由方法返回給客戶端。與VS-TUN相比,VS-DR這種實現方式不需要隧道結構,因此可以使用大多數操作系統做為物理服務器,其中包括:Linux 2.0.36、2.2.9、2.2.10、2.2.12;Solaris 2.5.1、2.6、2.7;FreeBSD 3.1、3.2、3.3;NT4.0無需打補丁;IRIX 6.5;HPUX11等。
不足:要求負載均衡器的網卡必須與物理網卡在一個物理段上
LVS之二:負載均衡調度算法
前面的文章介紹了LVS的三種模式:NAT、TUN、DR,那這三種模式下,如果進行負載均衡調度計算呢?這就涉及到新的知識點:負載均衡調度算法
目前LVS主要有三種請求轉發方式和10種調度算法?根據請求轉發方式的不同,所構架集群的網絡拓撲?安裝方式?性能表現也各不相同?用LVS主要可以架構三種形式的集群,分別是LVS/NAT?LVS/TUN和LVS/DR,可以根據需要選擇其中一種?在選定轉發方式的情況下,采用哪種調度算法將決定整個負載均衡的性能表現,不同的算法適用于不同的應用場合,有時可能需要針對特殊場合,自行設計調度算法?LVS的算法是逐漸豐富起來的,最初LVS只提供4種調度算法,后來發展到以下10種。
調度器通過“輪叫"調度算法將外部請求按順序輪流分配到集群中的真實服務器上,它均等地對待每一臺服務器,而不管服務器上實際的連接數和系統負載?
1.2 加權輪叫(Weighted Round Robin,WRR)
調度器通過“加權輪叫"調度算法根據真實服務器的不同處理能力來調度訪問請求?這樣可以保證處理能力強的服務器能處理更多的訪問流量?調度器可以自動問詢真實服務器的負載情況,并動態地調整其權值?
1.3 目標地址散列(Destination Hashing,DH)
“目標地址散列"調度算法根據請求的目標IP地址,作為散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空?主要用于緩存服務器的場景。
“源地址散列"調度算法根據請求的源IP地址,作為散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空?在沒有使用session共享的又需要保存session的環境下(如電子商務網站),建議使用此算法。
2.1 最少鏈接(Least Connections,LC)
調度器通過“最少連接"調度算法動態地將網絡請求調度到已建立的鏈接數最少的服務器上?如果集群系統的真實服務器具有相近的系統性能,采用“最小連接"調度算法可以較好地均衡負載?其具體算法為:
active*256+inactive
然后挑選服務器中上述值最小者分配新連接。
2.2 加權最少鏈接(Weighted Least Connections,WLC)
在集群系統中的服務器性能差異較大的情況下,調度器采用“加權最少鏈接"調度算法優化負載均衡性能,具有較高權值的服務器將承受較大比例的活動連接負載?調度器可以自動問詢真實服務器的負載情況,并動態地調整其權值?WLC為LVS的默認調度算法。其具體算法為:
(active*256+inactive)/weight
然后挑選服務器根據上述方法計算數字最小者分配新連接。
2.3 基于局部性的最少鏈接(Locality-Based Least Connections,LBLC)
“基于局部性的最少鏈接"調度算法是針對目標IP地址的負載均衡,目前主要用于Cache集群系統?該算法根據請求的目標IP地址找出該目標IP地址最近使用的服務器,若該服務器是可用的且沒有超載,將請求發送到該服務器;若服務器不存在,或者該服務器超載且有服務器處于一半的工作負載,則用“最少鏈接"的原則選出一個可用的服務器,將請求發送到該服務器?
類似于DH算法,不同的是,其結合了DH算法和LC算法的優勢。
2.4 帶復制的基于局部性最少鏈接(Locality-Based Least Connections with Replication,LBLCR)
“帶復制的基于局部性最少鏈接"調度算法也是針對目標IP地址的負載均衡,目前主要用于Cache集群系統?它與LBLC算法的不同之處是它要維護從一個目標IP地址到一組服務器的映射,而LBLC算法維護從一個目標IP地址到一臺服務器的映射?該算法根據請求的目標IP地址找出該目標IP地址對應的服務器組,按“最小連接"原則從服務器組中選出一臺服務器,若服務器沒有超載,將請求發送到該服務器;若服務器超載,則按“最小連接"原則從這個集群中選出一臺服務器,將該服務器加入到服務器組中,將請求發送到該服務器?同時,當該服務器組有一段時間沒有被修改,將最忙的服務器從服務器組中刪除,以降低復制的程度?
2.5 最短的期望的延遲(Shortest Expected Delay Scheduling,SED)
“最短的期望的延遲”是基于WLC算法的,只是其計算方法不同。具體算法如下:
(active+1)*256/weight
2.6?最少隊列(Never Queue Scheduling,NQ)
無需隊列。如果有臺 realserver的連接數=0就直接分配過去,不需要在進行SED運算。如果沒有服務器連接數為空閑,則使用SED算法。
了解這些算法原理能夠在特定的應用場合選擇最適合的調度算法,從而盡可能地保持Real Server的最佳利用性?
LVS之三:ipvsadm常用管理命令介紹
LVS全稱為Linux Virtual Server,工作在ISO模型中的第四層,由于其工作在第四層,因此與iptables類似,必須工作在內核空間上。因此lvs與iptables一樣,是直接工作在內核中的,叫ipvs,主流的linux發行版默認都已經集成了ipvs,因此用戶只需安裝一個管理工具ipvsadm即可。
[root@lvs ~]# grep -i "ip_vs" /boot/config-2.6.32-358.18.1.el6.x86_64
CONFIG_IP_VS=m
CONFIG_IP_VS_IPV6=y
# CONFIG_IP_VS_DEBUG is not set
CONFIG_IP_VS_TAB_BITS=12
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
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
CONFIG_IP_VS_FTP=m
[root@lvs ~]# yum -y install ipvsadm
# ipvs -A -t|u|f service-address [-s scheduler]
-t: TCP協議的集群
-u: UDP協議的集群
service-address:???? IP:PORT
-f: FWM: 防火墻標記
service-address: Mark Number
[root@lvs ~]# ipvsadm -A -t 172.16.1.253:80 -s wlc
# ipvs -E -t|u|f service-address [-s scheduler]
[root@lvs ~]# ipvsadm -E -t 172.16.1.253:80-s wrr
# ipvsadm -D -t|u|f service-address
[root@lvs ~]# ipvsadm -D -t 172.16.1.253:80
# ipvsadm -a -t|u|f service-address -r server-address [-g|i|m] [-w weight]
-t|u|f service-address:事先定義好的某集群服務
-r server-address: 某RS的地址,在NAT模型中,可使用IP:PORT實現端口映射;
[-g|i|m]: LVS類型
-g: DR
-i: TUN
-m: NAT
[-w weight]: 定義服務器權重
[root@lvs ~]# ipvsadm -a -t 172.16.1.253:80 -r 172.16.1.101 –g -w 5
[root@lvs ~]# ipvsadm -a -t 172.16.1.253:80 -r 172.16.1.102 –g -w 10
# ipvsadm -e -t|u|f service-address -r server-address [-g|i|m] [-w weight]
[root@lvs ~]# ipvsadm-e-t 172.16.1.253:80 -r 172.16.1.101 –g -w3
# ipvsadm -d -t|u|f service-address -r server-address
[root@lvs ~]# ipvsadm -d -t 172.16.1.253:80 -r 172.16.1.101
# ipvsadm -L|l [options]
-n: 數字格式顯示主機地址和端口
--stats:統計數據
--rate: 速率
--timeout: 顯示tcp、tcpfin和udp的會話超時時長
-c: 顯示當前的ipvs連接狀況
# ipvsadm -C
該命令與iptables的-F功能類似,執行后會清除所有規則。
# service ipvsadm save
# ipvsadm -S > /path/to/somefile
[root@lvs ~]# service ipvsadm save
ipvsadm: Saving IPVS table to /etc/sysconfig/ipvsadm:????? [確定]
# ipvsadm -R < /path/form/somefile
關于時間同步:各節點間的時間偏差不大于1s,建議使用統一的ntp服務器進行更新時間;
DR模型中的VIP的MAC廣播問題:
在DR模型中,由于每個節點均要配置VIP,因此存在VIP的MAC廣播問題,在現在的linux內核中,都提供了相應kernel 參數對MAC廣播進行管理,具體如下:
0:只要本地配置的有相應地址,就給予響應;
??? 1:僅在請求的目標地址配置在到達的接口上的時候,才給予響應;DR模型使用
arp_announce:定義將自己地址向外通告時的通告級別;
0:將本地任何接口上的任何地址向外通告;
1:試圖僅向目標網絡通告與其網絡匹配的地址;
??? 2:僅向與本地接口上地址匹配的網絡進行通告;DR模型使用
LVS之四:DR模型實現
使用iptables實現NAT配置較為簡單,主要如下:
[root@router ~]# echo 1 >/proc/sys/net/ipv4/ip_forward
如果需永久修改,則需要修改sysctl.conf文件。并使用sysctl -p 使其立即生效。
[root@router ~]# iptables –F
[root@router ~]# iptables -t nat -A POSTROUTING -o eth0 -s 172.16.1.0/24 -j SNAT --to 192.168.8.254
[root@router ~]# iptables -t nat -A PREROUTING -d 192.168.8.254 -p tcp --dport 80 -j DNAT --to-destination 172.16.1.253:80
##為了方便使用ssh客戶端連接,我還將lvs集群中各服務器的22端口映射到了不同端口,具體如下:
[root@router ~]# iptables -t nat -A PREROUTING -d 192.168.8.254 -p tcp --dport2022-j DNAT --to-destination172.16.1.252:22
[root@router ~]# iptables -t nat -A PREROUTING -d 192.168.8.254 -p tcp --dport2122-j DNAT --to-destination172.16.1.101:22
[root@router ~]# iptables -t nat -A PREROUTING -d 192.168.8.254 -p tcp --dport2222-j DNAT --to-destination172.16.1.102:22
[root@router ~]# iptables -A FORWARD -p ip -j ACCEPT
[root@router ~]# service iptables save
此時,Director和RealServer都已可以正常訪問外網。
1.3 配置本地windows,添加路由使其能訪問lvs集群:
由于試驗中物理主機(windows)和試驗用路由器(linux)的默認網關指向的是真實的路由器,因此物理主機(windows)是無法訪問lvs集群網絡的,為了能讓物理機(windows)訪問到集群網絡方便后面測試,因此需要添加路由,命令如下:
C:\windows\system32>route add 172.16.1.0/24 192.168.8.254
操作完成!
[root@lvs ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
如果想永久生效,則需要修改/etc/sysctl.conf文件。
[root@lvs ~]# route add -host 172.16.1.253 dev eth0:0
[root@lvs ~]# ifconfig eth0:1 172.16.1.253 netmask 255.255.255.255 up
[root@lvs ~]# iptables -F
[root@lvs ~]# iptables -Z
[root@lvs ~]# ipvsadm -C
[root@lvs ~]# ipvsadm -A -t 172.16.1.253:80 -s wlc
[root@lvs ~]# ipvsadm -a -t 172.16.1.253:80 -r 172.16.1.101 -g
[root@lvs ~]# ipvsadm -a -t 172.16.1.253:80 -r 172.16.1.102 -g
2.6 將上述過程編寫為一個服務腳本,直接在Director上實現開機啟動:
#!/bin/bash
#
# LVS script for VS/DR
# chkconfig: - 90 10
#
. /etc/rc.d/init.d/functions
#
VIP=172.16.1.253
DIP=172.16.1.252
RIP1=172.16.1.101
RIP2=172.16.1.102
PORT=80
RSWEIGHT1=5
RSWEIGHT2=5
#
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 $RSWEIGHT1
/sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -g -w $RSWEIGHT2
/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:0 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
將上述內容保存在/etc/init.d/lvs-director文件中,然后添加到服務:
[root@lvs ~]# chmod +x /etc/init.d/lvs-director
[root@lvs ~]# chkconfig --add lvs-director
[root@lvs ~]# chkconfig lvs-director on
[root@lvs ~]# /etc/init.d/lvs-director start
[root@lvs ~]# /etc/init.d/lvs-director status
ipvs is running ...
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port?????????? Forward Weight ActiveConn InActConn
TCP? 172.16.1.253:80 wlc
-> 172.16.1.101:80????????????? Route?? 5????? 0????????? 0
-> 172.16.1.102:80????????????? Route?? 5????? 0????????? 0
[root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@rs1 ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@rs1 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@rs1 ~]# ifconfig lo:0 172.16.1.253 netmask 255.255.255.255 up
[root@rs1 ~]# route add -host 172.16.1.253 dev lo:0
#!/bin/bash
#
# Script to start LVS DR real server.
# chkconfig: - 90 10
# description: LVS DR real server
#
.? /etc/rc.d/init.d/functions
VIP=172.16.1.253
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
保存至/etc/init.d/lvs-rs,并賦予執行權限,然后添加為開機啟動:
[root@rs1~]# chmod +x /etc/init.d/lvs-rs
[root@rs1 ~]# chkconfig --add lvs-rs
[root@rs1 ~]# chkconfig lvs-rs on
[root@rs1 ~]# /etc/init.d/lvs-rs start
至此就全部完成了lvs的DR模型配置。
[root@rs1 ~]# service httpd start
正在啟動 httpd:httpd: apr_sockaddr_info_get() failed for rs1
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
[確定]
[root@rs1 ~]# echo "This is RS1..." >/var/www/html/index.html
[root@rs2 ~]# echo "This is RS2..." >/var/www/html/index.html
訪問時觀察ipvs狀態:
Every 1.0s: ipvsadm -L -n??????????????????????????????????????????????????????????????????????? Tue Oct? 8 19:58:42 2013
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port?????????? Forward Weight ActiveConn InActConn
TCP? 172.16.1.253:80 wlc
-> 172.16.1.101:80????????????? Route?? 5???? 2????????? 8
-> 172.16.1.102:80????????????? Route?? 5???? 1????????? 8
LVS之五:使用腳本實現RealServer的健康檢查
上文部署的DR模型中,當一臺RS宕機時,ipvs是不會自動踢出該RS服務器的,我這里使用一個腳本實現對RS的監控檢查。
腳本要能判斷RS運行情況;
當RS的web服務不能訪問時,將其從lvs集群中踢出;而當RS重新上線時,再將其加入lvs集群;
定時檢查(死循環或cron計劃任務);
對RS的下線和上線做日志記錄。
使用curl能簡單的實現對web應用可用性進行監控:
curl命令選項:
--cacert CA證書 (SSL)
--capath CA目錄 (made using c_rehash) to verify peer against (SSL)
--compressed 要求返回是壓縮的形勢 (using deflate or gzip)
--connect-timeout 設置最大請求時間
-H/--header 自定義頭信息傳遞給服務器
-i/--include 輸出時包括protocol頭信息
-I/--head 只顯示文檔信息
--interface 使用指定網絡接口/地址
-s/--silent靜音模式。不輸出任何東西
-u/--user 設置服務器的用戶和密碼
-p/--proxytunnel 使用HTTP代理
#!/bin/bash
#
VIP=192.168.8.254
CPORT=80
##使用數組RS定義所有RS服務器
RS=("172.16.1.101" "172.16.1.102")
#定義RS狀態,后面引用
declare -a RSSTATUS
#定義權重
RW=("5" "5")
RPORT=80
#集群類型為DR
TYPE=g
CHKLOOP=3
#監控日志
LOG=/var/log/ipvsmonitor.log
#
#addrs函數在RS重新上線時將其添加到集群
addrs() {
ipvsadm -a -t $VIP:$CPORT -r $1:$RPORT -$TYPE -w $2
[ $? -eq 0 ] && return 0 || return 1
}
#delrs函數在RS下線時將其從集群中刪除
delrs() {
ipvsadm -d -t $VIP:$CPORT -r $1:$RPORT
[ $? -eq 0 ] && return 0 || return 1
}
#checkrs檢查RS狀態,如果上次均為離線狀態,則判定其為離線
checkrs() {
local I=1
while [ $I -le $CHKLOOP ]; do
if curl --connect-timeout 1http://$1&> /dev/null; then
return 0
fi
let I++
done
return 1
}
#初始化RS狀態函數
initstatus() {
local I
local COUNT=0;
for I in ${RS[*]}; do
if ipvsadm -L -n | grep "$I:$RPORT" && > /dev/null ; then
RSSTATUS[$COUNT]=1
else
RSSTATUS[$COUNT]=0
fi
let COUNT++
done
}
#執行初始化RS狀態檢查函數
initstatus
#死循環
while :; do
let COUNT=0
for I in ${RS[*]}; do
if checkrs $I; then
if [ ${RSSTATUS[$COUNT]} -eq 0 ]; then
addrs $I ${RW[$COUNT]}
[ $? -eq 0 ] && RSSTATUS[$COUNT]=1 && echo "`date +'%F %H:%M:%S'`, $I is back." >> $LOG
fi
else
if [ ${RSSTATUS[$COUNT]} -eq 1 ]; then
delrs $I
[ $? -eq 0 ] && RSSTATUS[$COUNT]=0 && echo "`date +'%F %H:%M:%S'`, $I is gone." >> $LOG
fi
fi
let COUNT++
done
sleep 5
done
LVS之六:使用keepalived實現LVS的DR模式熱備
在《LVS之一:三種工作模式的優缺點比較(NAT/TUN/DR)》文章講述了LVS的三種轉發模式對比,我們先就用LVS的DR模式來實現Web應用的負載均衡。為了防止LVS服務器自身的單點故障導致整個Web應用無法提供服務,因此還得利用Keepalived實現lvs的高可用性,keepalived主要使用VRRP協議來保存鏈路的高可用性。而VRRP(Virtual Router Redundancy Protocol)協議本身是用于實現路由器冗余的協議。
LVS-DR模式的原理如下(借用別人的圖):
1、? LVS服務器和WEB服務器必須在同一網段;
2、? 多臺Web服務器間使用NFS服務器等共享存儲存放用戶上傳附件,以保障數據的一致性(如上傳圖片)。下文討論
IP地址規劃:
VIP ??????? ?????192.168.18.60
LVS-MASTER???? 192.168.18.51
LVS-BACKUP???? 192.168.18.52
NFS?? Server?????? 192.168.18.20
MySQL?????????????? 192.168.18.18
WEB1??????? 192.168.18.61
WEB2??????? 192.168.18.62
[root@lvs1 ~]# yum install ipvsadm ?keepalived –y
[root@lvs1 ~]# rpm -qa |grep ipvsadm
ipvsadm-1.25-10.el6.x86_64
[root@lvs1 ~]# rpm -qa |grep keepalived
keepalived-1.2.7-3.el6.x86_64
[root@lvs1 ~]# chkconfig keepalived on?? ##設置為開機啟動
[root@lvs1 ~]# service keepalived start?? ##立即啟動keepalived服務
[root@lvs1 ~]# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.bak
原始的配置文件包含了三種模式的配置,而這里我們只需要用到DR模式,因此最終保留配置如下:
[root@lvs1 ~]#? vim /etc/keepalived/keepalived.conf
global_defs {?????????????????????? ##全局配置部分
#?? notification_email {???????????? ##下面幾行均為全局通知配置,可以實現出現問題后報警,但功能有限,因此注釋掉,并采用Nagios監視lvs運行情況
#?????? admin@toxingwang.com
#?? }
#?? notification_email_from master@toxingwang.com
#?? smtp_server smtp.exmail.qq.com
#?? smtp_connect_timeout 30
router_id LVS_MASTER???????? ????##設置lvs的id,在一個網絡內應該是唯一的
}
vrrp_instance VI_1 {??????????? ##設置vrrp組,唯一且同一LVS服務器組要相同
stateMASTER??##備份LVS服務器設置為BACKUP
interface eth0???????????? # #設置對外服務的接口
virtual_router_id 51??????? ##設置虛擬路由標識
priority 100??????????????????????????????????? #設置優先級,數值越大,優先級越高,backup設置為99,這樣就能實現當master宕機后自動將backup變為master,而當原master恢復正常時,則現在的master再次變為backup。
advert_int 1??????????? ##設置同步時間間隔
authentication {???????? ##設置驗證類型和密碼,master和buckup一定要設置一樣
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {????????? ##設置VIP,可以多個,每個占一行
192.168.18.60
}
}
virtual_server 192.168.18.60 80 {
delay_loop 6??????????? ##健康檢查時間間隔,單位s
lb_algo wrr???????????? ##負載均衡調度算法設置為加權輪叫
lb_kind DR??????????????????????????? ? ##負載均衡轉發規則
nat_mask 255.255.255.0?? ##網絡掩碼,DR模式要保障真是服務器和lvs在同一網段
persistence_timeout 50??? ##會話保持時間,單位s
protocol TCP??????????????????????? ?? ##協議
real_server 192.168.18.61 80 {????? ##真實服務器配置,80表示端口
weight 3 ???????????????????????????? ##權重
TCP_CHECK {?????????????????????? ##服務器檢測方式設置
connect_timeout 5??? ##連接超時時間
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
real_server 192.168.18.62 80 {
weight 3
TCP_CHECK {
connect_timeout 10
nb_get_retry 3
delay_before_retry 3
connect_port 80
}
}
}
作為高可用的備份lvs服務器配置只需在上述配置中的master修改backup即可,其他保持相同。
[root@lvs1 ~]# service keepalived start
注:由于keepalived配置文件有語法錯誤也能啟動,因此看到啟動了lvs服務,不代表配置文件沒有錯誤,如果遇到lvs不能正常轉發,及時跟蹤日志進行處理。
日志跟蹤方法:
1、開兩個ssh窗口連接到lvs服務器,第一個窗口運行如下命令:
[root@lvs1 ~]#?tail -F /var/log/message
2、第二個窗口重新啟動keepalived服務,同時觀察窗口1中日志的變化,然后根據日志提示解決即可。
在兩臺WEB服務器安裝并配置(非本文重點,不做web安裝配置講解),建立測試網頁,先使用實際IP進行訪問測試,能正常訪問后,進行如下操作:
在前面的文章中介紹DR模式時提到:負載均衡器也只是分發請求,應答包通過單獨的路由方法返回給客戶端。但實際上客戶端訪問時,IP都是指向的負載均衡器的ip(也就是LVS的VIP),如何能讓真是服務器處理IP頭為VIP的請求,這就需要做下面的操作,將VIP綁定到真實服務器的lo網口(回環),為了防止IP廣播產生IP沖突,還需關閉IP廣播,具體如下:
? [root@web1 ~]# vim /etc/init.d/realserver
#!/bin/bash
#chkconfig: 2345 79 20
#description:realserver
SNS_VIP=192.168.18.60
. /etc/rc.d/init.d/functions
case "$1" in
start)
ifconfig lo:0 $SNS_VIP netmask 255.255.255.255 broadcast $SNS_VIP
/sbin/route add -host $SNS_VIP dev lo:0
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
sysctl -p >/dev/null 2>&1
echo "RealServer Start OK"
;;
stop)
ifconfig lo:0 down
route del $SNS_VIP >/dev/null 2>&1
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
echo "RealServer Stoped"
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
exit 0
arp_ignore: 定義接收到ARP請求時的響應級別;
0:只要本地配置的有相應地址,就給予響應;默認;
1:僅在請求的目標地址配置在到達的接口上的時候,才給予響應;
arp_announce:定義將自己地址向外通告時的通告級別;
0:將本地任何接口上的任何地址向外通告;默認;
1:試圖僅向目標網絡通告與其網絡匹配的地址;
2:僅向與本地接口上地址匹配的網絡進行通告;
[root@web1 ~]# chkconfig realserver on
[root@web1 ~]# service realserver start
RealServer Start OK
[root@web1 ~]# ifconfig
eth0????? Link encap:Ethernet? HWaddr 00:50:56:B3:54:5A
inet addr:192.168.18.61? Bcast:192.168.18.255? Mask:255.255.255.0
inet6 addr: fe80::250:56ff:feb3:545a/64 Scope:Link
UP BROADCAST RUNNING MULTICAST? MTU:1500? Metric:1
RX packets:98940 errors:4 dropped:4 overruns:0 frame:0
TX packets:82037 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:23077218 (22.0 MiB)? TX bytes:16043349 (15.3 MiB)
Interrupt:18 Base address:0x2000
lo??????? Link encap:Local Loopback
inet addr:127.0.0.1? Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING? MTU:16436? Metric:1
RX packets:300 errors:0 dropped:0 overruns:0 frame:0
TX packets:300 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:528420 (516.0 KiB)? TX bytes:528420 (516.0 KiB)
lo:0????? Link encap:Local Loopback
inet addr:192.168.18.60?Mask:255.255.255.255
UP LOOPBACK RUNNING? MTU:16436? Metric:1
在lvs master服務器上運行如下命令:
[root@lvs1 ~]# watch -n 1 ipvsadm -ln
在多臺客戶端通過瀏覽器訪問VIP或域名(域名需解析到VIP),看能否獲取到正確的頁面,且同時觀察上述窗口的變化。
從上圖(為了方便觀察,使用了壓力測試)可以看出,訪問被正常的分擔到了兩臺后端web服務器 。
1、用戶新上傳的附件存放問題;目前我們采用的是NFS方式解決,但存在單點故障,需要配合其他方式解決。NFS的基本用法請參考《NFS的配置和使用》
2、后端數據庫高可用性;
3、會話共享和保持問題(Session共享);算法調整為SH可解決,但有RealServer宕機時,其上的session也會丟失。后期將調整為實現共享session。
LVS之七:使用持久連接解決session問題
前面在討論LVS算法中,SH算法可以實現將同一客戶端的請求總是發送給第一次指定的RS,除非該RS出現故障不能再提供服務。其實在LVS集群中,持久連接功能也能在一定時間內,將來自同一個客戶端請求派發至此前選定的RS,而且是無關算法的。
在基于SSL的加密https協議中,特別需要用到持久連接,因為客戶端需要與服務器進行交換證書并協商加密算法等。
如果一個集群中提供了兩種服務,持久連接會將同一客戶端的所有請求都同步到同一RS。持久連接分三種:
PPC(持久端口連接):將來自于同一個客戶端對同一個集群服務的請求,始終定向至此前選定的RS;
PCC(持久客戶端連接):將來自于同一個客戶端對所有端口的請求,始終定向至此前選定的RS;PCC是把所有端口統統定義為集群服務,一律向RS轉發;
PNMPP:持久防火墻標記連接。使用iptables的標記功能,可以實現給多個服務(端口)打上相同的標記,然后在ipvsadm使用-f選項,并使用上述防火墻標記即可將多個服務放到一個LVS集群中。實現過程如下:
# iptables -t mangle -A PREROUTING -d 192.168.8.253 -p tcp --dport 80 -i $INCARD -j MARK --set-mark10
# iptables -t mangle -A PREROUTING -d 192.168.8.253 -p tcp --dport 443 -i $INCARD -j MARK --set-mark10
# ipvsadm -A -f10-s wlc –p 600
LVS的持久連接又集群的持久連接模板(一個內存緩沖區)提供;該持久連接模板保存著每一個客戶端及分配給它的RS的映射關系。使用如下命令可以查看該模板:
[root@lvs ~]#ipvsadm -L -c
IPVS connection entries
pro expire state?????? source???????????? virtual??????????? destination
TCP 01:56? FIN_WAIT??? 192.168.8.12:51822 172.16.1.253:http? 172.16.1.102:http
TCP 01:57? FIN_WAIT??? 192.168.8.12:51825 172.16.1.253:http? 172.16.1.101:http
TCP 01:56? FIN_WAIT??? 192.168.8.12:51821 172.16.1.253:http? 172.16.1.101:http
TCP 01:42? FIN_WAIT??? 192.168.8.12:51814 172.16.1.253:http? 172.16.1.102:http
TCP 01:57? FIN_WAIT??? 192.168.8.12:51826 172.16.1.253:http? 172.16.1.102:http
TCP 01:57? FIN_WAIT??? 192.168.8.12:51824 172.16.1.253:http? 172.16.1.102:http
TCP 01:56? FIN_WAIT??? 192.168.8.12:51820 172.16.1.253:http? 172.16.1.102:http
TCP 14:58? ESTABLISHED 192.168.8.12:51828 172.16.1.253:http? 172.16.1.102:http
TCP 01:55? FIN_WAIT??? 192.168.8.12:51815 172.16.1.253:http? 172.16.1.101:http
TCP 01:56? FIN_WAIT??? 192.168.8.12:51823 172.16.1.253:http? 172.16.1.101:http
TCP 01:57? FIN_WAIT??? 192.168.8.12:51827 172.16.1.253:http? 172.16.1.101:http
ipvsadm -A|E ... -p timeout
timeout: 持久連接時長,默認300秒;單位是秒;
在使用《LVS之四:DR模型實現》中的lvs集群,每次刷新客戶端時,都會在RS1和RS2上切換。如下圖:
[root@lvs ~]# 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.1.253:80 wlc
-> 172.16.1.101:80????????????? Route?? 5????? 0????????? 1
-> 172.16.1.102:80????????????? Route?? 5????? 0????????? 2
[root@lvs ~]# ipvsadm -E -t 172.16.1.253:80 -p 600
[root@lvs ~]# 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.1.253:80 wlc persistent 600
-> 172.16.1.101:80????????????? Route?? 5????? 0????????? 0
-> 172.16.1.102:80????????????? Route?? 5????? 0????????? 1
此時再次刷新客戶端,會發現已經不會再改變RS。
[root@lvs ~]# ipvsadm -L --persistent-conn
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port??????????? Weight??? PersistConn ActiveConn InActConn
-> RemoteAddress:Port
TCP? 172.16.1.253:http wlc persistent 600
-> 172.16.1.101:http??????????? 5???????? 0?????????? 0????????? 0
->172.16.1.102:http??????????? 5???????? 1?????????? 0????????? 14