LVS詳解

簡介:
Linux虛擬服務器(Linux Virtual Server. LVS),是一個由章文鬆開發的自由軟件.利用LVS可以實現高可用的、可伸縮縮的Web, Mail, Cache和Medial等網絡服務,並在此基礎上開發支持龐大用戶數的,可伸縮的,高可用的電子商務應用。LVS1998年發展到現在,已經變得比較成熟,目前廣泛應用在各種網絡服務和電了商務應用中.


LVS具有很好的伸縮縮性、可靠性和管埋性,通過LVS要實現的最終目標是:利用linux操作系統和LVS集羣軟件實現一個高可用、高性能,低成本的服務器應用集羣。

LVS集羣的組成
利用LVS架設的服務器羣系統由3個部分組成:最前端的是負載均衡層(這裏用 Load Balancer表示),中間是服務器集羣層(用Server Array表示).
LVS體系結構如下圖所示:

wKiom1NUUN2Sj0KmAASTCcn-uiM346.jpg

下面對LVS的各個組成部分進行詳細介紹
       負載均衡層:位於整個集羣系統的最前端,由一臺或多臺負載調度器(Director Server)組成.LVS核心模塊IPVS就安裝在director Server上,而director的主要作用類似於一個路由器,它含有爲完成LVS功能所設定的路由表,通過這些路由表把用戶的請求分發給服務器羣組層的應用服務器(real Server)。同時,在director server上還要安裝隊real server的監控模塊Ldirectord,此模塊用於監測各個real server服務的健康狀況。

      服務器羣組層:由一組實際運行應用服務的機器組成,real Server可以是Web服務器、Mail服務器、FTP服務器、DNS服務器、視頻服務器中的一個或多個,每個Real Server之間通過高速的LAN或分佈在各地的WAN相連接:實際的應用中, Director Server也可以同時兼任Real Server的角色,但是儘量不要這樣使用!
      共享存儲層:是爲所有Real Server提供共亨存儲空間和內容一致性的存儲區域,一般由磁盤陣列設備組成。爲了提供內容的一致性,一般可以通過NFS網絡文件系統共享數據,但是NFS在繁忙的業務系統中,性能並不是很好,此時可以採用集羣文件系統,例如Red Hat的GFS文件系統,Oracle提供的OS2文件系統等。
       從整個LVS結構可以看出,Director Server是整個LVS的核心。目前,用於Director Server 的操作系統只有Linux和FreeBSD, Linux 2.6內核完全內置了LVS的各個模塊,不用任何設置就可以支持LVS功能。
       Real Server,幾乎所有的系統平臺,如 Linux、Windows、Solaris、AIX、BSD 系列等都能很好地支持它 



LVS集羣的特點
1. IP負載均衡與負載調度

負載均衡技術有很多實現方案,有基於DNS域名輪流解析的方法,有基於客戶端調度訪問的方法,還有基於應用層系統負載的調度方法,還有基於ip地址的調度方法。在這些負載調度算法中,執行效率最卨的是IP負栽均衡技術。

LVS 的IP負載均衡技術是通過IPVS模塊來實現的。IPVS是LVS集羣系統的核心軟件, 它的主要作用是:安裝在Director Server上,同時在Director Server上虛擬出一個IP地址,用戶必須通過這個虛擬的IP地址訪問服務器,這個虛擬IP—般稱爲LVS的VIP,即Virtual IP 。訪問的請求首先經過VIP到達負載調度器,然後由負載調度器從Real Server列表中選取 一個服務節點響應用戶的請求。

在用戶的請求到達負載調度器後,調度器如何將請求發送到提供服務的Real Server節點,Real Server節點如何返回數據給用戶,是IPVS實現的重點技術。IPVS實現負載均衡的方式有4種,分別是NAT、Full NAT、TUN和DR。

下面進行詳細介紹。

VS/NAT :即 Virtual Server via Network Address Translation,也就是網絡地址翻譯技術實現虛擬服務器。當用戶請求到達調度器時,調度器將請求報文的目標地址(即虛擬IP地址)改寫成選定的Real Server地址,同時將報文的目標端口也改成選定的 Real Server的相應端口,最後將報文請求發送到選定的Real Server。在服務器端得到數據後,Real Server將數據返回給用戶時,需要再次經過負載調度器將報文的源地址和源端口改成虛擬IP地址和相應端口,然後把數據發送給用戶,完成整個負載調度過程。可以看出在NAT方式下,用戶請求和響應報文都必須經過Director Server地址重寫,當用戶請求越來越多時,調度器的處理能力將成爲瓶頸. 如下圖所示:VS/NAT 架構圖

