lvs

簡(jiǎn)介

lvs是linux上的一種負(fù)載均衡技術(shù)。這篇文章簡(jiǎn)單記錄測(cè)試和理解。

網(wǎng)絡(luò)基礎(chǔ)

網(wǎng)絡(luò)的七層模型中,第三層是網(wǎng)絡(luò)層,常見的系統(tǒng)維護(hù)工作就是網(wǎng)絡(luò)層的維護(hù),如ip配置,路由配置;第二層是數(shù)據(jù)鏈路層,是服務(wù)器底層網(wǎng)卡和交換機(jī)數(shù)據(jù)交換的基礎(chǔ),數(shù)據(jù)鏈路層的數(shù)據(jù)包的結(jié)構(gòu)是地址+類型+數(shù)據(jù),其中數(shù)據(jù)可以是第三層的ip報(bào)文。當(dāng)服務(wù)器A向服務(wù)器B發(fā)送數(shù)據(jù),除了在ip報(bào)文里面存放源ip地址和目標(biāo)ip地址,還需要在數(shù)據(jù)鏈路層的數(shù)據(jù)包地址部分封裝源MAC地址和目標(biāo)MAC地址,服務(wù)器是如何根據(jù)ip地址獲取目標(biāo)MAC地址的呢?這里要分兩種情況討論:如果服務(wù)器A和服務(wù)器B在同網(wǎng)段,那么目標(biāo)MAC地址就是B服務(wù)器配置了對(duì)應(yīng)IP的網(wǎng)卡的MAC地址,這時(shí)候服務(wù)器A是通過arp協(xié)議,發(fā)送廣播給同網(wǎng)段的服務(wù)器,查詢指定ip的MAC地址;如果不在同網(wǎng)段那么目標(biāo)MAC地址是網(wǎng)關(guān)設(shè)備(一般就是路由器)的MAC地址,服務(wù)器在數(shù)據(jù)包中封裝的目標(biāo)MAC就是網(wǎng)關(guān)設(shè)備的MAC(可以理解為什么服務(wù)器的網(wǎng)關(guān)要設(shè)置成與自身ip同網(wǎng)段,因?yàn)榉?wù)器也是通過arp獲取網(wǎng)關(guān)MAC的),然后把包發(fā)送給網(wǎng)關(guān)設(shè)備,后面的轉(zhuǎn)發(fā)由網(wǎng)關(guān)設(shè)備去完成??梢岳斫釳AC就是數(shù)據(jù)包下一跳的網(wǎng)卡的MAC地址

arp測(cè)試

arp一般都是自動(dòng)工作的,不需要手工配置,手工配置一般是網(wǎng)絡(luò)層,簡(jiǎn)化了系統(tǒng)維護(hù)工作。

#arp相關(guān)命令
arp -n   #查看ip和mac地址對(duì)應(yīng)關(guān)系,可以用來排查ip沖突
arp -d xx.xxx.xx.xx  #刪除某個(gè)arp緩存
tcpdump -e arp host xx.xx.xx.xx  #抓取目的ip或者源ip是xx.xx.xx.xx的arp數(shù)據(jù)包,并且打印mac地址信息

lvs原理

lvs的通信架構(gòu)就是客戶端發(fā)送數(shù)據(jù)到直連服務(wù)器(簡(jiǎn)寫DR),再轉(zhuǎn)到真實(shí)服務(wù)器(簡(jiǎn)寫RS,一般多臺(tái))。
lvs有三種模式:

  • nat:客戶端發(fā)送數(shù)據(jù)到DR之后,DR修改數(shù)據(jù)包的源地址和目標(biāo)地址,然后轉(zhuǎn)發(fā)給RS,RS處理之后會(huì)給DR,DR再回給客戶端。nginx也是這種工作模式。由于公網(wǎng)ip數(shù)量有限,局域網(wǎng)和互聯(lián)網(wǎng)的通信也是這種模式,局域網(wǎng)有個(gè)路由器連接了互聯(lián)網(wǎng)和局域網(wǎng)內(nèi)部的網(wǎng)絡(luò),它同時(shí)有互聯(lián)網(wǎng)ip和局域網(wǎng)ip。特點(diǎn)是配置簡(jiǎn)單,要求低。
  • tun: 隧道模式,就是在基礎(chǔ)的數(shù)據(jù)包外層再封裝一層數(shù)據(jù)包結(jié)構(gòu)。特點(diǎn)是支持跨機(jī)房。
  • dr: 客戶端發(fā)送數(shù)據(jù)到DR之后,DR修改數(shù)據(jù)包的MAC地址為真實(shí)服務(wù)器網(wǎng)卡的MAC地址,不修改數(shù)據(jù)包的源ip(源IP還是客戶端IP),然后發(fā)送給RS(RS需要配置與DR相同的ip,這樣RS收到數(shù)據(jù)包就會(huì)正常處理),RS處理之后,直接應(yīng)答給客戶端(因?yàn)镈R發(fā)來的數(shù)據(jù)包的源ip是客戶端ip),不需要經(jīng)過DR。DR是使用最廣泛的,因?yàn)閿?shù)據(jù)包只有進(jìn)來的時(shí)候需要DR分發(fā)給RS,RS返回?cái)?shù)據(jù)的時(shí)候不需要經(jīng)過DR處理,性能比nat和tun好。DR模式的網(wǎng)絡(luò)處理瓶頸在于修改進(jìn)來的網(wǎng)絡(luò)包MAC,所以如果進(jìn)來的網(wǎng)絡(luò)包較小,處理能力就較強(qiáng)。

