LVS (一) 原理

昀溪發表於2018-10-07

LVS原理概述

負載均衡就是,在多個提供相同服務主機的前段,增加一個分發器,根據使用者請求,然後根據某種方式或者策略,將使用者請求分發到提供服務的主機上。同時負載均衡應用還應該提供對後其後端服務健康檢查的功能。

如何轉發取決於排程演算法,有2種演算法一個是RR一個是WRR。使用者看到的是負載均衡的地址,一般還會對負載均衡做高可用,這樣才能保證業務的持續性。
負載均衡有2大類:

  • 硬體:F5的BIG IP;Citrx的Netcaler
  • 軟體:
    • 四層負載均衡(LVS):TCP/IP層,類似一個路由裝置,根據使用者請求的套接字(三層IP)和四層的埠協議型別,將請求分發至後端主機。LVS的發明者是中國人。
    • 七層負載均衡(Nginx和Haproxy):Nginx主要是對HTTP、SMTP、POP3和IMAP協議做負載均衡,是一個7層代理,只負責解析有限的7層協議;Haproxy主要是對HTTP做負載均衡,另外還可以對常見的TCP/IP層應用做負載均衡,比如MYSQL,還有SMTP。

四層和七層的有什麼區別?

一般七層的負載均衡叫做代理或者叫反向代理。四層和七層的主要區別在於四層只解析到TCP/IP層,它不在解析更高層,說白了就是不再繼續拆包,所以四層的比七層的效能更好,但是缺點是沒有高階特性,網康裝置就是工作在七層的,所以它可以有很多高階功能,比如檢視使用者訪問了那些網站,其實就是對HTTP請求做的解析。對負載均衡裝置來說,工作在七層的可以根據使用者請求的URL來做負載均衡。而且七層負載均衡一般都是針對特定一種或者幾種(不會是所有,也就是針對某一個方面)做解析,同時它還支援對解析出來的東西做一些修改然後在向後端分配。不過相對來講七層的效能比四層的略低(在相同硬體配置和相同請求量的前提下),不過在生產環境中七層的更能貼近實際需求,所以在選擇使用哪種負載均衡的時候要根據業務特性和需求來進行判斷。

LVS可以解析三層和四層請求,只要是TCP/IP協議都可以解析,假設一個WEB伺服器叢集,使用預設80埠,其中一臺主機是172.16.100.1,如果負載均衡器收到一起請求,那麼它就會把請求轉發到該主機上,這個過程有點類似於NAT,但是還不同,因為它可以向後轉發到多臺主機上。

DNAT的工作過程:

使用者請求IP:PORT地址A(這個地址是路由器的地址),路由器收到這個地址後會檢視自己的過濾表,如果找到匹配的配置項,就會修改資料包的目標地址為後端主機的真實地址,然後把資料包放到轉發佇列,然後進行轉發。如果發現沒有匹配項,則認為這個請求是請求給路由器自己的,因為請求帶有埠號,路由器會檢查自己是否開啟了對應埠的程式,如果有就說明是訪問該程式的,如果沒有就會給請求發起方報錯。

LVS其實也是借鑑了DNAT的工作方式,LVS工作在Linux的核心空間上。但是不同的是LVS收到請求會直接修改請求的資料包中的目標地,然後進行轉發。

在Iptables中,ipbables只是用來寫規則的,真正執行的是netfilter;在LVS中也是類似的結構,ipvsadmin是管理工具(工作在使用者空間的工具),ipvs是執行的且工作在核心中。Ipvs是工作在input鏈上(Input鏈是Iptables所用的到的Linux核心框架的一部分),一旦使用者請求到了input鏈,就會被IPVS捕獲,然後IPVS就會去檢查資料包,如果它發現請求是一個叢集服務就會修改資料包,然後轉發。如果IPVS發現這個請求不是對叢集服務的請求,就會把這個請求轉發到使用者空間(Linux系統的使用者空間)。這一點和iptables有點不太一樣,所以iptables和LVS不能同時在一臺Linux主機上使用。所以LVS中的IPVS必須工作在核心中。所以基於IP和埠的轉發就是四層轉發。

