lvs負載均衡技術

本文在參考譽天鄒老師培訓教程基礎上,已做部分補充完善,大家閱讀時有個思路即可。

 

lvs負載均衡技術

1.相關術語
什麼是負載均衡?
在大型的網絡應用中,使用多臺服務器提供同一個服務是常有的事。平均分配每臺服務器上的壓力、將壓力分散的方法就叫做負載均衡。

智能DNS輪詢?
實現服務器流量的負載均衡,原理是“給網站訪問者隨機分配不同ip”

集羣?
由2臺或多臺計算機連接在一起,共同執行任務的。
根據業務目標分爲:HA(高可用)、LB(負載均衡)、HP(高性能)

HA:keepalived、heartbeat、rhcs
LB:lvs、nginx、haproxy、F5
HP:
www.zghpc.com/index/Downfile/infor_id/42


2.lvs負載均衡技術深究
2.1 lvs簡介
linux虛擬服務器,由章文嵩博士發起的自由軟件項目,現在lvs成爲linux標準內核的一部分,直接編譯到內核中了。
編譯進內核的模塊叫ipvs,管理工具叫ipvsadm,類似於iptables,netfiler編譯進內核的模塊,iptables是其一個管理工具;

如何查看內核是否編譯指定模塊?(查看/boot下的config文件)
cat config-2.6.18-194.el5 |grep -i ipvs

一個模塊的功能是否被加進內核中,如何查看?
=y 在內核中已經編譯成模塊,並每次開機默認加載,如lsmod;
=m 在內核中已經編譯成模塊,默認不加載,有需要再加載,如nfs;
lsmod |grep nfs #查看nfs模塊,默認是沒有被加載的
modprobe nfs  #加載nfs模塊


2.2 lvs的3種工作模式
dr、nat、tun

lvs-nat:
rs和ds必須在同一個網絡,僅用於與ds通信;
ds接收所有數據包;
rs默認網關指向ds;
ds支持端口映射,即將客戶端請求映射到rs的另一個端口;
支持任意平臺os;
單一的ds是整個集羣瓶頸;
擴展有限,DS將處理所有請求,壓力大,擴展10個就不行了;

lvs-dr:
rs必須與ds在同一網絡;
rs是公網IP地址;
ds接收的數據包,根據調度算法將數據包轉發到rs;
rs不需要ds作爲默認網關;
支持任意平臺os;
可支持更多rs;
性能最佳,但必須要求近距離,如同一個機房,不能做異地分佈,lvs-tun可解決;

lvs-tun:
dr和rs不必在同一個網絡;
rip必須使用公網地址;
ds只處理進來的請求,不處理出去的請求;
ds不支持端口映射;
只能使用那些支持IP隧道協議的os做rs;
可實現基於網絡的集羣,脫離lvs-dr的rs之間的距離限制;

專線加密;
二層:在mac之外再加一層mac;
三層:源ip目標ip之外再加一層ip;
隧道目的:隱藏意圖,通過轉換(ip套ip)來隱藏目的;

現系統內核默認支持以下2個內核參數。
arp_ignore:定義對目標地址爲本地IP的ARP詢問不同的應答模式
0 - (默認值): 迴應任何網絡接口上對任何本地IP地址的arp查詢請求
1 - 只回答目標IP地址是來訪網絡接口本地地址的ARP查詢請求
2 -只回答目標IP地址是來訪網絡接口本地地址的ARP查詢請求,且來訪IP必須在該網絡接口的子網段內
3 - 不迴應該網絡界面的arp請求,而只對設置的唯一和連接地址做出迴應
4-7 - 保留未使用
8 -不迴應所有(本地地址)的arp查詢 

arp_announce:對網絡接口上本地IP地址發出的ARP迴應作出相應級別的限制:
0 - (默認) 在任意網絡接口(eth0,eth1,lo)上的任何本地地址
1 -儘量避免不在該網絡接口子網段的本地地址做出arp迴應,當發起ARP請求的源IP地址是被設置應該經由路由達到此網絡接口的時候很有用,此時會檢查來訪IP是否爲所有接口上的子網段內ip之一。如果該來訪IP不屬於各個網絡接口上的子網段內,那麼將採用級別2的方式來進行處理。
2 - 對查詢目標使用最適當的本地地址。在此模式下將忽略這個IP數據包的源地址並嘗試選擇與能與該地址通信的本地地址,首要是選擇所有的網絡接口的子網中外出訪問子網中包含該目標IP地址的本地地址, 如果沒有合適的地址被發現,將選擇當前的發送網絡接口或其他的有可能接受到該ARP迴應的網絡接口來進行發送。

