lvs

1、負載均衡LVS基本介紹

LVS是 Linux Virtual Server 的簡稱,也就是Linux虛擬服務器。這是一個由章文嵩博士發起的一個開源項目,它的官方網站是 http://www.linuxvirtualserver.org 如今 LVS 已是 Linux 內核標準的一部分。使用 LVS 能夠達到的技術目標是:經過 LVS 達到的負載均衡技術和 Linux 操做系統實現一個高性能高可用的 Linux 服務器集羣,它具備良好的可靠性、可擴展性和可操做性。從而以低廉的成本實現最優的性能。LVS 是一個實現負載均衡集羣的開源軟件項目,LVS架構從邏輯上可分爲調度層、Server集羣層和共享存儲。前端

LVS:
一、抗負載能力強。抗負載能力強、性能高,能達到F5硬件的60%;對內存和cpu資源消耗比較低
二、工做在網絡4層,經過vrrp協議轉發(僅做分發之用),具體的流量由linux內核處理,所以沒有流量的產生。
二、穩定性、可靠性好,自身有完美的熱備方案;(如:LVS+Keepalived)
三、應用範圍比較廣,能夠對全部應用作負載均衡;
四、不支持正則處理,不能作動靜分離。
五、支持負載均衡算法:rr(輪循)、wrr(帶權輪循)、lc(最小鏈接)、wlc(權重最小鏈接)
六、配置 複雜,對網絡依賴比較大,穩定性很高。python

Ngnix:
一、工做在網絡的7層之上,能夠針對http應用作一些分流的策略,好比針對域名、目錄結構;
二、Nginx對網絡的依賴比較小,理論上能ping通就就能進行負載功能;
三、Nginx安裝和配置比較簡單,測試起來比較方便;
四、也能夠承擔高的負載壓力且穩定,通常能支撐超過1萬次的併發;
五、對後端服務器的健康檢查,只支持經過端口來檢測,不支持經過url來檢測。
六、Nginx對請求的異步處理能夠幫助節點服務器減輕負載;
七、Nginx僅能支持http、https和Email協議,這樣就在適用範圍較小。
八、不支持Session的直接保持,但能經過ip_hash來解決。、對Big request header的支持不是很好,
九、支持負載均衡算法:Round-robin(輪循)、Weight-round-robin(帶權輪循)、Ip-hash(Ip哈希)
十、Nginx還能作Web服務器即Cache功能。linux

HAProxy的特色是:
一、支持兩種代理模式:TCP(四層)和HTTP(七層),支持虛擬主機;
二、可以補充Nginx的一些缺點好比Session的保持,Cookie的引導等工做
三、支持url檢測後端的服務器出問題的檢測會有很好的幫助。
四、更多的負載均衡策略好比:動態加權輪循(Dynamic Round Robin),加權源地址哈希(Weighted Source Hash),加權URL哈希和加權參數哈希(Weighted Parameter Hash)已經實現
五、單純從效率上來說HAProxy更會比Nginx有更出色的負載均衡速度。
六、HAProxy能夠對Mysql進行負載均衡,對後端的DB節點進行檢測和負載均衡。
九、支持負載均衡算法:Round-robin(輪循)、Weight-round-robin(帶權輪循)、source(原地址保持)、RI(請求URL)、rdp-cookie(根據cookie)
十、不能作Web服務器即Cache。nginx

2、LVS的組成

LVS 由2部分程序組成,包括 ipvs 和 ipvsadm。算法

1. ipvs(ip virtual server):一段代碼工做在內核空間,叫ipvs,是真正生效實現調度的代碼。
2. ipvsadm:另一段是工做在用戶空間,叫ipvsadm,負責爲ipvs內核框架編寫規則,定義誰是集羣服務,而誰是後端真實的服務器(Real Server)sql

3、lvs的三種模式

VS/DR模式

image

①.客戶端將請求發往前端的負載均衡器,請求報文源地址是CIP,目標地址爲VIP。vim

②.負載均衡器收到報文後,發現請求的是在規則裏面存在的地址,那麼它將目標MAC改成了RIP的MAC地址,並將此包發送給RS。後端

③.RS發現請求報文中的目的MAC是本身,就會將次報文接收下來,處理完請求報文後,將響應報文經過lo接口送給eth0網卡直接發送給客戶端。服務器

注意:cookie

須要設置lo接口的VIP不能響應本地網絡內的arp請求。

優勢