一個負載均衡排程器可以為多個叢集服務提供服務,功能上可以,但是出於效能考慮一般不會這麼做,所以一個負載均衡排程器只會為一個叢集服務提供服務。

LVS的伺服器有2個網路卡,對外接收請求的網路卡的IP叫做VIP,也就是虛擬IP,其實也是真實的IP地址,至少這樣稱呼,相對於內部真正的應用伺服器而言;對內的網路卡的IP叫做DIP,也就是轉發IP;而真實的應用伺服器網路卡的IP叫做RIP。使用者電腦的IP叫做CIP。

LVS的三種型別

LVS-NAT模式

對於這種型別,負載均衡排程器需要有2個網路介面,一個面對網際網路,一個面對內網,也就是上面的圖形。屬於串聯模式。相當於在LVS後面組成一個私有網路。
實現原理就是把使用者的請求的地址修改為後端真是伺服器的IP地址來然後進行轉發。工作機制和DNAT一樣。

源地址是CIP,目標地址是VIP,然後修改資料包,挑選一個後端伺服器,然後就把資料包轉發到該後端伺服器,這時候資料包的源IP是CIP,目標IP則是某一臺主機的RIP。
當主機返回資訊的時候,轉發器會在做一次轉發,修改資料包。

在這種模式下對於使用者請求的進出都要經過轉發器,所以轉發器的壓力相對較大。在這種模式下後端應用最多10個,但一般都會少於10個。

基本法則:

  • 轉發器、應用伺服器都要在同一子網中(轉發器的DIP和應用伺服器組成一個私有網路)
  • 應用伺服器的閘道器要指向DIP
  • RIP通常都是私有地址,而且僅可以和DIP通訊
  • 轉發器可以實現埠對映,例如80轉換到8080
  • 應用伺服器可以是任何作業系統
  • 單一轉發器可能成為整個叢集的瓶頸尤其是在大規模場景下

一般企業不使用NAT模型,哪怕應用伺服器比較少。

缺陷:轉發器和應用伺服器必須在同一子網中

LVS-DR 直接路由模式

LVS伺服器和應用伺服器都是單網路卡,LVS和應用伺服器並聯在交換機上。

在這個模型上就是請求進來被髮送到LVS上,LVS的核心空間的IPVS擷取,然後分析,如果是訪問叢集服務,就轉發到被LVS選中的應用伺服器上,應用伺服器處理完成後,直接返回資料給客戶端,而不再經過LVS,這樣就減少了LVS的工作負擔,同時應用伺服器也不用和LVS組成一個私有網路。

這裡就有一個問題,我們知道轉發器在會把資料包中的目標IP更換為RIP進行轉發,那麼應用伺服器處理完成後返回結果,返回資料包的源IP會是RIP,目標IP則是CIP,這時就不對了,因為請求進來的時候目標IP是LVS上的VIP。所以為了解決這個問題,LVS和所有應用伺服器上都配置了VIP。

那麼這裡就又有一個問題,如果都配置相同的VIP,那麼就會衝突,而且路由器也不知道該發給誰,所以這裡就用到了網路卡別名。在LVS上它其實配置了VIP和DIP,雖然只有一個網路卡,VIP配置在網路卡上,DIP配置在網路卡別名上。在應用伺服器上,RIP是不同的這個是肯定的,VIP是一樣的,這個VIP也是配置在網路卡別名上而且是隱藏的,它不用來接收任何請求,接收資料還是RIP來完成,這個VIP只有在應用伺服器響應請求的時候把它作為源地址時使用,當然實際使用的網路卡開始那個配置了RIP的網路卡,在通訊層面上VIP不起作用,它只是作為資料包的源地址使用。

不過需要注意的是,在DR模式中,轉發器會修改請求的資料包的地址,但是修改不是把VIP替換成RIP,而是修改了地址(源MAC和目標MAC)。因為從路由器進來以後,會把報文封裝成幀,會加入源MAC和目標MAC,路由器的內網口會把源MAC地址寫成自己的內網口MAC,目標寫成LVS物理網路卡的MAC地址,然後LVS收到以後會修改幀裡面的目標MAC地址(原來為LVS網路卡的MAC地址)為被挑選的應用伺服器的MAC地址,修改源MAC地址(原來路由器內網口的MAC地址)為自己網路卡的MAC地址,而不是修改目標IP地址。