NAT:多目標的DNAT
特性

  • RS應該使用私有地址;

  • RS的網關必須指向DIP;

  • RIP和DIP必須在同一網段內;

  • 請求和響應的報文都得經過Director;(在高負載應用場景中,Director很可能成爲系統性能瓶頸)

  • 支持端口映射;

  • RS可以使用任意支持集羣服務的OS(如Windows)

適用場景

  • 非高併發請求場景,10個RS以內;可隱藏內部的DIP和RIP地址;

結構圖:

wKioL1NUUR6xJPdIAAPI6-VYNAQ124.jpg


VS/TUN :即Virtual Server via IP Tunneling,也就是通過IP隧道技術實現虛擬服務器。這種方式的連接調度度和管理與VS/NAT方式一樣,只是報文轉發方法不同。在 VS/TUN方式中,調度器採用IP隧道技術將用戶清求轉發到某個Real Server,而這個Real Server將直接響應用戶的請求,不再經過前端調度器。此外,對Real Server的地域位置沒有要求,可以和Director Server位於同一個網段,也可以在獨立的一個網絡中。因此,在TUN方式中,調度器將只處理用戶的報文請求,從而使集羣系統的吞吐量大大提高。如下圖所示VS/TUN 架構圖:

TUN:IP隧道,即含有多個IP報頭

特性

  • RIP、DIP、VIP都得是公網地址;

  • RS的網關不會指向也不可能指向DIP;

  • 請求報文經過Director,但響應報文一定不經過Director;

  • 不支持端口映射;

  • RS的操作系統必須得支持隧道功能,即部署ipip模塊

適用場景

  • 跨互聯網的請求轉發

結構圖

wKioL1NUUXyzlD3LAAWqhFn-JXs928.jpg

 

FULLNAT是一種新的轉發模式
主要思想:引入local address(內網ip地址),cip-vip轉換爲lip->rip,而lip和rip均爲IDC內網ip,可以跨vlan通訊;FULLNAT:NAT模型的改進版

特性

  • 實現RS間跨VLAN通信,是NAT模式的改進版;

  • 默認內核不支持,需重新編譯內核,才能使用;

適用場景

  • 內網服務器跨VLAN的負載分擔

結構圖

wKiom1NUUcPzKwifAAQPUKtOtLQ188.jpg

 

VS/DR: 即Virtual Server via Direct Routing,也就是用直接路由技術實現虛擬服務器。 這種方式的連接調度和管理與前兩種一樣,但它的報文轉發方法又有所不同,VS/DR 通過改寫請求報文的MAC地址,將請求發送到Real Server,而Real Server將響應直接返回給客戶.免去了VS/TUN中的IP隧道開銷,這種方式是3種負莪調度方式中性能最好的,但是要求Director Server與Real Server必須由一塊網卡連在同一物理網段上

如下圖所示:VS/DR 架構圖

DR:Direct Routing

需解決的關鍵問題

  • 讓前端路由將請求發往VIP時,只能是Director上的VIP進行響應;實現方式是修改RS上的Linux內核參數,將RS上的VIP配置爲lo接口的別名,並限制Linux僅對對應接口的ARP請求做響應

特性

  • RS可以使用私有地址,但也可以使用公網地址,此時可以直接通過互聯網連入RS以實現配置,監控等;

  • RS的網關一定不能指向DIP;

  • RS和Director要在同一物理網絡(即不能由路由器分隔)

  • 請求報文經過Director,但響應報文一定不經過Director

  • 不支持端口映射;

  • RS可以使用大多數的操作系統

適用場景

  • 因爲響應報文不經過Director,極大的減輕了Director的負載壓力,故Director可以支持更大的併發訪問,一般RS在100臺以內

結構圖

LVS-DR配置架構根據其VIP與RIP是否在同一個網段內又分爲兩種模型:

wKiom1NUUYXgY-cuAAngzldUKCc340.jpg

 


LVS調度算法

1>負載調度算法

靜態方法僅根據算法本身進行調度

rr:Round Robin # 即輪詢
wrr:Weighted RR # 即加權輪詢
sh:Source Hashing # 即來源IP地址hash
dh:Destination Hashing # 即目標地址hash(不常用,僅用於前端多防火牆的場景,保證防火牆的連接追蹤功能有效)

動態方法根據算法及RS當前的負載情況

lc:Least Connection
    # 評判標準:Overhead=Active*256+Inactive
    # Overhead最小者勝出
wlc:Weighted LC
    # 評判標準:Overhead=(Active*256+Inactive)/weight
    # Overhead最小者勝出
sed:Shortest Expect Delay
    # 評判標準:Overhead=(Active+1)*256/weight
    # Overhead最小者勝出
nq:Never Queue 
    #集羣開始時工作時,每臺服務器至少分配一個連接請求,然後再根據sed算法調度;
lblc:Locality-based Least Connection # 類似於dh+lc
lblcr:Relicated and Locality-based Least Connection # 主要用於後端服務器是緩存服務器時