和TUN(隧道模式)同樣,負載均衡器也只是分發請求,應答包經過單獨的路由方法返回給客戶端。與VS-TUN相比,VS-DR這種實現方式不須要隧道結構,所以可使用大多數操做系統作爲物理服務器。

DR模式的效率很高,可是配置稍微複雜一點,所以對於訪問量不是特別大的公司能夠用haproxy/nginx取代。日1000-2000W PV或者併發請求1萬一下均可以考慮用haproxy/nginx。

缺點

全部 RS 節點和調度器 LB 只能在一個局域網裏面。

VS/TUN模式

image

①.客戶端將請求發往前端的負載均衡器,請求報文源地址是CIP,目標地址爲VIP。

②.負載均衡器收到報文後,發現請求的是在規則裏面存在的地址,那麼它將在客戶端請求報文的首部再封裝一層IP報文,將源地址改成DIP,目標地址改成RIP,並將此包發送給RS。

③.RS收到請求報文後,會首先拆開第一層封裝,而後發現裏面還有一層IP首部的目標地址是本身lo接口上的VIP,因此會處理次請求報文,並將響應報文經過lo接口送給eth0網卡直接發送給客戶端。

注意:

須要設置lo接口的VIP不能在公網上出現。

優勢

負載均衡器只負責將請求包分發給後端節點服務器,而RS將應答包直接發給用戶。因此,減小了負載均衡器的大量數據流動,負載均衡器再也不是系統的瓶頸,就能處理很巨大的請求量,這種方式,一臺負載均衡器可以爲不少RS進行分發。並且跑在公網上就能進行不一樣地域的分發。

缺點:

隧道模式的RS節點須要合法IP,這種方式須要全部的服務器支持」IP Tunneling」(IP Encapsulation)協議,服務器可能只侷限在部分Linux系統上。

VS/NAT模式

image

①.客戶端將請求發往前端的負載均衡器,請求報文源地址是CIP(客戶端IP),後面統稱爲CIP),目標地址爲VIP(負載均衡器前端地址,後面統稱爲VIP)。

②.負載均衡器收到報文後,發現請求的是在規則裏面存在的地址,那麼它將客戶端請求報文的目標地址改成了後端服務器的RIP地址並將報文根據算法發送出去。

③.報文送到Real Server後,因爲報文的目標地址是本身,因此會響應該請求,並將響應報文返還給LVS。

④.而後lvs將此報文的源地址修改成本機併發送給客戶端。

注意:

在NAT模式中,Real Server的網關必須指向LVS,不然報文沒法送達客戶端

優勢:

集羣中的物理服務器可使用任何支持TCP/IP操做系統,只有負載均衡器須要一個合法的IP地址。

缺點

擴展性有限。當服務器節點(普通PC服務器)增加過多時,負載均衡器將成爲整個系統的瓶頸,由於全部的請求包和應答包的流向都通過負載均衡器。當服務器節點過多時,大量的數據包都交匯在負載均衡器那,速度就會變慢!

7、LVS的八種調度算法

1. 輪叫調度 rr
這種算法是最簡單的,就是按依次循環的方式將請求調度到不一樣的服務器上,該算法最大的特色就是簡單。輪詢算法假設全部的服務器處理請求的能力都是同樣的,調度器會將全部的請求平均分配給每一個真實服務器,無論後端 RS 配置和處理能力,很是均衡地分發下去。

2. 加權輪叫 wrr
這種算法比 rr 的算法多了一個權重的概念,能夠給 RS 設置權重,權重越高,那麼分發的請求數越多,權重的取值範圍 0 – 100。主要是對rr算法的一種優化和補充, LVS 會考慮每臺服務器的性能,並給每臺服務器添加要給權值,若是服務器A的權值爲1,服務器B的權值爲2,則調度到服務器B的請求會是服務器A的2倍。權值越高的服務器,處理的請求越多。

3. 最少連接 lc
這個算法會根據後端 RS 的鏈接數來決定把請求分發給誰,好比 RS1 鏈接數比 RS2 鏈接數少,那麼請求就優先發給 RS1 

4. 加權最少連接 wlc
這個算法比 lc 多了一個權重的概念。

5. 基於局部性的最少鏈接調度算法 lblc
這個算法是請求數據包的目標 IP 地址的一種調度算法,該算法先根據請求的目標 IP 地址尋找最近的該目標 IP 地址全部使用的服務器,若是這臺服務器依然可用,而且有能力處理該請求,調度器會盡可能選擇相同的服務器,不然會繼續選擇其它可行的服務器

