LVS服務腳本及後端服務健康狀態檢查

libnet下載地址: http://search.cpan.org/dist/libnet/


ipvsadm下載地址: http://www.linuxvirtualserver.org/software/ipvs.html#kernel-2.6


從Linux內核版本2.6起,ip_vs code已經被整合進了內核中,因此,只要在編譯內核的時候選擇了ipvs的功能,您的Linux即能支持LVS。Linux 2.4.23以後的內核版本也整合了ip_vs code,但如果是更舊的內核版本,您得自己手動將ip_vs code整合進內核原碼中,並重新編譯內核方可使用lvs。



一、關於ipvsadm:

ipvsadm是運行於用戶空間、用來與ipvs交互的命令行工具,它的作用表現在:

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需要解析的名稱僅限於RealServer,考慮到DNS提供名稱解析服務效率不高的情況,建議將所有RealServer的名稱解析通過/etc/hosts文件來實現;


三、調度算法

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


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

2、最少連接(least connected, lc), 加權最少連接(weighted least connection, wlc)——新的連接請求將被分配至當前連接數最少的RealServer;最小連接調度是一種動態調度算法,它通過服務器當前所活躍的連接數來估計服務器的負載情況。調度器需要記錄各個服務器已建立連接的數目,當一個請求被調度到某臺服務器,其連接數加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地址外,它的算法流程與目標地址散列調度算法的基本相似。在實際應用中,源地址散列調度和目標地址散列調度可以結合使用在防火牆集羣中,它們可以保證整個系統的唯一出入口。


四、關於LVS追蹤標記fwmark:

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



查看LVS上當前的所有連接

# ipvsadm -Lcn   

或者

#cat /proc/net/ip_vs_conn


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

# ipvsadm -l --stats


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

# ipvsadm -l --rate



VS/NAT


LVS-NAT基於cisco的LocalDirector。VS/NAT不需要在RealServer上做任何設置,其只要能提供一個tcp/ip的協議棧即可,甚至其無論基於什麼OS。基於VS/NAT,所有的入站數據包均由Director進行目標地址轉換後轉發至內部的RealServer,RealServer響應的數據包再由Director轉換源地址後發回客戶端。 

VS/NAT模式不能與netfilter兼容,因此,不能將VS/NAT模式的Director運行在netfilter的保護範圍之中。現在已經有補丁可以解決此問題,但尚未被整合進ip_vs code。


        ____________

       |            |

       |  client    |

       |____________|                     

     CIP=192.168.0.253 (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 VIP:PORT -s rr

如:

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


設置轉發:

# ipvsadm -a -t VIP:PORT -r RIP_N:PORT -m -w N

如:

# 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


打開路由轉發功能

# echo "1" > /proc/sys/net/ipv4/ip_forward


服務控制腳本:


#!/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




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以追蹤此連接,而後將其轉發至後端的RealServer之一。

如果Client在請求建立至VIP的連接時由某RealServer響應了其請求,則Client會在其MAC table中建立起一個VIP至RealServer的對就關係,並以至進行後面的通信。此時,在Client看來只有一個RealServer而無法意識到其它服務器的存在。

爲了解決此問題,可以通過在路由器上設置其轉發規則來實現。當然,如果沒有權限訪問路由器並做出相應的設置,則只能通過傳統的本地方式來解決此問題了。這些方法包括:

1、禁止RealServer響應對VIP的ARP請求;

2、在RealServer上隱藏VIP,以使得它們無法獲知網絡上的ARP請求;

3、基於“透明代理(Transparent Proxy)”或者“fwmark (firewall mark)”;

4、禁止ARP請求發往RealServers;


傳統認爲,解決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


爲了保證其時效性,Hash table中“連接追蹤”信息被定義了“生存時間”。LVS爲記錄“連接超時”定義了三個計時器:

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,這通常不符合使用要求。





Director腳本:

#!/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



RealServer腳本:


#!/bin/bash

#

# Script to start LVS DR real server.

# description: LVS DR real server

#

.  /etc/rc.d/init.d/functions


VIP=192.168.0.219

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


後端服務健康狀態檢查:

方法1:使用命令elinks 去下載,如果執行成功返回值是0,從而判斷web服務是否在線

[root@localhost ~]# elinks -dump http://192.168.1.11

                                rs1.mylinux.com

[root@localhost ~]# echo $?

0

[root@localhost ~]# 

如服果不在線就從RS列表中移除,如果在線就自動把它添加回來。


方法2:

 在web上提供一個測試頁面


[root@localhost ~]# cd /var/www/html/

[root@localhost html]# vim .health_check.html

[root@localhost html]# 

[root@localhost html]# elinks -dump http://192.168.1.11/.health_check.html

   OK

只要能grep到OK信息頁面就正常


curl命令選項:

 --cacert <file> CA證書(SSL)

 --capath <directory> CA目錄 (made using c_rehash)to verify peer  against (SSL)

 --connect-timeout <second> 設置最大請求超時時間


[root@localhost html]# curl --connect-timeout 1 http://192.168.1.11/index.html

<h1>rs1.mylinux.com</h1>

[root@localhost html]# curl --connect-timeout 1 http://192.168.1.12/index.html

curl: (7) couldn't connect to host



[root@localhost html]# curl -I http://192.168.1.11/index.html 以head方式打開網頁

HTTP/1.1 200 OK    只要是2或者3開頭的響應報文,則表示頁面是能訪問到的

Date: Fri, 09 Dec 2016 07:39:13 GMT

Server: Apache/2.2.15 (CentOS)

Last-Modified: Fri, 09 Dec 2016 06:54:41 GMT

ETag: "62038-19-543343a73956e"

Accept-Ranges: bytes

Content-Length: 25

Connection: close

Content-Type: text/html; charset=UTF-8


-s不輸出任何東西 ,只輸入網頁內容


檢查後臺狀況後自動操作RS羣

vim health_check.sh

#!/bin/bash

VIP=192.168.1.10

CPORT=80

FAIL_BACK=127.0.0.1

RS=("192.168.1.11" "192.168.10.12") 數組

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://$I &> /dev/null;then

        return 0

       fi

       let I++

    done

    return 1

}

initstatus() {

local I

local COUNT =0;

for I in ${RS[*]};do

   if checkrs $I ; then

     RSSTATUS[$COUNT]=1

   else

     RSSTATUS[$CONUT]=0

   fi

let COUNT++

done

}

initstatus

whlie :; 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 os gone." >> $LOG

         fi

     fi

     let COUNT++

   done

   sleep5

done

 


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