當應用伺服器收到資料包以後,拆掉MAC地址,看到的資料包的源IP是CIP也就是客戶端的IP,而目標IP就是VIP,而且應用伺服器上透過網路卡別名已經設定了VIP,所以它會認為這就是個自己的。處理完請求後需要返回資料,因為客戶端是請求的VIP,所以應用伺服器就用VIP來封裝資料包,這樣就直接響應出去了,而不需要再經過LVS。
這樣的話就LVS的效能就會有很大提高,因為請求資料包都很小,響應報文都比較大。

說明:無論是否是DR模式,來自網路層的IP報文都最終都會被封裝成幀。所以路由器接收到IP資料包之後會先到到資料鏈路層後經過LLC子層和MAC子層進行協議頭封裝,最終形成乙太網MAC幀,送達到主機。

基本法則:

  • 叢集節點和轉發器必須在同一物理網路內,因為它使用MAC地址轉發
  • RIP的地址可以使用公網IP
  • 轉發器僅處理入棧請求,響應報文由應用伺服器之間發往客戶端
  • 叢集節點不能使用DIP作為閘道器
  • 這種模式下轉發器不支援埠對映
  • 大多數作業系統都可以是應用伺服器,因為應用伺服器需要隱藏VIP
  • DR模式效能強,可以處理比NAT模式更多的主機

缺陷:所有應用伺服器都暴露在公網,就算它用私有地址,但是也要保障它可以和網際網路直接通訊,否則它響應的報文無法到達客戶端。

LVS-TUN 隧道模式

DR模式下叢集節點要在同一物理網路內,那有一種場景如果要實現異地容災,兩個機房在不同城市甚至是不同國家,那怎麼辦?這就用到隧道模式。

在隧道模式下LVS即不替換VIP也不修改MAC地址,而是透過在資料包文外層再套一層報文來封裝。

因為客戶端請求發過來的時候源IP是CIP,目標IP是VIP,所以LVS要轉發到其他地區的應用伺服器上這隻能在三層協議上進行也就是IP報文,如果你替換了VIP,那麼應用伺服器響應客戶端的時候就有問題,所以就會在原有的IP報文上在套一層來封裝,把LVS的DIP作為源IP,而應用伺服器的RIP作為目標IP,然後進行轉發。當應用伺服器收到資料包以後,拆開第一層,然後發現裡面的資料包有CIP和VIP,應用伺服器上也有VIP(跟DR模式一樣使用網路卡別名然後隱藏),就會認為是發給自己的,然後做出處理最後響應請求,同時封裝響應請求的時候目標是CIP,源IP則使用VIP地址。

在這種模式下LVS和應用伺服器要支援隧道機制。

基本法則:

  • 叢集節點可以跨越網際網路部署
  • 應用伺服器的RIP必須是公網地址(可路由的)
  • 轉發器僅處理入棧請求
  • 響應報文直接傳送給客戶端不經過LVS,也就是說應用伺服器的閘道器指向公網閘道器
  • 支援隧道功能的作業系統才可以成為應用伺服器
  • 不支援埠對映

LVS-FULLNAT 模式

Linux核心發展到2.6.32以後才引入的一種型別,這個型別必須要打補丁才能使用。不過現在大多使用CentOS 7所以無需補丁。

這個模型是採用NAT基礎但是解決了應用伺服器和排程器可以在不同子網中。因為是NAT模型所以應用伺服器就不會暴露在網際網路上,同時也實現了應用伺服器可以跨網段部署。

所謂FULLNAT就是把資料包的源地址和目標地址都做修改,入棧的時候把CIP
+VIP的資料包修改為DIP+RIP的資料包,這樣就可以傳送到應用伺服器上,當應用伺服器響應請求的時候,同樣適用DIP+RIP的資料包,這樣就保障肯定會發到LVS主機上,然後排程器再次修改資料包的源地址和目標地址,改成CIP+VIP然後傳送給客戶端。

LVS的排程演算法

排程演算法就是從LVS的後端應用伺服器中挑選一個進行轉發。排程演算法有10種,那麼10種又分成2大類,靜態方法和動態方法。