lvs-dr模式工作原理的常見問題
(1)lvs-dr如何處理請求報文的,會修改IP包內容嗎?不會修改IP包的內容
lvs-dr本身不會關心IP層以上的信息,即使是端口號也是tcp/ip協議棧去判斷是否正確,lvs-dr本身主要做這麼幾個事:
1)接收client的請求,根據設定的負載均衡算法選取一臺realserver的ip;
2)以選取的這個ip對應的mac地址作爲目標mac,然後重新將IP包封裝成幀轉發給這臺RS;
3)在hash table中記錄連接信息。

vs/dr做的事情很少,也很簡單,所以它的效率很高,不比硬件負載均衡設備差多少。
數據包、數據幀的大致流向是這樣的:client --> VS --> RS --> client

(2)RealServer爲什麼要在lo接口上配置VIP?在出口網卡上配置VIP可以嗎?
既然要讓RS能夠處理目標地址爲vip的IP包,首先必須要讓RS能接收到這個包。在lo上配置vip能夠完成接收包並將結果返回client。

不可以將VIP設置在出口網卡上,否則會響應客戶端的arp request,造成client/gateway arp table紊亂,以至於整個load balance都不能正常工作。

(3)RealServer爲什麼要抑制arp幀?
lvs-dr在同一個網絡,且RS和DS都配有vip地址,當客戶端請求VIP時,誰去響應?這時候只允許DS接收arp請求,RS就要抑制arp請求。(RS內核參數arp_ignore實現)

DS不知道RS上有vip地址的,DS只負責把arp請求分配給RS,RS接收到數據包後,打開數據包發現目標ip在lo:0上,就給lo:0,迴應的時候也希望通過lo:0接口,這樣就可以避免RS直接響應客戶端,更好地屏蔽RS。

上一問題中已經作了說明,這裏結合具體實施部署時說明:
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
這兩條是可以不用的,因爲arp對邏輯接口沒有意義。

echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
如果RS的外部網絡接口是eth0,那麼真正要執行的是:
echo "1" >/proc/sys/net/ipv4/conf/eth0/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/eth0/arp_announce
在此建議把上面兩條也加到腳本里,因爲萬一系統裏上面兩條默認的值不是0,那可能會出問題。

arp_ignore:定義對目標地址爲本地IP的ARP詢問不同的應答模式;
別人的arp請求,我不接收,我不響應別人的arp,我不接收別人;
arp_announce:對網絡接口上本地IP地址發出的ARP迴應作出相應級別的限制。
別人訪問我這個接口,我不用這個接口響應別人,我主動去廣播。

(4)lvs-dr load balancer(director)與RS爲什麼要在同一網段中?
從第一個問題中應該明白lvs-dr是如何將請求轉發給RS的?它是在數據鏈路層來實現的,所以director必須和RS在同一網段裏面。

(5)爲什麼director上eth0接口除了VIP另外還要配一個ip(即DIP)?
如果是用了keepalived等工具做HA或者Load Balance,則在健康檢查時需要用到DIP,否則沒有存在的實際意義。

(6)lvs-dr ip_forward需要開啓嗎?
不需要。因爲director跟realserver是同一個網段,無需開啓轉發。

(7)director的vip的netmask一定要是255.255.255.255嗎?
lvs-dr裏,director的vip的netmask 沒必要設置爲255.255.255.255,也不需要。
route add -host $VIP dev eth0:0
director的vip本來就是要像正常的ip地址一樣對外通告的,不要搞得這麼特殊.

參考LVS-DR工作原理圖文詳解
http://www.cnblogs.com/czh-liyu/archive/2011/11/29/2267963.html


2.3 lvs的4種靜態調度算法
所謂靜態就是請求進來後,按照某種調度算法,將請求分給後端真實服務器,不關心後端是否有活動連接,後端忙不忙跟我沒有關係,我只負責分配請求;
動態就是判斷後端真實服務器的繁忙程度,再分配請求;

(1)輪詢調度rr
將外部請求按順序輪流分配到集羣中的真實服務器,均等對待每一臺服務器,不管服務器的連接數和系統負載;