6. 複雜的基於局部性最少的鏈接算法 lblcr
記錄的不是要給目標 IP 與一臺服務器之間的鏈接記錄,它會維護一個目標 IP 到一組服務器之間的映射關係,防止單點服務器負載太高。

7. 目標地址散列調度算法 dh
該算法是根據目標 IP 地址經過散列函數將目標 IP 與服務器創建映射關係,出現服務器不可用或負載太高的狀況下,發往該目標 IP 的請求會固定發給該服務器。

8. 源地址散列調度算法 sh
與目標地址散列調度算法相似,但它是根據源地址散列算法進行靜態分配固定的服務器資源。

DR模式
    
    direct_server:192.168.254.17
    real_server:192.168.254.18
    real_server:192.168.254.19
    
    vip爲虛擬服務ip
    vip:192.168.254.250    
    
    
direct_server:
    yum install ipvsadm

老闆
direct_server:
    ipvsadm -C    #清除配置信息
    
    
    #添加對外提供的服務ip
    ipvsadm -A -t 192.168.254.250:80 -s rr    #-A爲ADD   -t爲tcp   -s rr爲設
置算法爲輪叫算法
    
    #添加2臺real_server主機
    ipvsadm -a -t 192.168.254.250:80 -r 192.168.254.18:80 -g #-a爲add   -
t爲tcp   -r爲realserver   -g爲DR路由模式
    ipvsadm -a -t 192.168.254.250:80 -r 192.168.254.19:80 -g #-a爲add   -
t爲tcp   -r爲realserver   -g爲DR路由模式
    
    #配置網卡的子網口爲vip,ip地址爲192.168.254.250
    ifconfig ens33:0 192.168.254.250 broadcast 192.168.254.250 netmask 
255.255.255.255 up
    
    #添加路由(訪問192.168.254.250都走ens33:0這個網卡)
    route add -host 192.168.254.250 dev ens33:0

員工1 | 員工2
real_server:
    #在迴環地址的子網口上配置服務ip(vip)
    ifconfig lo:0 192.168.254.250 broadcast 192.168.254.250 netmask 255.255.255.255 up 
    
    #添加路由
    route add -host 192.168.254.250 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


    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
    
    
    arp_ignore:定義接收到ARP請求時的響應級別      
        0:默認,只用本地配置的有響應地址都給予響應       
        1:僅僅在目標IP是本地地址,而且是配置在請求進來的接口上的時候纔給予響應
            (僅在請求的目標地址配置請求到達的接口上的時候,纔給予響應)

    arp_announce:定義將本身的地址向外通告時的級別       
        0:默認,表示使用配置在任何接口的任何地址向外通告       
        1:儘可能僅向目標網絡通告與其網絡匹配的地址       
        2:僅向與本地接口上地址匹配的網絡進行通告

nat配置

DS:橋接:192.168.31.100
        255.255.255.0
        192.168.31.1
   vmnet2:192.168.250.1
          255.255.255.0
RS1:192.168.250.2
    255.255.255.0
    192.168.250.1
RS2:192.168.250.3
    255.255.255.0
    192.168.250.1

#掛在本地鏡像
mount /dev/cdrom /mnt/
cd /mnt/Packages/

#安裝ipvsadm包
rpm -ivh ipvsadm-1.27-7.el7.x86_64.rpm

#開啓轉發模式
[root@db1 ~]# cat /proc/sys/net/ipv4/ip_forward 
0
[root@db1 ~]#echo 1 > /proc/sys/net/ipv4/ip_forward 
或者
vim /etc/sysctl.conf 
net.ipv4.ip_forward = 1


#配置nat模式
ipvsadm -A -t 192.168.31.100:80 -s rr 
ipvsadm -a -t 192.168.31.100:80 -r 192.168.250.2 -m 
ipvsadm -a -t 192.168.31.100:80 -r 192.168.250.3 -m 
#若是想讓配置保存下來須要 #查看ipvsadm包的文件位置 
[root@db1 ~]# rpm -ql ipvsadm-1.27-7.el7.x86_64 
/etc/sysconfig/ipvsadm-config 
/usr/lib/systemd/system/ipvsadm.service 
/usr/sbin/ipvsadm /usr/sbin/ipvsadm-restore 
/usr/sbin/ipvsadm-save /usr/share/doc/ipvsadm-1.27
/usr/share/doc/ipvsadm-1.27/README /usr/share/man/man8/ipvsadm-restore.8.gz 
/usr/share/man/man8/ipvsadm-save.8.gz /usr/share/man/man8/ipvsadm.8.gz 
#查看ipvsadm.service服務的結構能夠看到配置未見在/etc/sysconfig/ipvsadm