對(duì)于dr模式,需要在RS和DR上面配置同樣的ip,那么不會(huì)存在ip沖突的問題嗎?這個(gè)問題就需要上面提到的arp協(xié)議知識(shí)解答了。如果多臺(tái)服務(wù)器(DR+RS)配置同一個(gè)ip(假設(shè)為vip),但是只有一個(gè)服務(wù)器會(huì)回應(yīng)對(duì)vip的arp查詢(實(shí)際就是DR服務(wù)器),那么所有到vip的數(shù)據(jù)包都會(huì)發(fā)送到這個(gè)能正?;貞?yīng)arp查詢的服務(wù)器,不會(huì)發(fā)生ip沖突的問題。
為什么需要在RS上面也配置vip呢?因?yàn)檫@樣RS收到DR修改了MAC地址的數(shù)據(jù)包的時(shí)候,解析數(shù)據(jù)包發(fā)現(xiàn)目的ip就是自己配置了的vip,就會(huì)正常處理并返回?cái)?shù)據(jù)包;RS應(yīng)答的數(shù)據(jù)包的源ip就是vip,目標(biāo)ip是客戶端ip,客戶端收到后也能正常處理,形成一個(gè)閉環(huán)?;蛘呷绻鸕S返回?cái)?shù)據(jù)包的源ip是其他ip,就會(huì)發(fā)生客戶端問ipx一個(gè)問題,忽然收到一個(gè)來自ipy的回答,它對(duì)應(yīng)不上來,處理不了。

lvs測(cè)試驗(yàn)證

  • 環(huán)境準(zhǔn)備:
    一臺(tái)DR,ip為18.1.99.238,兩臺(tái)RS,ip分別為18.1.99.236和18.1.99.237,vip為18.1.99.239,客戶端則是任意一個(gè)linux服務(wù)器
  • RS服務(wù)器配置:
    在兩臺(tái)RS上安裝nginx,并進(jìn)行簡(jiǎn)單配置
[root@18.1.99.236 conf.d]# cat index.conf 
server {
   listen 8080;
   location / {
     return 200 "this is on 236\n";
   }

}
[root@18.1.99.236 conf.d]# cd  /usr/local/nginx/sbin/
[root@18.1.99.236 sbin]# ./nginx 
[root@18.1.99.236 sbin]# curl http://18.1.99.236:8080
this is on 236

[root@18.1.99.237 conf.d]# cat index.conf 
server {
   listen 8080;
   location / {
     return 200 "this is on 237\n";
   }

}
[root@18.1.99.237 conf.d]# cd  /usr/local/nginx/sbin/
[root@18.1.99.237 sbin]# ./nginx 
[root@18.1.99.237 sbin]# curl http://18.1.99.237:8080
this is on 237
  • 網(wǎng)絡(luò)配置
ipvsadm命令參數(shù)
              -A #添加DR
              -D #刪除DR
              -L  #顯示配置
              -a  #添加RS
              -d  #刪除RS
              -t   #tcp協(xié)議
              -s  [rr|wrr|dh|sh|..]  #DR分發(fā)給RS的策略
              -g #dr模式,默認(rèn)模式
              -i  #tun模式
              -m #nat模式