類似DNS輪詢;
優先級或權值沒有意義;

問題:一服務器很繁忙,請求被調度過來,另一服務器很空閒,沒有請求調度。

(2)加權輪詢wrr
根據真實服務器的不同處理能力來調度訪問請求,保證性能強的服務器處理更多的訪問流量。調度器可以自動問詢真實服務器的負載情況,並動態調整其權值。

設定優先級或權值,性能好的權值高,處理請求多,數值越大,權重越高;
與ha中的權重有區別,wrr設爲1:10,

問題:性能好的服務器處理很繁忙,請求還是調度過來,不會將請求調度給性能差些的空閒服務器。

(3)目標地址散列(目標哈希)dh
以請求的目標ip地址,作爲散列鍵從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空。

客戶端請求第一次調度給a服務器,下次訪問仍然調度給a服務器,可產生緩存。

(4)源地址散列sh
以請求的源ip地址,作爲散列鍵從靜態分配的散列表找出對應的服務器,若該服務器是可用的且未超載,將請求發送到該服務器,否則返回空。


2.4 lvs的6種動態調度算法
(1)最少鏈接lc
通過lc動態地將請求調度到已建立的連接數最少的服務器上。集羣系統中的真實服務器具有相近的系統性能,採用lc調度算法可以較好的負載均衡。

調度器會計算真實服務器的活動連接數和非活動連接數的總和,
判斷連接數的個數,

服務器開銷=活動連接數*256+非活動連接數,值小的,調度器就分配請求給誰。

(2)加權最少鏈接wlc
對於集羣系統中服務器性能差異較大的情況下,調度器採用wlc可以優化負載均衡性能,具有最高權值的服務器將承受較大比例的活動連接負載。調度器可以自動詢問真實服務器的負載情況,並動態調整其權值。

默認的調度算法,最優秀的調度算法,目前絕大多數都採用此算法;
服務器開銷=(活動連接數*256+非活動連接數)/權重,值小的,調度器就分配請求給誰。

(3)最短的期望延遲sed
在wlc基礎上進行優化;
只考慮活動連接數;
服務器開銷=(活動連接數+1)*256/權重,值小的,調度器就分配請求給誰。
爲了避免活動連接數都爲0,請求分配給誰?

(4)最少隊列調度ng
在wlc基礎上進行優化;
無需隊列,若一臺真實服務器的連接數爲0,就直接分配過去,不需要進行sed運算。
只考慮活動連接數;
在sed運算時,活動連接數都爲0,a權重爲1,b權重爲10,則10個請求都分給B?

(5)基於局部的最少鏈接(lblc)
dh的動態實現,對目標ip地址的負載均衡,用於cache集羣系統。
以請求的目標ip地址,找出該目標ip地址最近使用的服務器,若該服務器是可用的且未超載,將請求發送到該服務器;
的原則選出一個可用的服務器,將請求發送過去。

(6)帶複製的基於局部的最少鏈接(lblcr)
lblc是維護從一個目標IP地址到一臺服務器的映射;
lblcr是維護從一個目標IP地址到一組服務器的映射;

以請求的目標IP地址找出該目標IP地址對應的服務器組,按最少鏈接lc原則從服務器組中選出一臺服務器,若服務器沒有超載,將請求發送到該服務器;若超載,則按lc原則從這個集羣中選出一臺服務器,將該服務器加入到服務器組中,將請求發送到該服務器。同時,當該服務器組有一段時間沒有被修改,將最忙的服務器從服務器組中刪除,以降低複製的程度。

2.5 lvs-nat實例配置:
拓撲:
Director:eth0 10.124.0.1(dip) eth1:172.16.0.1(vip) 開啓路由轉發
Realserver1: eth0 10.124.0.21 gw 10.124.0.1 開啓httpd
Realserver2: eth0 10.124.0.22 gw 10.124.0.1 開啓httpd
client:172.16.0.11

#添加集羣服務
ipvsadm -A -t 172.16.0.1:80 -s rr
ipvsadm -L -n
#爲集羣服務添加主機,t即tcp;m即nat,dr即r;w即權重
ipvsadm -a -t 172.16.0.1:80 -r 10.124.0.21 -m -w 1
ipvsadm -a -t 172.16.0.1:80 -r 10.124.0.22 -m -w 2
#保存配置
service ipvsadm save
#修改調度算法
ipvsadm -E -t 172.16.0.1:80 -s wrr