前面介紹過,負載調度器是根據各個服務器的負載情況,動態地選擇一臺Real Server響應用戶請求。那麼動態選擇是如何實現呢?其實就是通過這裏要說的負載調度算法。根據不同的網絡服務需求和服務器配IPVS實現10種負載調度算法。這裏詳細講述最常用的幾種調度算法。

1、 輪詢(round robin, rr),加權輪詢(Weighted round robin, wrr)——新的連接請求被輪流分配至各RealServer算法的優點是其簡潔性,無需記錄當前所有連接的狀態,所以它是一種無狀態調度。輪叫調度算法假設所有服務器處理性能均相同,不管服務器的當前連接數和響應速度。該算法相對簡單,不適用於服務器組中處理性能不一的情況,而且當請求服務時間變化比較大時,輪叫調度算法容易導致服務器間的負載不平衡。

2、 最少連接(least connected, lc), 加權最少連接(weighted least connection, wlc)——新的連接請求將被分配至當前連接數最少的Real Server;最小連接調度是一種動態調度算法,它通過服務器當前所活躍的連接數來估計服務器的負載情況。調度器需要記錄各個服務器已建立連接的數目,當一個請求被調度到某臺服務器,其連接數加1;當連接中止或超時,其連接數減一。

3、 基於局部性的最少鏈接調度(Locality-Based Least Connections Scheduling,lblc)——針對請求報文的目標IP地址的負載均衡調度,目前主要用於Cache集羣系統,因爲在Cache集羣中客戶請求報文的目標IP地址是變化的。這裏假設任何後端服務器都可以處理任一請求,算法的設計目標是在服務器的負載基本平衡情況下,將相同目標IP地址的請求調度到同 一臺服務器,來提高各臺服務器的訪問局部性和主存Cache命中率,從而整個集羣系統的處理能力。LBLC調度算法先根據請求的目標IP地址找出該目標 IP地址最近使用的服務器,若該服務器是可用的且沒有超載,將請求發送到該服務器;若服務器不存在,或者該服務器超載且有服務器處於其一半的工作負載,則用“最少鏈接”的原則選出一個可用的服務器,將請求發送到該服務器。

4、 帶複製的基於局部性最少鏈接調度(Locality-Based Least Connections with Replication Scheduling,lblcr)——也是針對目標IP地址的負載均衡,目前主要用於Cache集羣系統。它與LBLC算法的不同之處是它要維護從一個 目標IP地址到一組服務器的映射,而 LBLC算法維護從一個目標IP地址到一臺服務器的映射。對於一個“熱門”站點的服務請求,一臺Cache服務器可能會忙不過來處理這些請求。這時,LBLC調度算法會從所有的Cache服務器中按“最小連接”原則選出一臺Cache服務器,映射該“熱門”站點到這臺Cache服務器,很快這臺Cache服務器也會超載,就會重複上述過程選出新的Cache服務器。這樣,可能會導致該“熱門”站點的映像會出現在所有的Cache服務器上,降低了Cache服務器的使用效率。LBLCR調度算法將“熱門”站點映射到一組Cache服務器(服務器集合),當該“熱門”站點的請求負載增加時,會增加集合裏的Cache服務器,來處理不斷增長的負載;當該“熱門”站點的請求負載降低時,會減少集合裏的Cache服務器數目。這樣,該“熱門”站點的映像不太可能出現在所有的Cache服務器上,從而提供Cache集羣系統的使用效率。LBLCR算法先根據請求的目標IP地址找出該目標IP地址對應的服務器組;按“最小連接”原則從該服務器組中選出一臺服務器,若服務器沒有超載,將請求發送到該服務器;若服務器超載;則按 “最小連接”原則從整個集羣中選出一臺服務器,將該服務器加入到服務器組中,將請求發送到該服務器。同時,當該服務器組有一段時間沒有被修改,將最忙的服務器從服務器組中刪除,以降低複製的程度。

5、 目標地址散列調度(Destination Hashing,dh)算法也是針對目標IP地址的負載均衡,但它是一種靜態映射算法,通過一個散列(Hash)函數將一個目標IP地址映射到一臺服務器。目標地址散列調度算法先根據請求的目標IP地址,作爲散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空。

6、 源地址散列調度(Source Hashing,sh)算法正好與目標地址散列調度算法相反,它根據請求的源IP地址,作爲散列鍵(Hash Key)從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空。它採用的散列函數與目標地址散列調度算法相同。除了將請求的目標IP地址換成請求的源IP地址外,它的算法流程與目標地址散列調度算法的基本相似。在實際應用中,源地址散列調度和目標地址散列調度可以結合使用在防火牆集羣中,它們可以保證整個系統的唯一出入口。

