LVS是Linux Virtual Server的簡稱,也就是Linux虛擬服務器, 是一個由章文嵩博士發起的自由軟件項目,它的官方站點是www.linuxvirtualserver.org。html
如今LVS已是Linux標準內核的一部分,在Linux2.4內核之前,使用LVS時必需要從新編譯內核以支持LVS功能模塊,可是從Linux2.4內核之後,已經徹底內置了LVS的各個功能模塊,無需給內核打任何補丁,能夠直接使用LVS提供的各類功能。前端
LVS主要用於服務器集羣的負載均衡。其優勢有:linux
#工做在網絡層,能夠實現高性能,高可用的服務器集羣技術。 #廉價,可把許多低性能的服務器組合在一塊兒造成一個超級服務器。 #易用,配置很是簡單,且有多種負載均衡的方法。 #穩定可靠,即便在集羣的服務器中某臺服務器沒法正常工做,也不影響總體效果。 #可擴展性也很是好。
linux內核2.4版本以上的基本都支持LVS,要使用lvs,只須要再安裝一個lvs的管理工具:ipvsadmweb
yum install ipvsadm
其實LVS的自己跟iptables很類似,並且連命令的使用格式都很類似,其實LVS是根據iptables的框架開發的,那麼LVS的自己分紅了兩個部分:算法
第一部分是工做在內核空間的一個IPVS的模塊,其實LVS的功能都是IPVS模塊實現的,
第二部分是工做在用戶空間的一個用來定義集羣服務的一個工具ipvsadm, 這個工具的主要做用是將管理員定義的集羣服務列表傳送給工做在內核空間中的IPVS模塊,下面來簡單的介紹下ipvsadm命令的用法
ipvsadm組件定義規則的格式:vim
#virtual-service-address:是指虛擬服務器的ip 地址 #real-service-address:是指真實服務器的ip 地址 #scheduler:調度方法 #ipvsadm 的用法和格式以下: ipvsadm -A|E -t|u|f virutal-service-address:port [-s scheduler] [-p[timeout]] [-M netmask] ipvsadm -D -t|u|f virtual-service-address ipvsadm -C ipvsadm -R ipvsadm -S [-n] ipvsadm -a|e -t|u|f service-address:port -r real-server-address:port [-g|i|m] [-w weight] ipvsadm -d -t|u|f service-address -r server-address ipvsadm -L|l [options] ipvsadm -Z [-t|u|f service-address] ipvsadm --set tcp tcpfin udp ipvsadm --start-daemon state [--mcast-interface interface] ipvsadm --stop-daemon ipvsadm -h #命令選項解釋:有兩種命令選項格式,長的和短的,具備相同的意思。在實際使用時,兩種均可以。 -A --add-service #在內核的虛擬服務器表中添加一條新的虛擬服務器記錄。也就是增長一臺新的虛擬服務器。 -E --edit-service #編輯內核虛擬服務器表中的一條虛擬服務器記錄。 -D --delete-service #刪除內核虛擬服務器表中的一條虛擬服務器記錄。 -C --clear #清除內核虛擬服務器表中的全部記錄。 -R --restore #恢復虛擬服務器規則 -S --save #保存虛擬服務器規則,輸出爲-R 選項可讀的格式 -a --add-server #在內核虛擬服務器表的一條記錄裏添加一條新的真實服務器記錄。也就是在一個虛擬服務器中增長一臺新的真實服務器 -e --edit-server #編輯一條虛擬服務器記錄中的某條真實服務器記錄 -d --delete-server #刪除一條虛擬服務器記錄中的某條真實服務器記錄 -L|-l --list #顯示內核虛擬服務器表 -Z --zero #虛擬服務表計數器清零(清空當前的鏈接數量等) --set tcp tcpfin udp #設置鏈接超時值 --start-daemon #啓動同步守護進程。他後面能夠是master 或backup,用來講明LVS Router 是master 或是backup。在這個功能上也能夠採用keepalived 的VRRP 功能。 --stop-daemon #中止同步守護進程 -h --help #顯示幫助信息 #其餘的選項: -t --tcp-service service-address #說明虛擬服務器提供的是tcp 的服務[vip:port] or [real-server-ip:port] -u --udp-service service-address #說明虛擬服務器提供的是udp 的服務[vip:port] or [real-server-ip:port] -f --fwmark-service fwmark #說明是通過iptables 標記過的服務類型。 -s --scheduler scheduler #使用的調度算法,有這樣幾個選項rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq,默認的調度算法是: wlc. -p --persistent [timeout] #持久穩固的服務。這個選項的意思是來自同一個客戶的屢次請求,將被同一臺真實的服務器處理。timeout 的默認值爲300 秒。 -M --netmask #子網掩碼 -r --real-server server-address #真實的服務器[Real-Server:port] -g --gatewaying 指定LVS 的工做模式爲直接路由模式(也是LVS 默認的模式) -i --ipip #指定LVS 的工做模式爲隧道模式 -m --masquerading #指定LVS 的工做模式爲NAT 模式 -w --weight weight #真實服務器的權值 --mcast-interface interface #指定組播的同步接口 -c --connection #顯示LVS 目前的鏈接 如:ipvsadm -L -c --timeout #顯示tcp tcpfin udp 的timeout 值 如:ipvsadm -L --timeout --daemon #顯示同步守護進程狀態 --stats #顯示統計信息 --rate #顯示速率信息 --sort #對虛擬服務器和真實服務器排序輸出 --numeric -n #輸出IP 地址和端口的數字形式 ipvsadm命令方法
lvs調度算法(不區分大小寫)能夠分爲兩大類:bash
1.Fixed Scheduling Method 靜態調服方法 RR #輪詢 #調度器經過"輪叫"調度算法將外部請求按順序輪流分配到集羣中的真實服務器上,它均等地對待每一臺服務器,而無論服務器上實際的鏈接數和系統負載。 WRR #加權輪詢 #調度器經過"加權輪叫"調度算法根據真實服務器的不一樣處理能力來調度訪問請求。 這樣能夠保證處理能力強的服務器處理更多的訪問流量。調度器 能夠自動問詢真實服務器的負載狀況,並動態地調整其權值。 DH #目標地址hash #算法也是針對目標IP地址的負載均衡,但它是一種靜態映射算法,經過一個散列(Hash)函數將一個目標IP地址映射到一臺服務器。 #目標地址散列調度算法先根據請求的目標IP地址,做爲散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,不然返回空。 SH #源地址hash #算法正好與目標地址散列調度算法相反,它根據請求的源IP地址,做爲散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是 可用的且未超載,將請求發送到該服務器,不然返回空。 #它採用的散列函數與目標地址散列調度算法的相同。除了將請求的目標IP地址換成請求的源IP地址外,它的算法流程與目標地址散列調度算法的基本類似。在實際應用中,源地址散列調度和目標地址散列調度能夠結合使用在防火牆集羣中,它們能夠保證整個系統的惟一出入口。 2.Dynamic Scheduling Method 動態調服方法 LC #最少鏈接 #調度器經過"最少鏈接"調度算法動態地將網絡請求調度到已創建的連接數最少的服務器上。 若是集羣系統的真實服務器具備相近的系統性能,採用"最小鏈接"調度算法能夠較好地均衡負載。 WLC #加權最少鏈接 #在集羣系統中的服務器性能差別較大的狀況下,調度器採用"加權最少連接"調度算法優化負載均衡性能,具備較高權值的服務器將承受較大比例的活動鏈接負載。調度器能夠自動問詢真實服務器的負載狀況,並動態地調整其權值。 SED #最少指望延遲 #基於wlc算法,舉例說明:ABC三臺機器分別權重123,鏈接數也分別是123,name若是使用WLC算法的話一個新請求 進入時他可能會分給ABC中任意一個,使用SED算法後會進行這樣一個運算 #A:(1+1)/2 #B:(1+2)/2 #C:(1+3)/3 #根據運算結果,把鏈接交給C NQ #從不排隊調度方法 #無需列隊,若是有臺realserver的鏈接數=0 就直接分配過去,不須要進行sed運算. LBLC #基於本地的最少鏈接 # "基於局部性的最少連接" 調度算法是針對目標IP地址的負載均衡,目前主要用於Cache集羣系統。 #該算法根據請求的目標IP地址找出該 目標IP地址最近使用的服務器,若該服務器 是可用的且沒有超載,將請求發送到該服務器; #若服務器不存在,或者該服務器超載且有服務器處於一半的工做負載,則用"最少連接"的原則選出一個可用的服務器,將請求發送到該服務器。 LBLCR #帶複製的基於本地的最少鏈接 #"帶複製的基於局部性最少連接"調度算法也是針對目標IP地址的負載均衡,目前主要用於Cache集羣系統。 #它與LBLC算法的不一樣 之處是它要維護從一個 目標IP地址到一組服務器的映射,而LBLC算法維護從一個目標IP地址到一臺服務器的映射。 #該算法根據請求的目標IP地址找出該目標IP地址對應的服務器組,按"最小鏈接"原則從服務器組中選出一臺服務器, #若服務器沒有超載,將請求發送到該服務器;若服務器超載,則按"最小鏈接"原則從這個集羣中選出一 臺服務器 ,將該服務器加入到服務器組中,將請求發送到該服務器。同時,當該服務器組有一段時間沒有被修改, 將最忙的服務器從服務器組中刪除,以下降複製的程度。 lvs調度算法
NAT模型其實就是經過網絡地址轉換來實現負載均衡的。下面是它的流程:服務器
1.用戶請求VIP(也能夠說是CIP請求VIP) 2,Director Server 收到用戶的請求後,發現源地址爲CIP請求的目標地址爲VIP,那麼Director Server會認爲用戶請求的是一個集羣服務,那麼Director Server 會根據此前設定好的調度算法將用戶請求負載給某臺Real Server。
假如說此時Director Server 根據調度的結果會將請求分攤到RealServer1上去,那麼Director Server 會將用戶的請求報文中的目標地址,從原來的VIP改成RealServer1的IP,而後再轉發給RealServer1 3,此時RealServer1收到一個源地址爲CIP目標地址爲本身的請求,那麼RealServer1處理好請求後會將一個源地址爲本身目標地址爲CIP的數據包經過Director Server 發出去, 4.當Driector Server收到一個源地址爲RealServer1 的IP 目標地址爲CIP的數據包,此時Driector Server 會將源地址修改成VIP,而後再將數據包發送給用戶
LVS-NAT的性能瓶頸:網絡
在LVS/NAT的集羣系統中,請求和響應的數據報文都須要經過負載調度器(Director),當真實服務器(RealServer)的數目在10臺和20臺之間時,負載調度器(Director)將成爲整個集羣系統的新瓶頸。架構
大多數Internet服務都有這樣的特色:請求報文較短而響應報文每每包含大量的數據。若是能將請求和響應分開處理,即在負載調度器(Director)中只負責調度請求而響應直接(RealServer)返回給客戶,將極大地提升整個集羣系統的吞吐量。
在RealServer上部署httpd服務並測試
#安裝httpd服務,建立httpd測試頁面,啓動httpd服務 [root@web1 ~]# yum -y install httpd [root@web1 ~]# service httpd start [root@web1 ~]# echo "RS1-web1 Allentuns.com" > /var/www/html/index.html [root@web2 ~]# yum -y install httpd [root@web2 ~]# echo "RS2-web2 Allentuns.com" > /var/www/html/index.html [root@web2 ~]# service httpd start #測試httpd服務是否OK! [root@web1 ~]# curl http://localhost RS1-web1 Allentuns.com [root@web1 ~]# curl http://172.16.100.11 RS2-web2 Allentuns.com
在Director上部署ipvs服務並測試
添加集羣服務
[root@LVS ~]# ipvsadm -A -t 192.168.0.200:80 -s rr #定義一個集羣服務 [root@LVS ~]# ipvsadm -a -t 192.168.0.200:80 -r 172.16.100.10 -m #添加RealServer並指派調度算法爲NAT [root@LVS ~]# ipvsadm -a -t 192.168.0.200:80 -r 172.16.100.11 -m #添加RealServer並指派調度算法爲NAT [root@LVS ~]# ipvsadm -L -n #查看ipvs定義的規則列表 IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.0.200:80 rr -> 172.16.100.10:80 Masq 1 0 0 -> 172.16.100.11:80 Masq 1 0 0 [root@LVS ~]# cat /proc/sys/net/ipv4/ip_forward #查看Linux是否開啓路由轉發功能 0 [root@LVS ~]# echo 1 > /proc/sys/net/ipv4/ip_forward #啓動Linux的路由轉發功能 [root@LVS ~]# cat /proc/sys/net/ipv4/ip_forward 1
測試訪問http頁面
[root@LVS ~]# curl http://192.168.0.200/index.html RS2-web2 Allentuns.com #第一次是web2 [root@LVS ~]# curl http://192.168.0.200/index.html RS1-web1 Allentuns.com #第二次是web1 [root@LVS ~]# curl http://192.168.0.200/index.html RS2-web2 Allentuns.com #第三次是web1 [root@LVS ~]# curl http://192.168.0.200/index.html RS1-web1 Allentuns.com #第四次是web2
更改LVS的調度算法並壓力測試,查看結果
[root@LVS ~]# ipvsadm -E -t 192.168.0.200:80 -s wrr [root@LVS ~]# ipvsadm -e -t 192.168.0.200:80 -r 172.16.100.10 -m -w 3 [root@LVS ~]# ipvsadm -e -t 192.168.0.200:80 -r 172.16.100.11 -m -w 1 [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 192.168.0.200:80 wrr -> 172.16.100.10:80 Masq 3 0 2 -> 172.16.100.11:80 Masq 1 0 2 [root@LVS ~]# curl http://192.168.0.200/index.html RS1-web1 Allentuns.com [root@LVS ~]# curl http://192.168.0.200/index.html RS1-web1 Allentuns.com [root@LVS ~]# curl http://192.168.0.200/index.html RS1-web1 Allentuns.com [root@LVS ~]# curl http://192.168.0.200/index.html RS2-web2 Allentuns.com [root@LVS ~]# curl http://192.168.0.200/index.html RS1-web1 Allentuns.com
永久保存LVS規則並恢復
#第一種方法: [root@LVS ~]# service ipvsadm save ipvsadm: Saving IPVS table to /etc/sysconfig/ipvsadm: [肯定] #第二種方法: [root@LVS ~]# ipvsadm -S > /etc/sysconfig/ipvsadm.s1
模擬清空ipvsadm規則來恢復
[root@LVS ~]# ipvsadm -C [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 [root@LVS ~]# ipvsadm -R < /etc/sysconfig/ipvsadm.s1 [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 192.168.0.200:80 wrr -> 172.16.100.10:80 Masq 3 0 0 -> 172.16.100.11:80 Masq 1 0 0
LVS-NAT服務控制腳本部署在Director上
#!/bin/bash # # chkconfig: - 88 12 # description: LVS script for VS/NAT # . /etc/rc.d/init.d/functions # VIP=192.168.0.200 DIP=172.16.100.1 RIP1=172.16.100.10 RIP2=172.16.100.11 # case "$1" in start) # /sbin/ifconfig eth1:0 $VIP netmask 255.255.255.0 up # 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 rr # Now direct packets for this VIP to # the real server IP (RIP) inside the cluster /sbin/ipvsadm -a -t $VIP:80 -r $RIP1 -m /sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -m /bin/touch /var/lock/subsys/ipvsadm.lock ;; stop) # Stop forwarding packets echo 0 > /proc/sys/net/ipv4/ip_forward # Reset ipvsadm /sbin/ipvsadm -C # Bring down the VIP interface ifconfig eth1:0 down rm -rf /var/lock/subsys/ipvsadm.lock ;; status) [ -e /var/lock/subsys/ipvsadm.lock ] && echo "ipvs is running..." || echo "ipvsadm is stopped..." ;; *) echo "Usage: $0 {start|stop}" ;; esac lvs-nat-director.sh
分享LVS-NAT一鍵安裝腳本
#!/bin/bash # # 一鍵安裝lvs-nat腳本,須要注意的是主機名成和ip的變化稍做修改就能夠了 HOSTNAME=`hostname` Director='LVS' VIP="192.168.0.200" RIP1="172.16.100.10" RIP2="172.16.100.11" RealServer1="web1" RealServer2="web2" Httpd_config="/etc/httpd/conf/httpd.conf" #Director Server Install configure ipvsadm if [ "$HOSTNAME" = "$Director" ];then ipvsadm -C yum -y remove ipvsadm yum -y install ipvsadm /sbin/ipvsadm -A -t $VIP:80 -s rr /sbin/ipvsadm -a -t $VIP:80 -r $RIP1 -m /sbin/ipvsadm -a -t $VIP:80 -r $RIP2 -m echo 1 > /proc/sys/net/ipv4/ip_forward echo "========================================================" echo "Install $Director sucess Tel:13260071987 Qq:467754239" echo "========================================================" fi #RealServer Install htpd if [ "$HOSTNAME" = "$RealServer1" ];then yum -y remove httpd rm -rf /var/www/html/index.html yum -y install httpd echo "web1 Allentuns.com" > /var/www/html/index.html sed -i '/#ServerName www.example.com:80/a\ServerName localhost:80' $Httpd_config service httpd start echo "========================================================" echo "Install $RealServer1 success Tel:13260071987 Qq:467754239" echo "========================================================" fi if [ "$HOSTNAME" = "$RealServer2" ];then yum -y remove httpd rm -rf /var/www/html/index.html yum -y install httpd echo "web2 Allentuns.com" > /var/www/html/index.html sed -i '/#ServerName www.example.com:80/a\ServerName localhost:80' $Httpd_config service httpd start echo "Install $RealServer2" echo "=========================================================" echo "Install $RealServer1 success Tel:13260071987 Qq:467754239" echo "=========================================================" fi lvs-nat-install
上面說了NAT模型的實現方式,那麼NAT模型有個缺陷,由於進出的每一個數據包都要通過Director Server,當集羣系統負載過大的時候Director Server將會成爲整個集羣系統的瓶頸,
那麼DR模型就避免了這樣的狀況發生,DR模型在只有請求的時候纔會通過Director Server, 迴應的數據包由Real Server 直接響應用戶不須要通過Director Server,其實三種模型中最經常使用的也就是DR模型了。
下面是它的工做流程:
1, 首先用戶用CIP請求VIP 2, 根據上圖能夠看到,無論是Director Server仍是Real Server上都須要配置VIP,那麼當用戶請求到達咱們的集羣網絡的前端路由器的時候,請求數據包的源地址爲CIP目標地址爲VIP,
此時路由器會發廣播問誰是VIP,那麼咱們集羣中全部的節點都配置有VIP,此時誰先響應路由器那麼路由器就會將用戶請求發給誰,這樣一來咱們的集羣系統是否是沒有意義了,
那咱們能夠在網關路由器上配置靜態路由指定VIP就是Director Server,或者使用一種機制不讓Real Server 接收來自網絡中的ARP地址解析請求,這樣一來用戶的請求數據包都會通過Director Servrer 3,當Director Server收到用戶的請求後根據此前設定好的調度算法結果來肯定將請求負載到某臺Real Server上去,假如說此時根據調度算法的結果,會將請求負載到RealServer 1上面去,
此時Director Server 會將數據幀中的目標MAC地址修改成Real Server1的MAC地址,而後再將數據幀發送出去 4,當Real Server1 收到一個源地址爲CIP目標地址爲VIP的數據包時,Real Server1發現目標地址爲VIP,而VIP是本身,因而接受數據包並給予處理,當Real Server1處理完請求後,
會將一個源地址爲VIP目標地址爲CIP的數據包發出去,此時的響應請求就不會再通過Director Server了,而是直接響應給用戶。
編輯DR有三種方式(目的是讓用戶請求的數據都經過Director Server)
第一種方式:在路由器上明顯說明vip對應的地址必定是Director上的MAC,只要綁定,之後再跟vip通訊也不用再請求了,這個綁定是靜態的,因此它也不會失效,也不會再次發起請求,可是有個前提,咱們的路由設備必須有操做權限可以綁定MAC地址,萬一這個路由器是運行商操做的,咱們無法操做怎麼辦?第一種方式當然很簡便,但未必可行。
第二種方式:在給別主機上(例如:紅帽)它們引進的有一種程序arptables,它有點相似於iptables,它確定是基於arp或基於MAC作訪問控制的,很顯然咱們只須要在每個real server上定義arptables規則,若是用戶arp廣播請求的目標地址是本機的vip則不予相應,或者說相應的報文不讓出去,很顯然網關(gateway)是接受不到的,也就是director相應的報文才能到達gateway,這個也行。第二種方式咱們能夠基於arptables。
第三種方式:在相對較新的版本中新增了兩個內核參數(kernelparameter),第一個是arp_ignore定義接受到ARP請求時的相應級別;第二個是arp_announce定義將本身地址向外通告是的通告級別。【提示:很顯然咱們如今的系統通常在內核中都是支持這些參數的,咱們用參數的方式進行調整更具備樸實性,它還不依賴於額外的條件,像arptables,也不依賴外在路由配置的設置,反而一般咱們使用的是第三種配置】
arp_ignore:定義接受到ARP請求時的相應級別
0:只要本地配置的有相應地址,就給予響應。 1:僅在請求的目標地址配置請求到達的接口上的時候,纔給予響應(當別人的arp請求過來的時候,若是接收的設備上面沒有這個ip,就不響應,默認是0,只要這臺機器上面任何一個設備上面有這個ip,就響應arp請求,併發送MAC地址應答。) 2:只回答目標IP地址是來訪網絡接口本地地址的ARP查詢請求,且來訪IP必須在該網絡接口的子網段內 3:不迴應該網絡界面的arp請求,而只對設置的惟一和鏈接地址作出迴應 4-7:保留未使用 8:不迴應全部(本地地址)的arp查詢
arp_announce:定義將本身地址向外通告是的通告級別;
0: 將本地任何接口上的任何地址向外通告 1:試圖僅想目標網絡通告與其網絡匹配的地址 2:僅向與本地藉口上地址匹配的網絡進行通告
在Real Server1 和Real Server2上作如下配置
# 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 #以上命令需填加到/etc/rc.local文件中讓其開機自動生效 # vim /etc/sysconfig/network-scripts/ifcfg-lo:0 內容以下 DEVICE=lo:0 IPADDR=172.16.100.100 NETMASK=255.255.255.255 BROADCAST=172.16.100.100 ONBOOT=yes NAME=loopback # ifdown lo:0 # ifup lo:0 # route add -host 172.16.100.100 dev lo:0 # echo "route add -host 172.16.100.100 dev lo:0" >> /etc/rc.local
在Director Server上作如下配置
# vim /etc/sysconfig/network-scripts/ifcfg-eth2:0 內容以下 DEVICE=eth2:0 IPADDR=172.16.100.100 NETMASK=255.255.255.255 BROADCAST=172.16.100.100 ONBOOT=yes # ifdown eth2:0 #命令 # ifup eth2:20 # route add -host 172.16.100.100 dev eth2:0 # echo "route add -host 172.16.100.100 dev eth2:0" >> /etc/rc.local # echo "1" > /proc/sys/net/ipv4/ip_forward # echo "echo "1" > /proc/sys/net/ipv4/ip_forward" >> /etc/rc.local # ipvsadm -A -t 172.16.100.100:80 -s wlc # ipvsadm -a -t 172.16.100.100:80 -r 172.16.100.10 -g -w 2 # ipvsadm -a -t 172.16.100.100:80 -r 172.16.100.11 -g -w 1
Director腳本
#!/bin/bash # # LVS script for VS/DR # . /etc/rc.d/init.d/functions # VIP=172.16.100.100 RIP1=172.16.100.10 RIP2=172.16.100.11 PORT=80 # case "$1" in start) /sbin/ifconfig eth2:0 $VIP broadcast $VIP netmask 255.255.255.255 up /sbin/route add -host $VIP dev eth2:0 # 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 eth2: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 Director.sh
RealServer腳本
#!/bin/bash # # Script to start LVS DR real server. # description: LVS DR real server # . /etc/rc.d/init.d/functions VIP=172.16.100.100 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 RealServer.sh
TUN的工做機制跟DR同樣,只不過在轉發的時候,它須要從新包裝IP報文。這裏的real server(圖中爲RIP)離得都比較遠。
用戶請求之後,到director上的VIP上,它跟DR模型同樣,每一個realserver上既有RIP又有VIP,Director就挑選一個real server進行響應,但director和real server並不在同一個網絡上,這時候就用到隧道了,Director進行轉發的時候,必定要記得CIP和VIP不能動。
咱們轉發是這樣的,讓它的CIP和VIP不動,在它上面再加一個IP首部,再加的IP首部源地址是DIP,目標地址的RIP的IP地址。收到報文的RIP,拆掉報文之後發現了裏面還有一個封裝,它就知道了,這就是隧道。
其實數據轉發原理和DR是同樣的,不過這個我我的認爲主要是位於不一樣位置(不一樣機房);LB是經過隧道進行了信息傳輸,雖然增長了負載,但是由於地理位置不一樣的優點,仍是能夠參考的一種方案;
優勢:負載均衡器只負責將請求包分發給物理服務器,而物理服務器將應答包直接發給用戶。因此,負載均衡器能處理很巨大的請求量,這種方式,一臺負載均衡能爲超過100臺的物理服務器服務,負載均衡器再也不是系統的瓶頸。
使用VS-TUN方式,若是你的負載均衡器擁有100M的全雙工網卡的話,就能使得整個Virtual Server能達到1G的吞吐量。 不足:可是,這種方式須要全部的服務器支持"IP Tunneling"(IP Encapsulation)協議;
在LVS模型中,director不負責檢查RS的健康情況,這就使得當有的RS出故障了,director還會將服務請求派發至此服務器,這種狀況對用戶、企業都是很不爽的,哪一個用戶倒黴說不定就遇到相似了。
爲了讓Director更人性化、可靠還要給director提供健康檢查功能;如何實現?Director沒有自帶檢查工具,只有手動編寫腳本給director實現健康狀態檢查功能!
#!/bin/bash # VIP=172.16.100.100 CPORT=80 FAIL_BACK=127.0.0.1 RS=("172.16.100.10" "172.16.100.11") declare -a RSSTATUS RW=("2" "1") RPORT=80 TYPE=g CHKLOOP=3 LOG=/var/log/ipvsmonitor.log addrs() { ipvsadm -a -t $VIP:$CPORT -r $1:$RPORT -$TYPE -w $2 [ $? -eq 0 ] && return 0 || return 1 } delrs() { ipvsadm -d -t $VIP:$CPORT -r $1:$RPORT [ $? -eq 0 ] && return 0 || return 1 } checkrs() { local I=1 while [ $I -le $CHKLOOP ]; do if curl --connect-timeout 1 http://$1 &> /dev/null; then return 0 fi let I++ done return 1 } 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 A++ Dir[0]=$A fi let COUNT++ done } 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 check-lvs-health.sh
參考資料: