在日常的使用中,一台伺服器足夠勝任很多的工作,但是當很多人同時通路的時候就會顯得稍有些無力,這個時候。可以有兩種解決的方法,第一種是不斷的改善這台伺服器的性能,但是總是會有一個上限存在,而且提升的效果并不明顯。另外一種方法就是使用多台伺服器,來均攤需要處理的任務,這就是叢集,通過一定的組合方式,将很多功能一樣的伺服器祖喝道一起,但是使用時感受不到他們的差異。組合的方式目前有四種,分别是lvs-nat、lvs-dr、lvs-tunnel和熱心網友提供的lvs-fullnat,在Linux核心中僅支援前三種,最後一種如果想要使用需要自己重新編譯核心。在開始介紹之前我們需要了解幾個常用術語:
<code>vs:virtual server,構成叢集的排程器(中心節點)</code>
<code>rs:real server,使用者隻能找到vs,但是真正提供服務的是rs</code>
<code>CIP:Client IP,用戶端的IP位址,即請求發送方的IP位址</code>
<code>VIP:Virtual Server IP,,虛拟伺服器的虛拟IP位址,用戶端通路的目的位址</code>
<code>DIP:Director IP,排程器IP位址,向後方Real Server轉發用戶端請求時使用的IP位址</code>
<code>RIP:Real Server IP,後方真實伺服器的IP位址</code>
簡單來說就是當使用者通路伺服器的時候首先通路到的是排程器,然後由排程器檢視有哪一台叢集中的伺服器是相對空閑,那麼就将請求送到這一台伺服器上進行處理。使用者的位址叫做CIP,使用者通路的位址叫做VIP,排程器上用于通路叢集的位址叫做DIP,叢集中各個伺服器的位址叫做RIP。下面開始依次介紹各種叢集方式。
一、lvs-nat
這種方式建構叢集的架構如圖所示:
<a href="https://s4.51cto.com/oss/201710/21/06f5c94b6eb77ac14d53f352eeb14ed3.png-wh_500x0-wm_3-wmp_4-s_3303131388.png" target="_blank"></a>
首先由用戶端的CIP發起請求,由排程器分發到後端伺服器上進行處理,在處理之後傳回處理結果。具體是哪個主機由排程器根據算法進行選擇,根據lvs在排程時是否考慮各RS目前的負載狀态,可以将排程算法分為兩類,分别是靜态算法和動态算法,靜态算法是事先就将配置設定的過程安排好,而動态算法是在實時的處理過程中根據伺服器的忙碌程度進行配置設定。(每種架構方式使用的基本都是如下算法,後邊不再重複說明)
靜态算法,根據算法本身的特點進行排程,注重起點公平,包括以下幾種:
<code>RR:RoundRobin,輪詢(一人一個任務,但是有的伺服器性能好,有的差,是以這種配置設定方式不太好)</code>
<code>WRR:Weighted RR,權重輪詢(有額外的權重幹擾配置設定結果)(能力越大責任越大)(權重高,代表工作能力強,就會被多配置設定任務)</code>
<code>SH:Source Hashing,源位址哈希,将來自于同一個IP位址的請求始終發往後端第一次被挑中的RS,進而可以實作會話綁定,例如購物等操作,最好要保持在同一台伺服器上</code>
<code>DH:Destination Hashing,目的位址哈希,将發往同一個目标位址的請求,始終發送至後端第一次被挑中的RS,一般用于正向代理伺服器叢集</code>
動态算法,主要根據每個RS目前的負載狀态進度排程,注重結果公平,包括以下幾種:
(後端RS的負載情況,用Overhead表示,使用這個變量可以來實時的觀測任務最好配置設定給哪台伺服器,通過active connection(活動的連接配接數)和inavtive connection(不活動的連接配接數)來進行計算)
<code>LC:least connections,最少連接配接數</code>
計算公式:Overhead=activeconnections*256+inactiveconnections
注意:第一次排程時,按照在ipvsadm中配置的順序自上而下進行配置設定
<code>WLC:Weighted LC,權重最小連接配接(如果在部署時未指定,預設為這個)</code>
計算公式:Overhead=(activeconnections*256+inactiveconnections)/weight
注意:第一次排程時,按照在ipvsadm中配置的順序自上而下進行配置設定,權重在第一次排程時不發揮作用
<code>SED:Shortest Expection Delay,最短期望延遲</code>
計算公式:Overhead=(activeconnections+1)*256/weight
注意:SED可以解決起點不公平的問題,但是在權重差距比較大時,可能會導緻不公平
例如:weight一個1,一個10,那麼為10的會連續獲得多個任務
<code>NQ:Never Queue,改進版的SED算法,首次排程時,根據後端RS的權重依次為每台RS配置設定一個連接配接;然後再按照SED算法排程;必然會保證後端每台RS至少有一個 activeconnection;</code>
<code>LBLC:Locality-Based Least Connections:基于本地的最少連接配接,動态的DH算法</code>
<code>LBLCR:LBLC with Replication,帶有複制功能的LBLC</code>
叢集部署時最難的是了解架構方式,在了解了之後,部署是十分簡單的,在lvs-nat的方式下,我們隻需要将各個網段設定好,使相同網段之間能夠ping通即可,然後在排程器上使用“ipvsadm”指令(在核心中有ipvs,是實作叢集的功能,主要工作在INPUT鍊上,ipvs(INPUT):核心中的TCP/IP協定棧上的元件,而ipvsadm用來編寫規則送給ipvs(類似于防火牆的iptables軟體的功能,是使用者空間中的用于編寫ipvs規則的元件)檢視核心中是否支援ipvs功能:~]# grep -i -C 10 "ipvs" /boot/config*):
<code>ipvsadm:</code>
<code> </code><code>格式:</code>
<code> </code><code>ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]]</code>
<code> </code><code>ipvsadm -D -t|u|f service-address</code>
<code> </code><code>ipvsadm -C</code>
<code> </code><code>ipvsadm -R</code>
<code> </code><code>ipvsadm -S [-n]</code>
<code> </code><code>ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight]</code>
<code> </code><code>ipvsadm -d -t|u|f service-address -r server-address</code>
<code> </code><code>ipvsadm -L|l [options]</code>
<code> </code><code>ipvsadm -Z [-t|u|f service-address]</code>
<code> </code><code>ipvsadm --</code><code>set</code> <code>tcp tcpfin udp</code>
<code> </code><code>ipvsadm --start-daemon state [--mcast-interface interface]</code>
<code> </code><code>[--syncid syncid]</code>
<code> </code><code>ipvsadm --stop-daemon state</code>
<code> </code><code>ipvsadm -h</code>
<code>管理叢集服務:增,删,改(對叢集整體的處理)</code>
<code> </code><code>增加lvs叢集服務:ipvsadm -A -t|u|f service-address [-s scheduler] [-p [timeout]]</code>
<code> </code><code>-t:基于TCP協定的叢集服務</code>
<code> </code><code>service-address:與VIP綁定的套接字</code>
<code> </code><code>-u:基于UDP服務的叢集服務</code>
<code> </code><code>-f:基于防火牆協定(FWM—Firewall mark,防火牆标記)的叢集服務</code>
<code> </code><code>通過iptables的mangle表對資料設定的标記</code>
<code> </code><code>-s:指定叢集服務的排程算法(如果省略,預設是wlc)</code>
<code> </code><code>-p:是否開啟持久連接配接</code>
<code> </code><code>修改lvs叢集服務:ipvsadm -E -t|u|f service-address [-s scheduler] [-p [timeout]]</code>
<code> </code><code>參數和增加類似</code>
<code> </code><code>删除lvs叢集服務:ipvsadm -D -t|u|f service-address</code>
<code> </code><code>清除lvs叢集服務:ipvsadm -C(類似于iptables的“-F”)(最好不要輕易的使用)</code>
<code>管理叢集中的RS:增,删,改(這是對叢集中的哪些伺服器進行處理的指令)</code>
<code> </code><code>在叢集中添加RS:ipvsadm -a -t|u|f service-address -r server-address [-g|i|m] [-w weight]</code>
<code> </code><code>-r:指定要添加到叢集中的後端RS的IP位址和端口</code>
<code> </code><code>-g:選擇叢集類型為DR(預設值)</code>
<code> </code><code>-i:選擇叢集類型為TUN</code>
<code> </code><code>-m:選擇叢集的類型為NAT</code>
<code> </code><code>-w:為RS(Real Server)設定的權重(不要設定的懸殊過大,否則配置設定會不當)</code>
<code> </code><code>修改叢集中的RS:ipvsadm -e -t|u|f service-address -r server-address [-g|i|m] [-w weight]</code>
<code> </code><code>從叢集中删除的RS:ipvsadm -d -t|u|f service-address -r server-address</code>
<code>檢視lvs叢集狀态及屬性資訊:</code>
<code> </code><code>ipvsadm -L|l [options]:</code>
<code> </code><code>options包括:</code>
<code> </code><code>-c, --connection:檢視目前的ipvs中的各種連接配接的狀态</code>
<code> </code><code>--stats:顯示lvs叢集的統計資料資訊</code>
<code> </code><code>--rate:顯示lvs叢集與傳輸速率有關的内容</code>
<code> </code><code>--timeout:顯示TCP、TCP的FIN标志位及UDP會話的逾時時長</code>
<code>儲存和重載ipvs的規則(兩種方法都可以):</code>
<code> </code><code>儲存:</code>
<code>ipvsadm -S [-n](隻是顯示出來并不是儲存,需要重定向,自己儲存) > </code><code>/PATH/TO/IPVS_RULE_FILE</code>
<code>ipvsadm-save > </code><code>/PATH/TO/IPVS_RULE_FILE</code>
<code> </code><code>重載:</code>
<code>ipvsadm -R < </code><code>/PATH/TO/IPVS_RULE_FILE</code>
<code>ipvsadm-restore < </code><code>/PATH/TO/IPVS_RULE_FILE</code>
<code> </code><code>儲存規則并于開機時自動載入:</code>
<code> </code><code>CentOS 6-:</code>
<code> </code><code># chkconfig ipvsadm on</code>
<code> </code><code>将規則儲存至:</code><code>/etc/sysconfig/ipvsadm</code>
<code> </code><code>CentOS 7:</code>
<code> </code><code># systemctl enable ipvsadm.service</code>
<code>清空計數器(當想要重置的時候可以清空計數器):</code>
<code> </code><code>ipvsadm -Z [-t|u|f service-address]</code>
<code> </code><code>後頭如果沒參數則清空所有的計數器</code>
在了解了指令之後,我們就可以開始部署lvs-nat叢集了,首先按照圖中所示,配置好相應的IP,并在排程器上使用以下指令:
<code>~]</code><code># yum install ipvsadm -y #安裝管理軟體ipvsadm</code>
<code>~]</code><code># ipvsadm -A -t 172.15.0.2:80 -s rr #建立一個叢集服務</code>
<code>~]</code><code># ipvsadm -a -t 172.15.0.2:80 -r 172.16.128.18:80 -m -w 1</code>
<code> </code><code>#在剛才建立的叢集中添加一台伺服器,“-m”指定為NAT方式</code>
<code>~]</code><code># ipvsadm -a -t 172.15.0.2:80 -r 172.16.128.19:80 -m -w 2</code>
<code> </code><code>#在剛才建立的叢集中添加一台伺服器,“-w”指定權重(在NAT中權重沒用,但是先寫上,後邊會用)</code>
然後在RS上安裝httpd服務(所有伺服器上都要安裝)(預設是已經安裝完的):
<code>~]</code><code># yum install httpd -y</code>
<code>~]</code><code># route add default gw 172.16.128.17 #并指定網關,否則即使服務轉到伺服器上也回不去</code>
<code>~]</code><code># echo "This is 172.16.128.18" > /var/www/html/index.html 在172.16.128.18上執行</code>
<code>~]</code><code># echo "This is 172.16.128.19" > /var/www/html/index.html 在172.16.128.19上執行</code>
最後将服務都開啟:
<code>~]</code><code># service httpd start #CentOS 6 上</code>
回到排程器上進行驗證:
<a href="https://s3.51cto.com/oss/201710/21/76a6ada70f6b8731b0c31eb3f5eac9e2.png-wh_500x0-wm_3-wmp_4-s_2781817197.png" target="_blank"></a>
驗證通過之後,在排程器上開啟轉發功能:
<code>~]</code><code># echo 1 > /proc/sys/net/ipv4/ip_forward</code>
這樣,lvs-nat叢集就配置完成了,我們可以在作為用戶端的主機上通過指令來進行檢視:
<code> </code><code>~]</code><code># for i in {1..10} ; do curl http://172.15.0.2 ; done #使用循環的方式連續通路10次</code>
<a href="https://s3.51cto.com/oss/201710/21/ecd2a118f9a70b5419d0dd4d2a1fa567.png-wh_500x0-wm_3-wmp_4-s_3451384316.png" target="_blank"></a>
從圖中我們可以看出,排程器安裝輪詢的方式,一次通路172.16.128.19,一次通路172.16.128.18,此時我設定的是兩個不同的網頁,如果兩個相同,那麼在使用者使用的時候就看不出差距,就可以實作任務均攤,來減輕伺服器的負擔。
然後,我們可以更換一個算法,改為wlc算法:
<code>~]</code><code># ipvsadm -E -t 172.15.0.2:80 -s wlc</code>
再使用上面的方式進行檢視發現,兩台伺服器的工作配置設定方式變成了2比1,這是因為在上面添加伺服器的時候172.16.128.18的權重為1,而172.16.128.19的權重為2:
<a href="https://s1.51cto.com/oss/201710/21/de01b7d83dbe69ea864db3d7b61f5956.png-wh_500x0-wm_3-wmp_4-s_2373958296.png" target="_blank"></a>
二、lvs-dr
lvs-dr的配置相對于lvs-nat來說減輕了排程器的工作壓力,如果是lvs-nat方式,那麼不管是進入叢集的資料包還是從叢集中出來的資料包都要經過排程器進行分發,那麼排程器就是這個叢集的效率瓶頸,如果排程器不夠好,叢集的工作效率就會大打折扣。是以lvs-dr模型減輕了排程器的工作壓力,隻有進入叢集的資料包才會經過排程器,而從叢集中出來的資料包直接由伺服器發送回用戶端。不過這樣又會遇到一個問題,就是IP位址的問題,如果直接從伺服器進行發送,那麼源位址就不是用戶端請求的位址,用戶端就會禁止這種資料包,是以lvs-dr模型通過僞裝使用者通路的IP位址來實作叢集。架構的方式如圖所示(用戶端的IP現實中不會是這個,在這裡隻是為了進行簡單的驗證)(如果做過上面lvs-nat的實驗,主機IP等配置需要重置):
<a href="https://s4.51cto.com/oss/201710/21/75c58b1b2a0697c07707235141f207f7.png-wh_500x0-wm_3-wmp_4-s_2342196951.png" target="_blank"></a>
此時的用戶端可以和上圖中所有的IP進行通信:
<a href="https://s1.51cto.com/oss/201710/21/3dfb9fb91e3a988be29838308f086cc0.png-wh_500x0-wm_3-wmp_4-s_4210366236.png" target="_blank"></a>
在DR模型中,各個主機均需要配置VIP;解決位址沖突的方法通常有三種:
1.在前端網關上靜态綁定VIP和MAC;
2.在各個RS中使用arptables進行arp封包的過濾;
3.在各個RS中修改對應的核心參數,來限制ARP的通告和應答的級别;
在核心中通過更改下面兩個值可以達到相應的效果:
<code>arp_ignore:</code>
<code>0:預設值,對于從任何網絡接口接收到對本機任意IP位址的ARP查詢請求均予以回應;</code>
<code>1:隻應答目标IP位址是入站接口上配置的IP位址所在網段的IP位址的ARP請求;</code>
<code>2:隻應答目标IP位址是入站接口上配置的IP位址所在網段的IP位址的ARP請求,且來訪IP位址也必須與該接口的IP位址在同一子網中;</code>
<code>3:不響應該網絡接口的ARP請求,而隻對設定為全局的IP位址做應答;</code>
<code>4-7:保留;</code>
<code>8:不應答所有的ARP請求;</code>
<code>arp_announce:</code>
<code>0:預設值,将本機所有接口的資訊向所有接口所連接配接的網絡中通告;</code>
<code>1:盡量避免向與本接口不同網絡中的其他接口通告;</code>
<code>2:絕對避免向非本網絡的主機通告;</code>
在兩台伺服器上都運作下面的指令:
<code>echo</code> <code>1 > </code><code>/proc/sys/net/ipv4/conf/all/arp_ignore</code> <code>#設定所有接口(在所有中包含lo接口)</code>
<code>echo</code> <code>1 > </code><code>/proc/sys/net/ipv4/conf/lo/arp_ignore</code> <code>#設定lo接口(為了安全起見,在lo接口上再設定一次)</code>
<code>echo</code> <code>2 > </code><code>/proc/sys/net/ipv4/conf/all/arp_announce</code>
<code>echo</code> <code>2 > </code><code>/proc/sys/net/ipv4/conf/lo/arp_announce</code>
<code>ifconfig</code> <code>lo:0 172.16.128.128 netmask 255.255.255.255 broadcast 172.16.128.128 up</code>
<code>route add -host 172.16.128.128 dev lo:0</code>
這樣,在伺服器上的配置就完成了,然後還是像lvs-nat一樣将httpd服務開啟,并設定首頁,之後回到排程器上執行指令:
<code>~]</code><code># ifconfig eth0:0 172.16.128.128 netmask 255.255.255.255 broadcast 172.16.128.128 up</code>
<code>~]</code><code># ipvsadm -C #情空規則</code>
<code>~]</code><code># ipvsadm -A -t 172.16.128.128:80 -s rr #添加叢集</code>
<code>~]</code><code># ipvsadm -a -t 172.16.128.128:80 -r 172.16.128.18 -g -w 1 #向叢集中添加伺服器</code>
<code>~]</code><code># ipvsadm -a -t 172.16.128.128:80 -r 172.16.128.19 -g -w 3 #添加幾個,就寫幾個</code>
<code> </code><code>“-g”選項是選擇叢集類型為DR,不寫也可以,因為預設就是這個</code>
到此,lvs-dr模型就配置好了,可以到用戶端(172.16.128.17)上使用指令進行檢視:
<code>~]</code><code># for i in {1..10} ; do curl http://172.16.128.128 ; done</code>
<a href="https://s2.51cto.com/oss/201710/21/7a65e02163d66680f73ade024690d85d.png-wh_500x0-wm_3-wmp_4-s_3269935146.png" target="_blank"></a>
更改算法的方式和lvs-nat一樣。
三、基于标記的轉發
上面是兩種架構的方式,接下來要說一說基于标記的轉發方式,可以使用任何一個架構方式。通過防火牆的mangle表的PREROUTING鍊來對通路排程器的資料包進行标記,例如通路80端口就給其标記為6,然後在配置叢集的時候就可以使用這個标記來進行配置設定。這樣的方式相對于其他的方法更為靈活。配置的方法是首先使用iptables進行标記:
<code>iptables -t mangle -F </code><code>#清空規則,目的是防止其他規則的影響,可以不用執行</code>
<code>iptables -t mangle -A PREROUTING -d 172.16.128.128 -p tcp --dport 80 -j MARK --</code><code>set</code><code>-mark 6</code>
然後使用ipvsadm指令基于标記進行伺服器排程:
<code>ipvsadm -C</code>
<code>ipvsadm -A -f 6 -s rr </code><code>#“-f”後跟的是标記的記号,根據上頭設定的記号進行修改</code>
<code>ipvsadm -a -f 6 -r 172.16.128.18:80 -g -w 1</code>
<code>ipvsadm -a -f 6 -r 172.16.128.19:80 -g -w 3</code>
上面的指令都是在排程器上進行配置,伺服器不用管,下面使用用戶端檢視
四、長連接配接
在上面的基礎上,在排程器上使用下面這條指令:
<code>~]</code><code># ipvsadm -E -f 6 -s wrr -p</code>
這條指令的作用是建構長連接配接,即如果一個用戶端連接配接了叢集中的伺服器之後,那麼在“-p”選項後指定的時間(預設360秒)之内通路還是這個伺服器。
如圖所示,在排程器上使用這個指令:
<a href="https://s4.51cto.com/oss/201710/21/f2e6e35b243c7ef9a9f34eefb8d98c6d.png-wh_500x0-wm_3-wmp_4-s_3958481770.png" target="_blank"></a>
最後就可以在用戶端上重複連接配接10次,可以發現10次都是連接配接的同一個伺服器:
<a href="https://s4.51cto.com/oss/201710/21/b8c92dd8c41fe18109265e4f04a63424.png-wh_500x0-wm_3-wmp_4-s_4231710900.png" target="_blank"></a>
如果換一個主機,就會是另外一個伺服器了(根據算法進行選擇)
本文轉自正經的青年51CTO部落格,原文連結: http://blog.51cto.com/11142243/1974868,如需轉載請自行聯系原作者