7、加權最少連接調度(Weighted Least Connections)。“加權最少連接調度”是“最少連接調度”的超集。每個服務節點可以用相應的權值表示其處理能力,而系統管理員可以動態地設置相應的權值,默認權值爲1。加權最小連接調度在分配新連接請求時儘可能使服務節點的已建立連接數和其權值成正比。算法: overhead=active*256+inactive/weight   overhead最小值勝出;

8、sed:shorttest expect delay  最小期望延遲(改進的wlc) 算法:overhead=(active+1)*256/weight,案例:假如DFG三臺機器分別權重123,連接數也分別是123.那麼如果使用WLC算法的話一個新請求進入時它可能會分給DFG中的任意一個。使用sed算法後會進行這樣一個運算:

D:(1+1)/1

F:(1+2)/2

G:(1+3)/3

9、nq:nerver queue  增強改進的sed算法.如果有臺real Server的連接數=0直接分配,不需要再進行sed運算

2>高可用性
LVS是一個基於內核級別的應用軟件,因此具有很髙的處理性能。由LVS構建的負載均衡集羣系統具有優秀的處理能力,每個服務節點的故障不會影響整個系統的正常使用,又能夠實現負載的合理均衡,使應用具有超高負荷的服務能力,可支持上百萬個併發連接請求。如配置百兆網卡,採用VS/TUN或VS/DR調度技術,整個集羣系統的吞吐量可高達 1Gbit/s;又如配置千兆網卡,系統的最大吞吐量可接近10Gbit/s。

3>高可靠性
LVS負載均衡集羣軟件已經在企業和學校中得到了很好的普及,國內外很多大型的、關鍵性的Web站點也都採用了LVS集羣軟件,所以它的可靠性在實踐中得到了很好印證。有很多由LVS構成的負載均衡系統,運行很長時間,從未進行過重新啓動。這些都說明了 LVS 的髙穩定性和高可靠性。

4>配置LVS

1、定義在Director上進行dispatching的服務(service),以及哪些服務器(server)用來提供此服務;
2、爲每臺同時提供某一種服務的服務器定義其權重(即根據服務器性能確定其承擔負載的能力);

注:權重用整數來表示,有時候也可以將其設置爲atomic_t;其有效表示值範圍爲24bit整數空間,即(2^24-1);

因此,ipvsadm命令的主要作用表現在以下方面:
1、添加服務(通過設定其權重>0);
2、關閉服務(通過設定其權重>0);此應用場景中,已經連接的用戶將可以繼續使用此服務,直到其退出或超時;新的連接請求將被拒絕;
3、保存ipvs設置,通過使用“ipvsadm-sav > ipvsadm.sav”命令實現;
4、恢復ipvs設置,通過使用“ipvsadm-sav < ipvsadm.sav”命令實現;
5、顯示ip_vs的版本號,下面的命令顯示ipvs的hash表的大小爲4k;
 # ipvsadm
   IP Virtual Server version 1.2.1 (size=4096)
6、顯示ipvsadm的版本號
 # ipvsadm --version
  ipvsadm v1.24 2003/06/07 (compiled with popt and IPVS v1.2.0)

二、ipvsadm使用中應注意的問題
默認情況下,ipvsadm在輸出主機信息時使用其主機名而非IP地址,因此,Director需要使用名稱解析服務。如果沒有設置名稱解析服務、服務不可用或設置錯誤,ipvsadm將會一直等到名稱解析超時後才返回。當然,ipvsadm需要解析的名稱僅限於Real Server,考慮到DNS提供名稱解析服務效率不高的情況,建議將所有Real Server的名稱解析通過/etc/hosts文件來實現;

三、調度算法
Director在接收到來自於Client的請求時,會基於"schedule"從Real Server中選擇一個響應給Client。ipvs支持以上調度算法:

四、關於LVS追蹤標記fwmark:
如果LVS放置於多防火牆的網絡中,並且每個防火牆都用到了狀態追蹤的機制,那麼在迴應一個針對於LVS的連接請求時必須經過此請求連接進來時的防火牆,否則,這個響應的數據包將會被丟棄。

 

常用命令:

查看LVS上當前的所有連接
# ipvsadm -Lcn   
或者
#cat /proc/net/ip_vs_conn

查看虛擬服務和Real Server上當前的連接數、數據包數和字節數的統計值,則可以使用下面的命令實現:
# ipvsadm -L --stats

查看包傳遞速率的近似精確值,可以使用下面的命令:
# ipvsadm -L --rate


