有時候,單臺服務器的性能可能無法應付大規模的服務請求,且其一旦出現故障,就會造成用戶在一段時間內無法訪問。通過集羣技術,可以在付出較低成本的情況下獲得在性能、可靠性、靈活性方面的相對較高的收益。
集羣是一組相互獨立的、通過網絡互聯的計算機組,並以單一系統的模式加以管理,或用於分攤負載,或用於增強可靠性,或用於高速計算。
一、集羣類型
LB:Load Balancing,負載均衡集羣,用於消除單點故障,當一個節點出現故障而無法正常提供服務時,自動、快速地切換到另外的節點上去;常見軟件或實現方式有lvs, haproxy, nginx
HA:High Availability,高可用集羣,將客戶端的請求遵從恰當的負載均衡原則分配給各節點的集羣;heartbeat, corosync+pacemaker, cman+rgmanager, cman + pacemaker, keepalived
HPC:High Performance Computing,高性能計算集羣;hadoop
二、lvs工作原理
lvs由 ipvsadm/ipvs 這兩段代碼組成,ipvsadm是工作於用戶空間的程序,用於編寫規則(定義集羣服務、調度標準,指明有哪些後端服務器等)並送給ipvs;ipvs是集成於內核中的真正實現調度功能的代碼,工作於netfilter的INPUT鏈上,它會根據指定的調度標準確定將匹配的請求報文調度到哪臺後端服務器,然後對請求報文做一定處理(或修改目標ip、或修改目標MAC等)並轉到POSTROUTING鏈上發往相應的後端服務器
三、lvs相關術語
director:調度器,即提供ipvsadm/ipvs,直接面向客戶端請求,實現調度功能的主機
real server:後端真實服務器,即真正處理客戶端請求的服務器
CIP:client ip
VIP:virtual ip,客戶端請求的目標ip,要配置在director上
DIP:director ip
RIP:real server ip
四、lvs的類型
1、lvs-nat
這種模型中,響應報文會經由director轉發回client,因此real server和director要位於同一子網中且real server的網關必須指向director,director會對請求報文和響應報文分別做DNAT(目標地址轉換)和SNAT(源地址轉換)。
nat類型的特性:
①RS可使用私有地址來隱藏服務器;RS的網關必須指向DIP;
②請求和響應都要經過Director,因此在高負載場景中,Director易成爲性能瓶頸;
③支持端口映射;
④RS可以使用任意OS;
2、lvs-dr
這種模型中,響應報文不會流經director,而是直接響應給client,因此在real server上必須也配置VIP,且要將其隱藏,即不允許通告和響應arp解析請求,否則請求報文可能不經director而直接到達real server;director不能給請求報文做IP地址轉換,只能修改其目標MAC地址以將其送往real server,因此,要求director和real server在同一物理網絡中。
dr類型的特性:
⑴保證前端路由將目標地址爲VIP的報文統統發往Directory,而不能是RS;
解決方案:
①靜態地址綁定:在前端路由器上操作(問題:未必有路由操作權限)
②aprtables
③修改RS上內核參數,將RS上的VIP配置在lo接口的別名上,並限制其不能響應對VIP地址解析請求;
⑵RS可以使用私有地址;也可以使用公網地址,此時可通過互聯網通過RIP對其直接訪問;
⑶RS跟Directory必須在同一物理網絡中;
⑷請求報文經由Director,但響應報文不經過Director,因此相比NAT模型,Director負荷大大減小。
⑸不支持端口映射;
⑹RS可以是大多數常見的OS;
⑺RS的網關絕不允許指向DIP;
⑻缺點:RS上綁定vip,風險大
lvs-dr的配置:
⑴RS上首先配置內核參數:
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
說明:
arp_ignore:如何響應接收到的ARP請求;默認爲0,表示只要本機有,就響應;1表示僅當請求解析的IP地址爲接收請求報文的端口地址時才進行響應
arp_annouce:如何通告本機地址;默認爲0,通告本機所有接口地址,2表示僅通告網絡直連的接口的地址
這一步的作用在於禁止通告VIP和響應對VIP的ARP解析請求
⑵然後在RS上配置VIP:
ifconfig lo:0 VIP netmask 255.255.255.255 broadcast VIP up
route add -host VIP dev lo:0 #請求報文本來是物理接口eth#接收的,需要添加一條使請求報文到達VIP所在接口(VIP通常配置在lo:0上)的路由,這樣響應報文的源地址才能是VIP。
3、lvs-tun
lvs-tun不同於lvs-dr的地方在於它允許director和real server在不同的網絡中,這是通過隧道機制實現的。在這種模型中,director會在請求報文原有IP首部之外再封裝一層首部,這樣,請求報文的IP首部就變成:內層IP首部(源地址:CIP,目標地址:VIP),外層IP首部(源地址:DIP,目標地址:RIP)。real server收到報文後,先將報文解封獲得原來目標地址爲VIP的報文,發現VIP地址被配置在本地的IP隧道設備上,所以就處理這個請求,然後根據路由表將響應報文直接返回給客戶。
tun類型的特性:
①RIP、VIP、DIP全部是公網地址;
②RS的網關不會也不可能指向DIP;
③請求報文經由Director,但響應報文必須不能經過Director;
④不支持端口映射;
⑤RS的OS必須支持隧道功能,一般需安裝隧道網卡;
⑥由於該模型允許Director和RS不在同一物理網絡中,因此常用於異地容災的場景中
lvs-tun的配置可參考http://www.linuxidc.com/Linux/2012-09/71340p3.htm
4、lvs-fullnat
同時修改請求報文的源地址和目標地址(CIP--VIP ==> DIP--RIP);實現director和RS之間跨子網通信,並且in/out流都會經過director;支持端口映射。
fullnat模式沒有被整合進linux內核,若要使用需要向內核打補丁,並且不被ipvsadm支持,不過可以使用keepalive生成規則。
四、lvs調度方法
grep -i 'VS' /boot/config-VERSION
⑴靜態方法:僅根據調度算法本身進行調度
rr: round robin,輪流,輪詢,輪叫
wrr: weighted round robin, 加權輪詢
sh: source hashing,源地址hash,表示將來源於同一個CIP的請求始終定向至同一個RS;SESSION保持;
dh: destination hashing, 目標地址hash,後端一般爲緩存服務器,可提高緩存命中率
⑵動態方法:根據算法及各RS當前的負載狀況進行調度
lc: least connection,最少連接
Overhead=Active*256+Inactive #overhead值越小越優先被選中,若overhead值一樣,則根據real server列表自上而下挑選
wlc: weighted lc,默認調度方法
Overhead=(Active*256+Inactive)/weight
sed: shortest expection delay;
wlc有個缺點,就是當overhead值相同時,權重小的若在列表中靠前則會被優先選擇,當請求量只有一個或很少時,這種調度不合適,而sed調度的主要目的在於讓權重大的優先接受請求
Overhead=(Active+1)*256/weight
nq: Never Queue,先按權重輪詢一圈,然後依照sed的overhead值選擇
lblc: Locality-Based Least Connection,動態版dh
lblcr:Replicated lblc
五、使用ipvsadm配置director
yum -y install ipvsadm
⑴定義一個集羣服務:
ipvsadm -A|E -t|u|f service-address [-s scheduler]
-A: 添加
-E: 修改
-f: firewall mark
-t: 說明提供的是TCP服務
-u: 說明提供的是UDP服務
-f: 說明是經過iptables標記過的服務類型
service-address:
-t|u: VIP:Port
-f: #
例如:ipvsadm -A -t 172.16.100.7:80 -s wlc
⑵向一個已經存在集羣服務添加一個RS:
ipvsadm -a|e -t|u|f service-address -r server-address [options]
-a: 添加RS記錄
-e: 修改RS記錄
options:
-w weight
-g, --gatewaying: 指定lvs工作模式爲DR模式,缺省模式
-i, --ipip: ipip encapsulation (tunneling)
-m, --masquerading: masquerading (NAT)
例如:ipvsadm -a -t 172.16.100.7:80 -r 10.0.0.8 -m -w 2
⑶查看已經定義的集羣服務及RS:
ipvsadm -L -n
-c: 查看各連接
--stats: 統計數據
--rate: 速率
--exact: 精確值
⑷從集羣服務中刪除RS:ipvsadm -d -t|u|f service-address -r server-address
⑸刪除集羣服務:ipvsadm -D -t|u|f service-address
⑹清空所有的集羣服務:ipvsadm -C
⑺保存集羣服務定義:
ipvsadm -S > /path/to/some_rule_file
ipvsadm-save > /path/to/some_rule_file
service ipvsadm save #該命令會將規則保存於/etc/sysconfig/ipvsadm中
⑻讓規則文件中的規則生效:
ipvsadm -R < /path/from/some_rule_file
ipvsadm-restore < /path/from/some_rule_file
可將該命令寫入/etc/rc.d/rc.local中,這樣開機啓動時就自動導入了
service ipvsadm start #以服務的方式啓動ipvsadm,它會從/etc/sysconfig/ipvsadm中讀取定義的集羣服務規則
⑼基於防火牆標記定義集羣服務
功能:將同屬於同一組應用的多個不同端口的服務定義成一個集羣服務,統一調度;例如http和https
結合netfilter來實現一種集羣服務定義機制;
①在mangle表的PREROUTING鏈定義規則,實現指定防火牆標記;
iptables -t mangle -A PREROUTING -d VIP -p {tcp|udp} --dport PORT -j MARK --set-mark #
②基於此前的標記定義集羣服務;
ipvsadm -A -f # [-s METHOD]
ipvsadm -a -f # -r RS [options]
例如:
iptables -t mangle -A PREROUTING -d 192.168.30.13 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 2
ipvsadm -A -f 2 -s wlc
ipvsadm -a -f 2 -r 172.16.100.2 -g -w 3
⑽lvs持久連接功能
無論使用什麼調度方法,持久連接功能都能保證在指定的一段時間內,來自同一個客戶端的請求始終被定向至同一個RS。當使用LVS持久連接時,調度器使用連接跟蹤(持久連接模板)來記錄每一個客戶端和給其分配的real server的映射關係
-p, --persistent [timeout]:使用持久連接,默認時長爲300秒
持久連接類型:
①PCC(persistent client connections):持久客戶端連接,又稱零端口連接
在基於tcp或udp定義集羣服務時,將來自於同一個客戶端對所有端口的請求,始終定向至此前選定的RS;以0作爲端口號
例:ipvsadm -A -t 172.16.100.7:0 -s rr -p
②PPC(persistent port connections):持久端口連接,將對同一端口的請求,始終定向至此前選定的RS;單服務調度;各集羣服務分開調度
例:ipvsadm -A -t 172.16.100.7:21 -s rr -p
③PFMC(persistent firewall mark connections):持久防火牆標記連接
iptables -t mangle -A PREROUTING -d 192.168.30.13 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 2
ipvsadm -A -f 2 -s wlc -p 600
-M, --netmask [NETMASK] 選項:
配合persistence_timeout使用,表示持久連接的粒度,默認是255.255.255.255,即單獨的客戶端IP。如果改成255.255.255.0,則表示只要是一個網段的client都會被分配到同一臺後端服務器上
六、配置示例
注意:lvs-nat模型中,director需要開啓報文轉發功能,而lvs-dr模型中則不需要
1、配置lvs-nat
以下示例中,我們以node3爲director,以node3上的兩個容器centos2和centos3(容器的創建詳見博客http://9124573.blog.51cto.com/9114573/1761114)作爲real server,node1作爲客戶端
VIP:192.168.30.13
DIP:172.16.100.1
RIP1:172.16.100.2
RIP2:172.16.100.3
#首先啓動容器,並保證其httpd服務正常運行 [root@node3 ~]# lxc-start -n centos2 -d [root@node3 ~]# lxc-start -n centos3 -d [root@node3 ~]# ssh [email protected] [email protected]'s password: Last login: Wed Apr 6 13:31:11 2016 [root@centos2 ~]# service httpd start Starting httpd: httpd: [ OK ] [root@centos2 ~]# ss -tnl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 0 *:22 *:* LISTEN 0 0 :::22 :::* LISTEN 0 0 :::80 :::* [root@centos2 ~]# logout Connection to 172.16.100.2 closed. [root@node3 ~]# ssh [email protected] [email protected]'s password: Last login: Wed Apr 6 13:31:38 2016 [root@centos3 ~]# service httpd start Starting httpd: httpd: [ OK ] [root@centos3 ~]# logout Connection to 172.16.100.3 closed. [root@node3 ~]# yum -y install ipvsadm ... Installed: ipvsadm.x86_64 0:1.26-4.el6 Complete! [root@node3 ~]# rpm -ql ipvsadm /etc/rc.d/init.d/ipvsadm #ipvsadm也有服務腳本 /etc/sysconfig/ipvsadm-config /sbin/ipvsadm /sbin/ipvsadm-restore /sbin/ipvsadm-save /usr/share/doc/ipvsadm-1.26 /usr/share/doc/ipvsadm-1.26/README /usr/share/man/man8/ipvsadm-restore.8.gz /usr/share/man/man8/ipvsadm-save.8.gz /usr/share/man/man8/ipvsadm.8.gz [root@node3 ~]# ipvsadm -A -t 192.168.30.13:80 -s rr #定義一個集羣服務,採用輪循調度 [root@node3 ~]# ipvsadm -a -t 192.168.30.13:80 -r 172.16.100.2 -m #添加real server [root@node3 ~]# ipvsadm -a -t 192.168.30.13:80 -r 172.16.100.3 -m [root@node3 ~]# ipvsadm -L -n #查看定義的集羣服務及RS IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.30.13:80 rr -> 172.16.100.2:80 Masq 1 0 0 -> 172.16.100.3:80 Masq 1 0 0 [root@node3 ~]# cat /proc/sys/net/ipv4/ip_forward #確保開啓報文轉發功能 1 [root@node3 ~]# iptables -L -n #確保已開放集羣服務端口 Chain INPUT (policy DROP) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED ACCEPT tcp -- 0.0.0.0/0 192.168.30.13 tcp dpt:22 state NEW ACCEPT tcp -- 0.0.0.0/0 172.16.100.1 tcp dpt:22 state NEW ACCEPT tcp -- 0.0.0.0/0 192.168.30.13 tcp dpt:80 state NEW Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
#這裏爲演示負載均衡的效果,刻意讓後端兩個RS上的網頁內容不同,實際環境是當然是相同的 [root@node1 ~]# curl 192.168.30.13 hello [root@node1 ~]# curl 192.168.30.13 how are you [root@node1 ~]# curl 192.168.30.13 hello [root@node1 ~]# curl 192.168.30.13 how are you
[root@node3 ~]# ipvsadm -L -n -c IPVS connection entries pro expire state source virtual destination TCP 01:17 TIME_WAIT 192.168.30.10:38368 192.168.30.13:80 172.16.100.2:80 TCP 01:17 TIME_WAIT 192.168.30.10:38369 192.168.30.13:80 172.16.100.3:80 TCP 01:15 TIME_WAIT 192.168.30.10:38367 192.168.30.13:80 172.16.100.3:80 TCP 01:14 TIME_WAIT 192.168.30.10:38366 192.168.30.13:80 172.16.100.2:80 [root@node3 ~]# ipvsadm-save > /tmp/lvs #將定義的規則保存至某個文件中 [root@node3 ~]# ipvsadm -D -t 192.168.30.13:80 #刪除指定的集羣服務 [root@node3 ~]# ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn [root@node3 ~]# ipvsadm-restore < /tmp/lvs [root@node3 ~]# ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.30.13:80 rr -> 172.16.100.2:80 Masq 1 0 0 -> 172.16.100.3:80 Masq 1 0 0
2、配置lvs-dr
以下示例中,node1爲客戶端,node3爲director,node4和node5爲real server,可將VIP配置於虛擬接口上,DIP與RIP要位於同一物理網絡;
DIP:192.168.30.13,eth0
VIP:192.168.30.100,eth0:0
RIP1:192.168.30.14
RIP2:192.168.30.15
[root@node4 ~]# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore [root@node4 ~]# echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce [root@node4 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore [root@node4 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce [root@node4 ~]# ifconfig lo:0 192.168.30.100 netmask 255.255.255.255 broadcast 192.168.30.100 up [root@node4 ~]# route add -host 192.168.30.100 dev lo:0 [root@node4 ~]# service httpd start Starting httpd: httpd: apr_sockaddr_info_get() failed for node5 httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName [ OK ] [root@node4 ~]# iptables -F
再在node5的做相同配置,略
#在director上配置VIP,定義集羣服務,添加後端RS [root@node3 ~]# ifconfig eth0:0 192.168.30.100/24 up #配置VIP [root@node3 ~]# ifconfig eth0 Link encap:Ethernet HWaddr 00:0C:29:CB:26:9B inet addr:192.168.30.13 Bcast:192.168.30.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fecb:269b/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:28711 errors:0 dropped:0 overruns:0 frame:0 TX packets:9590 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:4456933 (4.2 MiB) TX bytes:1970077 (1.8 MiB) eth0:0 Link encap:Ethernet HWaddr 00:0C:29:CB:26:9B inet addr:192.168.30.100 Bcast:192.168.30.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 ... [root@node3 ~]# cat /proc/sys/net/ipv4/ip_forward 1 [root@node3 ~]# ipvsadm -C [root@node3 ~]# iptables -t mangle -A PREROUTING -d 192.168.30.100 -p tcp -m multiport --dports 80,243 -j MARK --set-mark 1 [root@node3 ~]# ipvsadm -A -f 1 -s wlc #基於防火牆定義集羣服務 [root@node3 ~]# ipvsadm -a -f 1 -r 192.168.30.14 -g -w 2 [root@node3 ~]# ipvsadm -a -f 1 -r 192.168.30.15 -g -w 1 [root@node3 ~]# iptables -P INPUT ACCEPT
負載均衡效果測試:
[root@node1 ~]# curl 192.168.30.100 hello [root@node1 ~]# curl 192.168.30.100 hello [root@node1 ~]# curl 192.168.30.100 how are you
六、Session持久機制
①session綁定:始終將來自同一個源IP的請求定向至同一個RS;沒有容錯能力;有損均衡效果;
②session複製:在RS之間同步session,每個RS擁有集羣中的所有的session;對大規模集羣不適用;
③session服務器:利用單獨部署的服務器來統一管理集羣中的session;
七、real server的健康狀態檢測
lvs自身不具備後端RS健康狀態檢測功能,需要藉助keepalived,keepalived不僅能爲lvs提供高可用,還可以給lvs生成規則。
1、如何檢測RS的健康狀態:
應用層:利用集羣服務依賴的協議進行檢測
傳輸層:利用端口掃描或探測類工具對指定協議的端口進行探測
網絡層:如ping
2、處理措施:
①自動上下線各RS;
online --> fail,探測三次及以上;
offline --> ok,一次即可;
②所有RS均故障時,應該提供一個back server;
ipvsadm -a -t 192.168.30.13:80 -r 127.0.0.1 -m -w 0