2.6 lvs-dr實例配置:
拓撲:
DS:eth0 10.124.0.1(dip)
RS1: eth0 10.124.0.21  開啓httpd
RS2: eth0 10.124.0.22  開啓httpd
client:10.124.0.252

#配置DS子接口
ifconfig eth0:1 10.124.0.100 broadcast 10.124.0.100 netmask 255.255.255.255 up
#配置路由,迴應走eth0:1
route add -host 10.124.0.100 dev eth0:1
route -n

#需要安裝ipvsadm
#DS配置集羣和調度主機,-g默認的dr模式,最終顯示爲route
ipvsadm -A -t 10.124.0.100:80 -s wlc
ipvsadm -a -t 10.124.0.100:80 -g -r 10.124.0.21 -w 1
ipvsadm -a -t 10.124.0.100:80 -g -r 10.124.0.22 -w 2
ipvsadm -L -n


#配置RS,安裝httpd
#設置內核參數,不接收別的arp廣播,不廣播自己的mac地址
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

#配置lo:0,ip地址不是給某個網卡的,是屬於這個服務器上。
ifconfig lo:0 10.124.0.100 broadcast 10.124.0.100 netmask 255.255.255.255 up
#配置路由,迴應客戶端走lo:0。因爲不指定的話,eth0也可能迴應客戶端。
route add -host 10.124.0.100 dev lo:0


單一DS掛掉,怎麼辦?lvs+keepalived
#兩臺DS上安裝keepalived
yum -y install kernel-devel gcc openssl-devel
tar -zxvf keepalived-1.1.19.tar.gz
cd keepalived-1.1.19
./configure  --sysconf=/etc --with-kernel-dir=/usr/src/kernels/2.6.18-8.el5-i686
make && make install
ln -s /usr/local/sbin/keepalived  /sbin/

在編譯選項中,“--sysconf”指定了Keepalived配置文件的安裝路徑,即路徑爲/etc/Keepalived/Keepalived.conf,“--with-kernel-dir”這個參數必須指定,否則就找不到ipvs,啓動不起來,但這個參數並不是要把Keepalived編譯進內核,而是指定使用內核源碼裏面的頭文件,就是include目錄。如果要使用LVS時,才需要用到此參數,否則是不需要的。

#配置keepalived文件
vim /etc/Keepalived/Keepalived.conf
global_defs {
  router_id LVS_MASTER  #backup節點爲LVS_BACKUP
}

vrrp_instance VI_1 {
  state MASTER  #backup節點爲BACKUP
  interface eth0
  virtual_router_id 51
  priority 100  #backup節點爲80
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass 1111
  }
  virtual_ipaddress {
    192.168.10.100
  }
}

virtual_server 192.168.10.100 80 {
  delay_loop 6
  lb_algo rr
  lb_kind DR
  net_mask 255.255.255.0
  persistence_timeout 50
  protocol TCP

  real_server 192.168.10.3 80 {
    weight 1
    TCP_CHECK {
      connect_timeout 10
      nb_get_retry 3
      delay_before_retry 3
      connect_port 80
    } 
  }

  real_server 192.168.10.4 80 {
    weight 1
    TCP_CHECK {
      connect_timeout 10
      nb_get_retry 3
      delay_before_retry 3
      connect_port 80
    } 
  }
}

#啓動keepalived服務,並添加到開機啓動
/etc/init.d/keepalived start
chkconfig keepalived on


#realserver設置
cat /etc/init.d/realserver.sh
#!/bin/bash

WEB_VIP=192.168.10.100
./etc/rc.d/init.d/functions

case "$1" in
start)
       ifconfig lo:0 $WEB_VIP netmask 255.255.255.255 broadcast $WEB_VIP
       /sbin/route add -host $WEB_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 $WEB_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"
       ;;
*)
# Invalid entry.
        echo "Usage: $0 {start|stop}"
        exit 1
esac
exit 0

#設置執行權限,並啓動服務,添加開機啓動
chmod +x /etc/init.d/realserver.sh
/etc/init.d/realserver.sh start
ln -s /etc/init.d/realserver.sh /etc/rc.d/rc3.d/S99realserver.sh
ln -s /etc/init.d/realserver.sh /etc/rc.d/rc5.d/S99realserver.sh

(2013年7月14日更新v1.0)

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