VS/NAT
LVS- NAT基於cisco的LocalDirector。VS/NAT不需要在RealServer上做任何設置,其只要能提供一個tcp/ip的協議棧即可,甚至其無論基於什麼OS。基於VS/NAT,所有的入站數據包均由Director進行目標地址轉換後轉發至內部的 Real Server,Real Server響應的數據包再由Director轉換源地址後發回客戶端。 
VS/NAT模式不能與netfilter兼容,因此,不能將VS/NAT模式的Director運行在netfilter的保護範圍之中。現在已經有補丁可以解決此問題,但尚未被整合進ip_vs code。

     __________      |            |
      |  client    |
      |____________|                    
    CIP=192.168.0.153 (eth0)            
             |                          
             |                          
    VIP=192.168.0.220 (eth0)            
       ____________                      
      |            |                    
      |  director  |                    
      |____________|                    
    DIP=192.168.10.10 (eth1)        
             |                          
          (switch)------------------------
             |                           |
    RIP=192.168.10.2 (eth0)       RIP=192.168.10.3 (eth0)
       _____________               _____________      |             |             |             |
      | realserver1 |             | realserver2 |
      |_____________|             |_____________|

設置VS/NAT模式的LVS(這裏以web服務爲例)
Director:

如:
# ipvsadm -A -t 192.168.0.220:80 -s rr

如:
# ipvsadm -a -t 192.168.0.220:80 -r 192.168.10.2 -m -w 1
# ipvsadm -a -t 192.168.0.220:80 -r 192.168.10.3 -m -w 1


#!/bin/bash
#
# chkconfig: - 88 12
# description: LVS script for VS/NAT
#
. /etc/rc.d/init.d/functions

VIP=192.168.0.219
DIP=192.168.10.10
RIP1=192.168.10.11
RIP2=192.168.10.12
#case "$1" in 
start)
  /sbin/ifconfig eth0:1 $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 eth0:1 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


Real Server:route add default gw 192.168.10.10  

註釋:在real server 上網關一定要指向director服務器的DIP,不然用戶請求的數據報文,在VS/NAT模型中將無法發送出去.

#!/bin/bash
VIP=192.168.0.219
chmod  755 /etc/rc.d/init.d/functions
/etc/rc.d/init.d/functions
case "$1" in
start)
 echo " start LVS of REALServer"
 /sbin/ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255 up
 /sbin/route add -host $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
;;
stop)
/sbin/ifconfig lo:0 down
echo "close LVS Directorserver"
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 "Usage: $0 {start|stop}"exit 1
;;
esac


ARP問題:

 __________                    |        |
                    | client |
                    |________|
                           |
                        |
                     (router)                        |
                        |
                        |       __________                        |  DIP |          |
                        |------| director |
                        |  VIP |__________|
                        |
                        |
                        |
      ------------------------------------
      |                 |                |
      |                 |                |
  RIP1, VIP         RIP2, VIP        RIP3, VIP
______________    ______________    ______________|              |  |              |  |              |
| realserver1  |  | realserver2  |  | realserver3  |
|______________|  |______________|  |______________|

在如上圖的VS/DR或VS/TUN 應用的一種模型中(所有機器都在同一個物理網絡),所有的機器(包括Director和RealServer)都使用了一個額外的IP地址,即VIP。當一 個客戶端向VIP發出一個連接請求時,此請求必須要連接至Director的VIP,而不能是RealServer的。因爲,LVS的主要目標就是要 Director負責調度這些連接請求至RealServer的。
因此,在Client發出至VIP的連接請求後,只能由Director將其 MAC地址響應給客戶端(也可能是直接與Director連接的路由設備),而Director則會相應的更新其ipvsadm table以追蹤此連接,而後將其轉發至後端的Real Server之一。
如果Client在請求建立至VIP的連接時由某Real Server 響應了其請求,則Client會在其MAC table中建立起一個VIP至Real Server的對就關係,並以至進行後面的通信。此時,在Client看來只有一個Real Server而無法意識到其它服務器的存在。
爲了解決此問題,可以通過在路由器上設置其轉發規則來實現。當然,如果沒有權限訪問路由器並做出相應的設置,則只能通過傳統的本地方式來解決此問題了。這些方法包括:
1、禁止Real Server響應對VIP的ARP請求;
2、在Real Server上隱藏VIP,以使得它們無法獲知網絡上的ARP請求;
3、基於“透明代理(Transparent Proxy)”或者“fwmark (firewall mark)”;
4、禁止ARP請求發往Real Servers;

傳統認爲,解決ARP問題可以基於網絡接口,也可以基於主機來實現。Linux採用了基於主機的方式,因爲其可以在大多場景中工作良好,但LVS卻並不屬於這些場景之一,因此,過去實現此功能相當麻煩。現在可以通過設置arp_ignore和arp_announce,這變得相對簡單的多了。
Linux 2.2和2.4(2.4.26之前的版本)的內核解決“ARP問題”的方法各不相同,且比較麻煩。幸運的是,2.4.26和2.6的內核中引入了兩個新的調整ARP棧的標誌(device flags):arp_announce和arp_ignore。基於此,在DR/TUN的環境中,所有IPVS相關的設定均可使用arp_announce=2和arp_ignore=1/2/3來解決“ARP問題”了。