[root@db1 ~]# cat /usr/lib/systemd/system/ipvsadm.service 
那麼咱們只須要ipvsadm -S > /etc/sysconfig/ipvsadm就能夠把配置文件保存在配置文件中 
ipvsadm -R < /etc/sysconfig/ipvsadm就能夠從配置文件中恢復到當前配置

tun配置

tun隧道模式
    lvs-server
    ifconfig tunl0 192.168.254.250 broadcast 192.168.254.250 netmask 255.255.255.0 up
    route add -host 192.168.254.250 dev tunl0
    ipvsadm -A -t 192.168.254.250:80 -s rr
    ipvsadm -a -t 192.168.254.250:80 -r 192.168.254.18 -i
    ipvsadm -a -t 192.168.254.250:80 -r 192.168.254.19 -i


    real server
    ifconfig tunl0 192.168.254.250 netmask 255.255.255.255 broadcast 192.168.254.250 up
    route add -host 192.168.254.250 dev tunl0
    echo "1" >/proc/sys/net/ipv4/conf/tunl0/arp_ignore
    echo "2" >/proc/sys/net/ipv4/conf/tunl0/arp_announce
    echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
    echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
    echo "0" >/proc/sys/net/ipv4/conf/tunl0/rp_filter
    echo "0" > /proc/sys/net/ipv4/conf/all/rp_filter

    0:不開啓源地址校驗。
    1:開啓嚴格的反向路徑校驗。對每一個進來的數據包,校驗其反向路徑是不是最佳路徑。
        若是反向路徑不是最佳路徑,則直接丟棄該數據包。
    2:開啓鬆散的反向路徑校驗。對每一個進來的數據包,校驗其源地址是否可達,即反向路徑是否能通(經過任意網口),
        若是反向路徑不一樣,則直接丟棄該數據包。

用python寫腳本實現DR模式的設置
```
import paramiko
vip = '192.168.93.250'
ds = '192.168.93.11'
rs1 = '192.168.93.12'
rs2 = '192.168.93.13'
ds_cmd = '''
ipvsadm -C;
ipvsadm -A -t {vip}:80 -s wrr;
ipvsadm -a -t {vip}:80 -r {rs1}:80 -w 1 -g;
ipvsadm -a -t {vip}:80 -r {rs2}:80 -w 2 -g;
ifconfig ens33:0 {vip} broadcast {vip} netmask 255.255.255.255 up;
route add -host {vip} dev ens33:0;
'''.format(vip=vip, rs1=rs1, rs2=rs2)

rs1_cmd = '''
ifconfig lo:0 {vip} broadcast {vip} netmask 255.255.255.255 up;
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;
service httpd restart
'''.format(vip=vip)
rs2_cmd = '''
ifconfig lo:0 {vip} broadcast {vip} netmask 255.255.255.255 up;
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;
service httpd restart
'''.format(vip=vip)

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def direct_server():
ssh.connect('{ds}'.format(ds=ds), 22, 'root', '000123',timeout=3)
stdin, stdout, stderr = ssh.exec_command(ds_cmd)
print(stderr.read().decode('utf-8'))
print(stdout.read().decode('utf-8'))
print('dicret_server配置完成!!!')

def real_server1():
ssh.connect('{rs1}'.format(rs1=rs1), 22, 'root', '000123', timeout=3)
stdin, stdout, stderr = ssh.exec_command(rs1_cmd)
print(stderr.read().decode('utf-8'))
print(stdout.read().decode('utf-8'))
print('real_server1配置完成!!!')

def real_server2():
ssh.connect('{rs2}'.format(rs2=rs2), 22, 'root', '000123', timeout=3)
stdin, stdout, stderr = ssh.exec_command(rs2_cmd)
print(stderr.read().decode('utf-8'))
print(stdout.read().decode('utf-8'))
print('real_server2配置完成!!!')

def main():
direct_server()
real_server1()
real_server2()
ssh.close()

if name == 'main': main() ```

相關文章
相關標籤/搜索