#dr配置
[root@18.1.99.238 ~]# cd /etc/sysconfig
[root@18.1.99.238 ~]# touch ipvsadm
[root@18.1.99.238 ~]# systemctl start ipvsadm
[root@18.1.99.238 ~]# ipvsadm -A -t 18.1.99.239:8080 -s rr
[root@18.1.99.238 ~]# ipvsadm -a -t 18.1.99.239:8080 -r 18.1.99.236:8080 -g -w 1
[root@18.1.99.238 ~]# ipvsadm -a -t 18.1.99.239:8080 -r 18.1.99.237:8080 -g -w 1
[root@18.1.99.238 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  18.1.99.239:8080 rr
  -> 18.1.99.236:8080             Route   1      0          0         
  -> 18.1.99.237:8080             Route   1      0          0

#客戶端訪問測(cè)試
curl http://18.1.99.239:8080/
#抓包監(jiān)控
#DR和RS服務(wù)器上同時(shí)抓包和監(jiān)控?cái)?shù)據(jù)包錯(cuò)誤
[root@18.1.99.237 ~]# tcpdump -nn -vv  tcp port 8080
tcpdump: listening on ens192, link-type EN10MB (Ethernet), capture size 262144 bytes
19:16:01.154305 IP (tos 0x0, ttl 62, id 55678, offset 0, flags [DF], proto TCP (6), length 60)
    18.1.98.240.54158 > 18.1.99.239.8080: Flags [S], cksum 0xb33c (correct), seq 4057379965, win 29200, options [mss 1460,sackOK,TS val 847014882 ecr 0,nop,wscale 7], length 0
^C
1 packet captured
1 packet received by filter
0 packets dropped by kernel

[root@18.1.99.237 ~]# sar -n EIP 1
Linux 4.18.0-193.el8.x86_64 (18.1.99.237)         04/10/2023      _x86_64_        (4 CPU)

07:15:49 PM ihdrerr/s iadrerr/s iukwnpr/s   idisc/s   odisc/s   onort/s    asmf/s   fragf/s
07:16:00 PM      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
07:16:02 PM      0.00      1.00      0.00      0.00      0.00      0.00      0.00      0.00

[root@18.1.99.100 ~]# arp -n | grep 18.1.99.239
18.1.99.239              ether   00:50:56:b2:74:f4   C                     eth0

#可以發(fā)現(xiàn)RS18.1.99.237收到了DR轉(zhuǎn)發(fā)過來的數(shù)據(jù)包
#但是由于RS上面沒有配置18.1.99.239,導(dǎo)致網(wǎng)絡(luò)包錯(cuò)誤iadrerr增加,無法正常響應(yīng)客戶端的訪問

#所以必須在RS在lo網(wǎng)卡上配置vip18.1.99.239,并且禁止RS響應(yīng)關(guān)于18.1.99.239的arp查詢請(qǐng)求
#ens192是我服務(wù)器的網(wǎng)卡,根據(jù)自己服務(wù)器情況設(shè)置
sysctl -w net.ipv4.conf.ens192.arp_ignore=1
ifconfig lo:1 18.1.99.239 netmask 255.255.255.255
#這個(gè)配置會(huì)導(dǎo)致從ens192收到的arp查詢的地址如果不是ens192網(wǎng)卡上配置的,
#就不會(huì)回應(yīng)。數(shù)據(jù)包都是從ens192進(jìn)來的,vip配置在lo網(wǎng)卡上,所以RS服務(wù)器不會(huì)回應(yīng)vip的arp查詢請(qǐng)求。
#再次測(cè)試,客戶端收到并且正?;貜?fù)

#但是如果客戶端也在18.1.99.0/24這個(gè)網(wǎng)段(和RS一個(gè)網(wǎng)段),還是會(huì)出現(xiàn)問題
#測(cè)試結(jié)果見下面圖片arp_announce.png
#觀察發(fā)現(xiàn)RS的確沒有回應(yīng)客戶端的arp查詢請(qǐng)求,
#但是RS回包給客戶端的時(shí)候發(fā)現(xiàn)客戶端和自己是一個(gè)網(wǎng)段的,于是RS通過arp請(qǐng)求查詢客戶端服務(wù)器MAC地址,
#這個(gè)arp請(qǐng)求包的源ip是vip,MAC是RS的網(wǎng)卡ens192的MAC地址,客戶端收到這個(gè)請(qǐng)求之后會(huì)更新arp表,將vip和RS網(wǎng)卡ens192的MAC對(duì)應(yīng)上了。
#所以linux上服務(wù)器A查詢服務(wù)器B的MAC可能會(huì)觸發(fā)服務(wù)器B的arp表更新

#為了解決這個(gè)問題,就需要調(diào)整RS系統(tǒng)參數(shù)
sysctl -w net.ipv4.conf.ens192.arp_announce=2
#這會(huì)導(dǎo)致RS查詢客戶端MAC的時(shí)候arp查詢請(qǐng)求包的源ip是ens192網(wǎng)卡的ip,而不是lo網(wǎng)卡上配置的vip(雖然RS是打算使用vip和客戶端通信),這樣RS查詢客戶端的MAC地址的時(shí)候就不會(huì)更新客戶端的arp表。

arp_announce.png

總結(jié)

想要理解lvs的工作原理,需要了解數(shù)據(jù)鏈路層的通信原理,arp協(xié)議;在這篇文章中,我通過一步一步添加配置,然后抓包測(cè)試,分析缺少配置會(huì)發(fā)生的問題,有助于深入了解lvs工作原理。其中最重要的是通過tcpdump抓包分析這個(gè)過程。
網(wǎng)上關(guān)于arp_announce的說明始終有點(diǎn)難以完全理解,但是我通過保持arp_announce為0,進(jìn)行測(cè)試,觀察導(dǎo)致的問題之后,就很好理解為什么要設(shè)置arp_announce為2了。

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容