arp_annouce:Define different restriction levels for announcing the local source IP address from IP packets in ARP requests sent on interface;
   0 - (default) Use any local address, configured on any interface.
   1 - Try to avoid local addresses that are not in the target's subnet for this interface. 
   2 - Always use the best local address for this target.

arp_ignore: Define different modes for sending replies in response to received ARP requests that resolve local target IP address.
   0 - (default): reply for any local target IP address, configured on any interface.
   1 - reply only if the target IP address is local address configured on the incoming interface.
   2 - reply only if the target IP address is local address configured on the incoming interface and both with the sender's IP address are part from same subnet on this interface.
   3 - do not reply for local address configured with scope host, only resolutions for golbal and link addresses are replied.
   4-7 - reserved
   8 - do not reply for all local addresses

在RealServers上,VIP配置在本地迴環接口lo上。如果迴應給Client的數據包路由到了eth0接口上,則arp通告或請求應該通過eth0實現,因此,需要在sysctl.conf文件中定義如下配置:

#vim /etc/sysctl.conf
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth0.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2

以上選項需要在啓用VIP之前進行,否則,則需要在Drector上清空arp表才能正常使用LVS。到達Director的數據包首先會經過PREROUTING,而後經過路由發現其目標地址爲本地某接口的地址,因此,接着就會將數據包發往INPUT (LOCAL_IN HOOK)。此時,正在運行內核中的ipvs(始終監控着LOCAL_IN HOOK)進程會發現此數據包請求的是一個集羣服務,因爲其目標地址是VIP。於是,此數據包的本來到達本機(Director)目標行程被改變爲經由 POSTROUTING HOOK發往RealServer。這種改變數據包正常行程的過程是根據IPVS表(由管理員通過ipvsadm定義)來實現的。

如果有多臺Realserver,在某些應用場景中,Director還需要基於“連接追蹤”實現將由同一個客戶機的請求始終發往其第一次被分配至的Realserver,以保證其請求的完整性等。其連接追蹤的功能由Hash table實現。Hash table的大小等屬性可通過下面的命令查看:

# ipvsadm -lcn

   1、空閒TCP會話;
   2、客戶端正常斷開連接後的TCP會話;
   3、無連接的UDP數據包(記錄其兩次發送數據包的時間間隔);
上面三個計時器的默認值可以由類似下面的命令修改,其後面的值依次對應於上述的三個計時器:

# ipvsadm --set 28800 30 600

數據包在由Direcotr發往Realserver時,只有目標MAC地址發生了改變(變成了Realserver的MAC地址)。Realserver在接收到數據包後會根據本地路由表將數據包路由至本地迴環設備,接着,監聽於本地迴環設備VIP上的服務則對進來的數據庫進行相應的處理,而後將處理結果迴應至RIP,但數據包的原地址依然是VIP。


ipvs的持久連接:
無論基於什麼樣的算法,只要期望源於同一個客戶端的請求都由同一臺Realserver響應時,就需要用到持久連接。比如,某一用戶連續打開了三個telnet連接請求時,根據RR算法,其請求很可能會被分配至不同的Realserver,這通常不符合使用要求。


IPVS/DR

Director:

IP分配
VIP=192.168.0.210
RIP1=192.168.0.221
RIP2=192.168.0.222

1、下載安裝ipvsadm

wget http://www.linuxvirtualserver.org/software/kernel-2.6/ipvsadm-1.26.tar.gz
tar zxvf ipvsadm-1.26.tar.gz
cd ipvsadm-1.26
make && make install

 2、編寫並運行腳本(LVS服務器的腳本)

vim director.sh

#!/bin/bash
#
# LVS script for VS/DR
#
. /etc/rc.d/init.d/functions
#
VIP=192.168.0.210
RIP1=192.168.0.221
RIP2=192.168.0.222
PORT=80
#
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 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 eth0:1 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

3、給腳本加權限,並執行

chmod 755  /etc/rc.d/init.d/functions
chmod +x director.sh
./director.sh start

4、配置後端的WEB服務器腳本

vim realserver.sh

#!/bin/bash
#
# Script to start LVS DR real server.
# description: LVS DR real server
#
.  /etc/rc.d/init.d/functions
VIP=192.168.0.210
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

5、給腳本加權限,並執行

