LVS四種實現模式詳解

51cto發表於2019-04-20

一、叢集cluster

    當後端伺服器承受不住訪問的壓力,提高伺服器效能的解決方案會極大增加成本時,人們提出了橫向擴充套件的解決方案。增加一臺或幾臺伺服器,提供相同的服務,通過前段分發器將訪問量均勻的分配到後臺伺服器上。這種多臺伺服器組成的陣列集合就叫做叢集。

    叢集按功能劃分有三種模型:

  •     負載均衡叢集(loadBalance)

  •     高可用性叢集(High Availability)

  •     高效能叢集(High Performance)


二、負載均衡叢集

    根據某種演算法將負載壓力合理的分配到叢集中的每一臺計算機上,以減輕主伺服器的壓力。

    負載均衡實現的方式一般有三種:

  •     通過DNS輪詢進行負載均衡

  •     通過反向代理進行負載均衡

  •     通過網路地址轉換(NAT)進行負載均衡

    下面我要說的linux virtual server就是通過NAT技術進行負載均衡的


三、Linux Virtual Server (linux虛擬服務)

    負載均衡的實現可以使用硬體如著名的F5裝置,也可以使用軟體如:LVS、NGINX反向代理,畢竟硬體是要花錢的,軟體是開源免費的,你懂的。

    lvs是國內章文嵩教授牽頭開發的開源專案,現在已經被收到linux2.6以上的核心版本中,不需要對系統打補丁就可以輕鬆實現。lvs工作於IOS七層模型的傳輸層,通過對TCP、UDP、SCTP、IPsec ESP、AH這些工作在四層的協議的支援,根據目標地址和埠做出轉發與否的決策,根據排程演算法做出轉發至哪一個埠的決策。

    LVS將其控制程式ipvs巢狀至傳輸層資料流的Input鉤子函式上,ipvs將傳送至本控制器主機(director)上的資料流在input鏈上進行截流,通過對資料包文的分析根據自身的演算法將資料流轉發至後臺真正提供服務的主機(Real Server)上,達到根據後端伺服器負載能力均衡分配處理任務的效果。

    lvs中的術語:

    ClientIP:CIP------------------------客戶端ip

    Dirvector Virtual IP:VIP------------控制器上對外開放的ip

    Dirvector IP:DIP--------------------控制器上連線後臺伺服器的ip

    Realserver IP:RIP-------------------後臺伺服器的ip

    Director-----------------------------控制器或排程器

    Real Server--------------------------後臺提供服務的主機


四、LVS的四種型別

    1、lvs-nat(net adress translation)

    類似於DNAT,但支援多目標轉發。通過修改請求報文的目標地址為根據排程演算法所挑選出的某RS的RIP來進行轉發;

    架構特性:

       (1)RS應該使用私有地址,即RIP應該為私有地址:各RS的閘道器必須指向DIP;

       (2)請求和響應報文都經由director轉發:高負載場景中,dircetor可能成為瓶頸;

       (3)支援埠對映;

       (4)RS可以使用任意OS;

       (5)RS的RIP必須與director的DIP在同一網路;

     2、lvs-dr(direct route)

     director在實現轉發時不修改請求的ip首部,而是通過直接封裝MAC首部完成轉發:目標MAC是Dircetor根據排程演算法挑選出某RS的MAC地址,此型別中,RS也有同Director一樣的VIP。

    架構特點:

        (1)通過靜態繫結或核心引數修改或arptables規則實現只有Director上的VIP響應服務請求,RS上的VIP拒絕響應服務請求;

        (2)RS上的RIP可以是私有地址,也可以是公網地址;

        (3)請求報文必須經過Director排程,響應報文直接由RS通過VIP返回給使用者;

        (4)各RIP必須與DIP在同一網路中;

        (5)不支援埠對映;

        (6)RS可以使用大多數的OS;

        (7)RS的閘道器一定不能指向Director;

    3、lvs-tun(Tunnel transmission)

    隧道傳輸ipip:不修改請求報文ip首部,而是通過ip隧道機制在原有的ip報文之外在封裝ip首部,經由網際網路把請求報文交給選定的rs;

    架構特性:

       (1)RIP,DIP,VIP都是公網地址;

       (2)RS的閘道器不能,也不可能指向DIP;

       (3)請求報文由Director分發,但響應報文直接由RS響應給Client;

       (4)不支援埠對映;

       (5)RS的OS必須得支援IP隧道,現在只有linux系統支援,windows,bsfdb等不支援;

    4、lvs-fullnat(雙向轉換)

    通過請求報文的源地址為DIP,目標為RIP來實現轉發:對於響應報文而言,修改源地址為VIP,目標地址為CIP來實現轉發:

    架構特點:這是一種對nat模型的改進,是一個擴充套件,使得RS與Director可以處於不同網路。

        (1)RIP,DIP可以使用私有地址;

        (2)RIP和DIP可以不再同一個網路中,且RIP的閘道器未必需要指向DIP;

        (3)支援埠對映;

        (4)RS的OS可以使用任意型別;

        (5)請求報文經由Director,響應報文也經由Director;


五、LVS的十種排程演算法

    四種靜態演算法,不考慮後端伺服器實際負載情況:

    1、RR

    根據規則依次論調,不考慮RS的效能。輪到誰就轉發給誰。

    2、WRR

    加權輪詢,加入了weight(權重),可以根據RS的效能為其設定權重值,權重越大功能越強,但是不能發硬當前的伺服器的執行的情況。

    3、DH

    目標地址hash,適用於前段是一個drector後端是幾個快取伺服器,當客戶端第一次訪問到的是RS1的時候,DH這種演算法保證,在客戶端重新整理後還是訪問的是RS1。

    4、SH

    源地址hash,用於保證響應的報文和請求的報文是同一個路徑。

    六種動態演算法,考慮後端伺服器當前負載後再進行分配:

    1、LC

    least connection,當一個使用者請求過來的時候,就計算下哪臺RS的連結誰最小,那麼這臺RS就獲得了下次響應客戶端請求的機會,計算的方法Overhead=active*256+inactive,如果兩者的結果是相同的則從LVS中的規則依次往下選擇RS。這種演算法也是不考慮伺服器的效能的。

    2、WLC

    這個就是加了權重的LC,考慮了RS的效能,即是效能好的就給的權重值大一些,不好的給的權重值小一些。缺點就是如果Overhead相同,則會按規則表中的順序,由上而下選擇RS,Overhead=(active*256+inactive)/weight

    3、SED

    就是對WLC的情況的補充,Overhead=(active+1)*256/weight,加一,就是為了讓其能夠比較出大小。

    4、NQ

    never queue 基本和SED相同,避免了SED當中的效能差的伺服器長時間被空閒的弊端,它是第一個請求給效能好的伺服器,第二個請求一定是給的空閒伺服器不論它的效能的好與壞。以後還是會把請求給效能好的伺服器

    5、LBLC

    它就是動態DH和LC的組合,適用於cache群,對於從來沒有來過的那些新的請求會分給當前連線數較少的那臺伺服器。

    6、LBLCR

    帶有複製功能的LBLC,它的適用場景這裡舉例說明一下,比如說現在又RS1和RS2,第一次訪問RS1的5個請求第二次又來了,理所應到Director將會將其交給RS1,而此時在RS2是非常閒的,所以此時最好的處理方法就是可以將後來的這5個請求分別交給RS1和RS2,所以此時就需要把客戶端第一次請求的資源複製下來。(特殊情況)


六、ipvsadm使用說明

    1、編譯安裝或yum源安裝      

    下載:http://www.linuxvirtualserver.org/software/

    注意對應自己的核心版本

    ipvsadm-1.24.tar.gz
    tar zxvf ipvsadm-1.24.tar.gz
    cd ipvsadm-1.24
    make
    make install

    2、新增一個叢集服務director

    ipvsadm -A|E -t|u|f service-address [-s scheduler] 

                     -A:新增
                     -E:修改
                     -t:tcp

                     -u:udp

                     -f:打防火牆標記的tcp或udp

                     -D:刪除

                     -s:指定排程演算法

    3、給一個叢集服務新增一條RS規則

    ipvsadm -a|e -t|u|f service-address -r server-adddress [-g|-i|-m] [-w wegiht]

                     -a:新增
                     -e:修改
                     -d:刪除

                     -g:dr模式直接路由gatway

                     -i:ipip,tun隧道

                     -m:NAT模式,地址轉換

     # ipvsadm -D -t 172.16.13.10:80 
     # ipvsadm -d -t 172.16.13.10:80 -r 192.168.13.13:8080      
     # ipvsadm -C      //清空所有群集服務的定義

     4、 檢視規則:
     ipvsadm -L -n -c --stats

                     -c:列出當前所有的connection

                     --stats:列出統計資料

                     --rate:速率資料

     5、儲存規則:default save to /etc/sysconfig/ipvsadm

     # service ipvsadm save    
     # ipvsadm -S >/path/to/file
     # ipvsadm-save >/path/to/file

     6、過載規則:

     # service ipvsadm restart
     # ipvsadm -R < /path/from/file
     # ipvsadm-restore < /path/from/file

     7、清空所有已匹配的計數器

     ipvsadm -Z [-t|u|f service-address]


七、LVS-NAT示例

    虛擬網路型別為僅主機模式host-only

    Client :172.16.13.21     
    Director VIP:172.16.13.10  DIP:192.168.13.10        
    WebServer1:192.168.13.13     
    WebServer2:192.168.13.14

    Director配置:

    # yum install ipvsadm -y
    # echo 1 > /proc/sys/net/ipv4/ip_forward 
    # ipvsadm -A -t 172.16.13.10:80 -s wrr  
    # ipvsadm -a -t 172.16.13.10:80 -r 192.168.13.13:80 -m -w 1
    # ipvsadm -a -t 172.16.13.10:80 -r 192.168.13.14:80 -m -w 2

    Webserver配置

    安裝nginx當作web伺服器,web1主頁寫上192.168.13.13;web2主頁寫上192.168.13.14;

    將WebServer閘道器指定為192.168.13.10

    Client測試:

    瀏覽器輸入http://172.16.13.10/index.html

    # curl  http://172.16.13.10
    # tcpdump -i eth0 host 172.16.13.10 and tcp port 80     \\抓包工具在Director上使用

八、LVS-DR示例

    在同一網段網路拓撲如下

    Director配置:

echo 1 > /proc/sys/net/ipv4/ip_forward 
ifconfig eth0 172.16.13.10 up
ifconfig eth0:0 172.16.13.11 netmask 255.255.255.255 broadcast 172.16.13.11 up
route add -host 172.16.13.11 dev eth0:0      //以防萬一,不是必須
ipvsadm -A -t 172.16.13.11:80 -s rr
ipvsadm -a -t 172.16.13.11:80 -r 172.16.13.13:80 -g 
ipvsadm -a -t 172.16.13.11:80 -r 172.16.13.14:80 -g

    WebServer1配置:

ifconfig eth0 172.16.13.13 up
ifconfig eth1 192.168.1.13 up
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig lo:0 172.16.13.11 netmask 255.255.255.255 broadcast 172.16.13.11 up
route add -host 172.16.13.11 dev lo:0

    WebServer2配置:

ifconfig eth0 172.16.13.14 up
ifconfig eth1 192.168.1.14 up
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig lo:0 172.16.13.11 netmask 255.255.255.255 broadcast 172.16.13.11 up
route add -host 172.16.13.11 dev lo:0

    在不同網段網路拓撲圖

    Director配置:

echo 1 > /proc/sys/net/ipv4/ip_forward 
ifconfig eth0 192.168.1.10 up
ifconfig eth0:0 172.16.13.11 netmask 255.255.255.255 broadcast 172.16.13.11 up
route add default gw 192.168.1.254      
ipvsadm -A -t 172.16.13.11:80 -s rr
ipvsadm -a -t 172.16.13.11:80 -r 192.168.1.13:80 -g 
ipvsadm -a -t 172.16.13.11:80 -r 192.168.1.14:80 -g

    WebServer1配置:

ifconfig eth0 192.168.1.13 up
route add default gw 192.168.1.254
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig lo:0 172.16.13.11 netmask 255.255.255.255 broadcast 172.16.13.11 up
route add -host 172.16.13.11 dev lo:0

    WebServer2配置:

ifconfig eth1 192.168.1.14 up
route add default gw 192.168.1.254
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
ifconfig lo:0 172.16.13.11 netmask 255.255.255.255 broadcast 172.16.13.11 up
route add -host 172.16.13.11 dev lo:0

九、關於核心引數 

    arp_igonre

    0: 如果路由向我的一個網路介面傳送廣播,請求的是本機上的其他介面,就告知它(預設值);

    1:如果路由向我的一個網路介面傳送廣播,請求的是本機上的其他介面,就拒絕它;

    arp_announce

    0: 一旦我接入一個網路,就向這個網路內的所有主機通告自己所有的網路介面資訊,不隱藏(預設值);

    1:一旦我接入一個網路,就將接入網路這一個介面的資訊通告其他主機,本機上的其他介面資訊可以通告也可以不通告;

    2:一旦我接入一個網路,就將接入網路這一個介面的資訊通告其他主機,本機上的其他介面資訊絕對不通告出去;  


十、指令碼

    lvs-dr指令碼

    Director指令碼示例

#!/bin/bash
vip=172.16.13.11
rip=('172.16.13.13' '172.16.13.14')
weight=('1' '2')
port=80
scheduler=rr
ipvstype='-g'
case $1 in
start)
    iptables -F -t filter
    ipvsadm -C
    ifconfig eth0:0 $vip broadcast $vip netmask 255.255.255.255 up
    route add -host $vip dev eth0:0
    echo 1 > /proc/sys/net/ipv4/ip_forward
    ipvsadm -A -t $vip:$port -s $scheduler
    [ $? -eq 0 ] && echo "ipvs service $vip:$port added."  || exit 2
    for i in `seq 0 $[${#rip[@]}-1]`; do
        ipvsadm -a -t $vip:$port -r ${rip[$i]} $ipvstype -w ${weight[$i]}
        [ $? -eq 0 ] && echo "RS ${rip[$i]} added."
    done
    touch /var/lock/subsys/ipvs
;;
stop)
    echo 0 > /proc/sys/net/ipv4/ip_forward
    ipvsadm -C
    ifconfig eth0:0 down
    rm -f /var/lock/subsys/ipvs
    echo "ipvs stopped."
;;
status)
    if [ -f /var/lock/subsys/ipvs ]; then
echo "ipvs is running."
ipvsadm -L -n
else
echo "ipvs is stopped."
fi
;;
*)
    echo "Usage: `basename $0` {start|stop|status}"
exit 3
;;
esac

    RS指令碼示例

#!/bin/bash
vip=172.16.13.11
interface="lo:0"
case $1 in
start)
    echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
    ifconfig $interface $vip broadcast $vip netmask 255.255.255.255 up
    route add -host $vip dev $interface
;;
stop)
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
    ifconfig $interface down
;;
status)
    if ifconfig lo:0 |grep $vip &> /dev/null; then
echo "ipvs is running."
    else
echo "ipvs is stopped."
    fi
;;
*)
    echo "Usage: `basename $0` {start|stop|status}"
    exit 1
esac

    lvs-nat指令碼

    Director指令碼示例

#!/bin/bash
chmod  755 /etc/rc.d/init.d/functions
. /etc/rc.d/init.d/functions
VIP=172.16.13.11
DIP=192.168.1.11
RIP1=192.168.1.13
RIP2=192.168.1.14
#
case "$1" in
start)  
  /sbin/ifconfig eth0:1 $VIP netmask 255.255.255.0 up
  echo 1 > /proc/sys/net/ipv4/ip_forward
  /sbin/iptables -F
  /sbin/iptables -Z
  /sbin/ipvsadm -C
  /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
  /bin/touch /var/lock/subsys/ipvsadm.lock
;;
stop)
  echo 0 > /proc/sys/net/ipv4/ip_forward
  /sbin/ipvsadm -C
  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

    RS指令碼示例

#!/bin/bash
VIP=172.16.13.11
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

十一、健康狀態檢查

    在Director上實現後端RS健康狀態檢查的指令碼:

    lvs本身不支援對RS的健康狀態作檢測,所以應該寫指令碼實現;對指令碼有如下要求:

健康:週期性檢查機制

狀態發生轉變時,要作出相應處理

up --> down: 建議要至少確認三次;

down --> up: 建議一次以上(含一次);

下線處理機制:

(1) 設定權重為0;

(2) 將相應的RS從ipvs的可用RS列表中移除;

上線處理機制:

(1) 設定為正常權重;

(2) 將相應的RS新增至ipvs的可用RS列表;

如何做健康狀態檢查:

三種方案:

IP層:ping等主機線上狀態探查工具;

傳輸層:埠掃描工具探查服務線上狀態;

應用層:請求專用於健康狀態檢查的資源或者某正常資源;

備用伺服器:

sorry server, backup server

可以在Director上直接實現:即配置director成為web服務,僅提供有限資源,在所有RS都故障時,方才啟用此server;

#!/bin/bash
#
fwm=10
sorry_server='127.0.0.1'
lvstype='-m'
checkloop=3
logfile=/var/log/ipvs_health_check.log
rs=('192.168.1.13' '192.168.1.14')
rw=('1' '1')
rsstatus=(0 0)
addrs() {
# $1: rs, $2: rs weight
ipvsadm -a -f $fwm -r $1 $lvstype -w $2
[ $? -eq 0 ] && return 0 || return 1
}
delrs() {
# $1: rs
ipvsadm -d -f $fwm -r $1
[ $? -eq 0 ] && return 0 || return 1
}
chkrs() {
 # $1: rs
local i=1
while [ $i -le $checkloop ]; do
if curl --connect-timeout 1 -s http://$1/index.html | grep -i "real[[:space:]]* server" &> /dev/null; then
return 0
fi
let i++
sleep 2
done
return 1
}
   
initstatus() {
for host in `seq 0 $[${#rs[@]}-1]`; do
        if chkrs ${rs[$host]}; then
 if [ ${rsstatus[$host]} -eq 0 ]; then
rsstatus[$host]=1
        fi
else
if [ ${rstatus[$host]} -eq 1 ]; then
rsstatus[$host]=0
fi
fi
done
}
initstatus
while :; do
for host in `seq 0 $[${#rs[@]}-1]`; do
    if chkrs ${rs[$host]}; then 
        if [ ${rsstatus[$host]} -eq 0 ]; then
        addrs ${rs[$host]} ${rw[$host]}
        [ $? -eq 0 ] && rsstatus[$host]=1
        fi
    else
         if [ ${rsstatus[$host]} -eq 1 ]; then
         delrs ${rs[$host]}
         [ $? -eq 0 ] && rsstatus[$host]=0
         fi
     fi
done
sleep 10
done

相關文章