靜態方法:

只根據演算法本身進行排程和分配請求,這種方法中RR和WRR有缺陷就是使用者會話無法保持,比如在電商網站上,使用者第一次的請求被轉發到了A伺服器,使用者第二次的操作請求被轉發到了B伺服器,所以這就造成了使用者第一次會話請求資料丟失。所以要想解決就只能使用Session複製或者建立單獨的伺服器。

  • RR,也就是輪詢一個挨一個的逐個轉發,這種方法不考慮伺服器本身的硬體效能。
  • WRR,加權輪詢,也就是給每個伺服器設定權重,權重高的多分配。
  • SH:源地址雜湊,這個方法主要是增加了實現Session繫結功能,只要來源於同一個IP的就定向到相同的應用伺服器。但是它反均衡,就是會把同一IP地址出口的所有請求都轉發到同一伺服器,比如一般公司出口IP是一個,几几百人都用這一個公網IP上網。因為LVS是工作在四層的,所以它也只能根據IP來識別會話。無法像F5那樣七層裝置根據COOKIE來識別,COOKIE對於每一個計算機來說都是唯一,即使大家都用同一公網IP上網。
  • DH:目標地址雜湊,這個應用場景不多,它主要的作用就是保證在LVS前面有多臺防火牆的時候,使用者請求從哪個防火牆進來最後響應也從哪個防火牆出去。

動態方法:

根據演算法和應用伺服器的負載情況綜合分析來覺得轉發到哪個應用伺服器。

  • LC(Least Connection):最少連結數方法。也就是哪個伺服器的連線數少就給哪個的,但是在TCP中,連線有2種狀態,一個是正在傳送資料的叫做活動連線、另外一個是沒有傳輸資料但是連線沒有斷叫做非活動連線,這兩種連線所需要的資源是不同的,顯然活動連線需要伺服器的資源多,而非活動連線僅需要維持一個與伺服器的會話就行。所以這種方法是考慮應用伺服器的負載(活動連線數*256+非活動連線),這個計算結果數小的勝出,如果結果都一樣就輪詢。不過這種方法是不考慮權重的,其基本方法還是輪詢,只是增加了一個計算負載的前置條件。
  • WLC(Weighted LC):加權最少連線演算法,這個演算法跟LC大體一樣只是考慮了權重而不簡單的輪詢,(活動連線數*256+非活動連線)/權重,數最小的勝出,如果都一樣還是輪詢。
  • SED(Shorting expect delay):最少期望延遲,它是一種改進型的WLC,為了避免連線少的時候正好挑選了最差效能的伺服器,(活動連線數+1)*256/權重。
  • NQ(Nerver Queue):永不排隊,第一次根據權重輪詢一遍,之後根據SED演算法來分配。
  • LBLC(Locality-based least connection):基於本地的最少連線,相當於DH+LC演算法,主要用於後端的應用伺服器是快取伺服器的時候,來提高快取命中率,不過很少用這種演算法。
  • LBLCR(Rerplicated and Locality-based least connection):帶複製的基於本地最少連線,主要用於後端的應用伺服器是快取伺服器的時候。來提高快取命中率,不過很少用這種演算法。

補充知識:

Session會話儲存的方法有三種:

  • Session繫結:將同一請求者的連線始終保持連線在同一伺服器上,這種方式沒有容錯能力,如果使用者請求的會話在A伺服器上,那麼A伺服器一旦故障,那麼使用者請求會話的資料就丟失了。另外還有一個缺陷是反均衡,也就是一旦繫結該使用者的會話請求都會到這個伺服器上,無論這個伺服器是否繁忙,在大規模環境中,這種方法也不適用。
  • Session複製:在所有應用伺服器上建立Session叢集,基於單播、多播或者廣播的方式實現Session傳遞,讓每個應用伺服器都擁有一份相同的完整會話資料,在大規模叢集環境中,這種方式不適用。
  • 建立單獨的Session伺服器,所有應用伺服器都共享該會話伺服器,而且該伺服器也要實現高可用,否則會有單點故障。

LVS的缺陷是:它不會考慮應用伺服器的健康狀況,如果應用伺服器故障它也會選擇。

相關文章