chmod 755  /etc/rc.d/init.d/functions
chmod +x realserver.sh
./realserver.sh start


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 顯示內核虛擬服務器表 userver 列表;
-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]
-s --scheduler scheduler 使用的調度算法,默認的調度算法是:wlc.有這樣幾個選項 
rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq
-p --persistent [timeout] 持久穩固的服務。這個選項的意思是來自同一個客戶的多次請求,將被同一臺真實的服務器處理。timeout的默認值爲300秒。;
-M --netmask netmask persistent granularity mask
-r --real-server server-address 真實的服務器[Real-Server:port]
-i --ipip 指定LVS 的工作模式爲隧道模式
--mcast-interface interface 指定組播的同步接口
-c --connection 顯示LVS 目前的連接 如:ipvsadm -L -c
--timeout 顯示tcp tcpfin udp的timeout值 如:ipvsadm -L --timeout
--daemon 顯示同步守護進程狀態
--stats 顯示統計信息 ipvsadm –Ln --state 總共的數量
--rate 顯示速率信息 ipvsadm –Ln --rete 平均值
--sort 對虛擬服務器和真實服務器排序輸出
--numeric -n 輸出IP地址和端口的數字形式


 集羣相關的命令參數

-A --add-service 在內核的虛擬服務器表中添加一條新的虛擬服務器記錄。也就是增加一臺新的虛擬服務器。
-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]
-s --scheduler scheduler 使用的調度算法,默認的調度算法是:wlc.有這樣幾個選項 rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq
-p --persistent [timeout] 持久穩固的服務。這個選項的意思是來自同一個客戶的多次請求,將被同一臺真實的服務器處理。timeout 的默認值爲300 秒。 持久連接;
-E --edit-service 編輯內核虛擬服務器表中的一條虛擬服務器記錄。  修改定義過的集羣服務
-D :刪除指定集羣服務


RS相關的命令參數:

-a --add-server 在內核虛擬服務器表的一條記錄裏添加一條新的真實服務器記錄。也就是在一個虛擬服務器中增加一臺新的真實服務器。向指定的CS中添加RS
-r --real-server server-address 真實的服務器[Real-Server:port],只有支持端口映射的LVS類型才允許此處使用跟集羣服務中不同的端口
LVS 類型:
-g : gateway,DR # 指定集羣類型爲LVS/DR
-i ipip,TUN  # 指定集羣類型爲LVS/TUN
-m:masquerade,NAT # 指定集羣類型爲 NAT

-w:指定RS權重:
-e:修改指定的RS屬性
-d :從指定的集羣服務中刪除某RS

 

LVS的持久連接

持久連接即是不考慮LVS的轉發方法,確保所有來自同一個用戶的連接轉發到同一個RealServer上

lvs持久連接適用於大部分調度算法。當某一種請求需要定向到一個realserver時,就要用到持久連接

一般應用到:ssl(http.https等),ftp。。
-p  //表示此連接爲持久連接
N  //表示維持此持久連接的時間。默認6分鐘。當超過這個時間後,如果網頁還沒有關掉,仍處於激活狀態,重新復位時間爲2分鐘。


持久連接的類型:

1.PCC(persistent client connector,持久用戶連接)同一個用戶所有的請求在超時範圍之內都被定位到同一個RealServer上,這個時候在指定端口的時候使用的是0端口,就是所有的請求都轉發出去。
2.PPC(persistent port connector)用戶的所有請求在超時範圍內按照端口定位到不同的RS上。
3.防火牆標記:把相關聯的端口在防火牆上打上同樣的標記,用戶在訪問兩個相關聯的服務的時候,就會定位到同一個RealServer上。
4.FTP connection:由於ftp使用的是兩個端口號,所以需要單獨列出來。

 

A.PCC實例:

Directory-------RealServer1(192.168.1.11)           |
           |____RealServer2(192.168.1.12)
VIP=192.168.1.10

Directory上的配置:

#ifconfig eth0 192.168.1.9/24
#ifconfig eth0:0 192.168.1.10 broadcast 192.168.1.10 netmask 255.255.255.255 up
#route add -host 192.168.1.10 dev eth0:0
#echo 1 >/proc/sys/net/ipv4/ip_forward
#ipvsadm -A -t 192.168.1.10:0 -s rr -p 600
#ipvsadm -a -t 192.168.1.10:0 -r 192.168.1.11:0 -g
#ipvsadm -a -t 192.168.1.10:0 -r 192.168.1.12:0 -g

RealServer1上的配置:

#ifconfig eth0 192.168.1.11/24

#ifconfig lo:0 192.168.1.10 broadcast 192.168.1.10 netmask 255.255.255.255 up

#route add -host 192.168.1.10 dev lo:0
#echo 1 >/proc/sys/net/ipv4/conf/lo/arp_ignore
#echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
#echo 2 >/proc/sys/net/ipv4/conf/lo/arp_announce
#echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce
#yum install httpd
#echo "rs1" > /var/www/html/index.html
#service httpd start


RealServer2上的配置:

#ifconfig eth0 192.168.1.12/24
#ifconfig lo:0 192.168.1.10 broadcast 192.168.1.10 netmask 255.255.255.255 up
#route add -host 192.168.1.10 dev lo:0
#echo 1 >/proc/sys/net/ipv4/conf/lo/arp_ignore
#echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
#echo 2 >/proc/sys/net/ipv4/conf/lo/arp_announce
#echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce
#yum install httpd
#echo "rs2" > /var/www/html/index.html
#service httpd start


在瀏覽其中輸入http://192.168.1.80然後刷新頁面,可以看到頁面一直不變,然後我們再使用ssh登錄到192.168.1.10,使用ifconfig查看,和網頁所在的RealServer同樣,實驗完成!

 

B.PPC就是根據服務的不同,定向到不同的RealServer上,在Directory上多寫幾個ipvsadm指向,注意端口要區分開來就行了

 

C.防火牆標記的持久連接
依然是上面的圖
兩個RealServer配置不變
在Directory上重新配置:

#ipvsadm -C //清空ipvs表
#iptables -t mangle -A PREROUTING -d 192.168.1.10 -p tcp --dport 80 -j MARK --set-mark 10  把目的地爲1982.168.1.10:80標記爲10
#ipvsadm -A -f 10 -s rr -p 60  //使用上面標記的10定義集羣服務
#ipvsadm -a -f 10 -r 192.168.1.11 -g //爲集羣定義RealServer
#ipvsadm -a -f 10 -r 192.168.1.12 -g

測試:
在瀏覽其中輸入
http://192.168.1.10可以訪問到網頁,但是如果使用ssh連接192.168.1.10的話,就只能被定向到192.168.1.12上也就是Directory上,實驗完成

 

D.使用防火牆標記實現http、https姻親關係:
依然使用上面的拓撲圖:
1.首先在RS上做證書


#yum install mod_ssl
#cd /etc/pki/tls/certs
#make httpd.pem  //在設置的時候,Common Name設置和Directory的主機名一樣就行了#mkdir /etc/httpd/ssl
#cp httpd.pem /etc/httpd/ssl
#vim /etc/httpd/conf.d/ssl.conf
 SSLCertificateFile /etc/httpd/ssl/httpd.pem
 SSLCertificateKeyFile /etc/httpd/ssl/httpd.pem
 ServerName node1.a.org:443  //我的Directory的主機名是node1.a.org
 #service httpd restart


2.其他的配置和上面一樣,同樣RealServer2上也採取同樣的配置,我這裏就不演示了

3.Directory上的配置如下:
只需要在iptables上多添加一條命令如下

#iptables -t mangle -A PREROUTING -d 192.168.1.10 -p tcp --dport 443 -j MARK --set-mark 10 //這裏的標記和http的80端口的標記是一樣的,這個時候在訪問的時候,就會建立姻親關係,其他的配置和C的配置一樣,不多演示了

測試:在瀏覽器中輸入http://192.168.1.80https://192.168.1.80發現訪問的是同一個頁面,就證明成功啦!

 

LVS負載均衡器本身是沒有對後端服務器做健康狀態監測的功能的;所以我們可以編寫一個小小的腳本來完成這個功能; 

註釋:這些腳本的列子很粗糙,只是讓你們瞭解整個過程是怎樣的;

健康狀態監測腳本實例:

RS健康狀態檢查腳本示例第一版:
        #!/bin/bash
        #
        VIP=192.168.10.3
        CPORT=80
        FAIL_BACK=127.0.0.1
        FBSTATUS=0
        RS=("192.168.10.7" "192.168.10.8")
        RSTATUS=("1" "1")
        RW=("2" "1")
        RPORT=80
        TYPE=g
        add() {
          ipvsadm -a -t $VIP:$CPORT -r $1:$RPORT -$TYPE -w $2
          [ $? -eq 0 ] && return 0 || return 1
        }
        del() {
          ipvsadm -d -t $VIP:$CPORT -r $1:$RPORT
          [ $? -eq 0 ] && return 0 || return 1
        }        while :; do
          let COUNT=0
          for I in ${RS[*]}; do
            if curl --connect-timeout 1 http://$I &> /dev/null; then
              if [ ${RSTATUS[$COUNT]} -eq 0 ]; then
                 add $I ${RW[$COUNT]}
                 [ $? -eq 0 ] && RSTATUS[$COUNT]=1
              fi
            else
              if [ ${RSTATUS[$COUNT]} -eq 1 ]; then
                 del $I
                 [ $? -eq 0 ] && RSTATUS[$COUNT]=0
              fi
            fi
            let COUNT++          done
          sleep 5
        done
    RS健康狀態檢查腳本示例第二版:
        #!/bin/bash
        #
        VIP=192.168.10.3
        CPORT=80
        FAIL_BACK=127.0.0.1
        RS=("192.168.10.7" "192.168.10.8")
        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
            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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章