這篇文章將為大家詳細(xì)講解有關(guān)TKE容器網(wǎng)絡(luò)中的ARP Overflow問題探究及其解決方法是什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
10年積累的網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有阿合奇免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
最近,某內(nèi)部客戶的 TKE VPC-CNI 模式的獨(dú)立網(wǎng)卡集群上出現(xiàn)了 pod 間訪問不通的情況,問題 pod ping 不通任何其他 pod 和節(jié)點(diǎn)。
查看 dmesg 內(nèi)核日志,有如下報(bào)錯(cuò)信息:neighbour: arp_cache: neighbor table overflow!(下圖為后續(xù)復(fù)現(xiàn)的日志截圖)
并且,這個(gè)集群規(guī)模較大,約有 1000 個(gè)節(jié)點(diǎn),30000 個(gè) pod,基本可以懷疑是由于集群規(guī)模較大,導(dǎo)致 ARP 表項(xiàng)過多,從而引起 ARP Overflow 的問題。
名詞 | 說明 |
---|---|
TKE | 全稱 Tencent Kubernetes Engine, 騰訊云容器服務(wù),是基于原生 kubernetes 提供以容器為核心的、高度可擴(kuò)展的高性能容器管理服務(wù) |
VPC-CNI 模式 | 是容器服務(wù) TKE 基于 CNI 和 VPC 彈性網(wǎng)卡實(shí)現(xiàn)的容器網(wǎng)絡(luò)能力 |
Pod | Pod 是 kubernetes 的基本資源管理單位,擁有獨(dú)立的網(wǎng)絡(luò)命名空間,1個(gè) Pod 可包含多個(gè)容器 |
從如上報(bào)錯(cuò)信息可知,這個(gè)問題的基本原因在于 ARP 緩存表打滿了。這里涉及到內(nèi)核的 ARP 緩存垃圾回收機(jī)制。當(dāng) ARP 表項(xiàng)太多且又沒有可回收的表項(xiàng)的時(shí)候,新表項(xiàng)就會(huì)無法插入。
這就導(dǎo)致網(wǎng)絡(luò)包發(fā)送時(shí)無法找到對(duì)應(yīng)的硬件地址(MAC)。使得網(wǎng)絡(luò)包不能發(fā)送。
那么具體什么情況會(huì)導(dǎo)致新表項(xiàng)無法插入呢?回答這個(gè)問題,我們需要先深入了解一下 ARP 緩存老化及垃圾回收機(jī)制。
如上圖,是整個(gè) ARP 表項(xiàng)的生命周期及其狀態(tài)機(jī)。
我們知道,對(duì)于 TCP/IP 網(wǎng)絡(luò)包發(fā)送時(shí),網(wǎng)絡(luò)棧需要對(duì)端的 MAC 地址才能讓網(wǎng)絡(luò)包轉(zhuǎn)換成二層的數(shù)據(jù)結(jié)構(gòu)——幀,從而在網(wǎng)絡(luò)中傳輸。而對(duì)于不同廣播域的 IP 地址,其對(duì)端 MAC 地址為網(wǎng)關(guān),發(fā)送端會(huì)將網(wǎng)絡(luò)包發(fā)給網(wǎng)關(guān)讓其轉(zhuǎn)發(fā),而對(duì)于同廣播域中的 IP 地址,其對(duì)端 MAC 地址即與 IP 地址對(duì)應(yīng)。
而通過 IP 地址找到 MAC 地址就是 ARP 協(xié)議的主要工作內(nèi)容。ARP 協(xié)議的工作過程此處不再贅述,而通過 ARP 協(xié)議找到 IP 地址對(duì)應(yīng)的 MAC 地址后,會(huì)將該對(duì)應(yīng)關(guān)系存儲(chǔ)在本機(jī)上一段時(shí)間,以減少 ARP 協(xié)議的通信頻率,加快網(wǎng)絡(luò)包的發(fā)送。該對(duì)應(yīng)關(guān)系,即 ARP 緩存表項(xiàng),其狀態(tài)機(jī)或整個(gè)生命周期可描述如下:
初始時(shí),對(duì)于任何網(wǎng)絡(luò)包發(fā)送時(shí),內(nèi)核協(xié)議棧需要找到目的 IP 地址對(duì)應(yīng)的對(duì)端 MAC 地址,如果這時(shí) ARP 緩存中沒有命中,則會(huì)新插入一條狀態(tài)為 Incomplete 的表項(xiàng)。Incomplete 狀態(tài)會(huì)嘗試發(fā)送 ARP 包,請(qǐng)求某 IP 地址對(duì)應(yīng)的 MAC 地址。
若收到 ARP 回應(yīng)的,表項(xiàng)狀態(tài)就變?yōu)?Reachable。
若嘗試了一定次數(shù)后沒收到響應(yīng),表項(xiàng)即變?yōu)?Failed。
Reachable 表項(xiàng)在到達(dá)超時(shí)時(shí)間后,會(huì)變成 Stale 狀態(tài),Stale 狀態(tài)的表項(xiàng)已不可再使用。
Stale 的表項(xiàng)若有被引用來發(fā)包,則表項(xiàng)會(huì)變?yōu)?Delay 狀態(tài)。
Delay 狀態(tài)的表項(xiàng)也不可使用來發(fā)包,但在 Delay 狀態(tài)到期前,收到 ARP 的本機(jī)確認(rèn),則重新轉(zhuǎn)為 Reachable 狀態(tài)。
Delay 狀態(tài)到期,表項(xiàng)變?yōu)?Probe 狀態(tài),該狀態(tài)與 Incomplete 狀態(tài)類似。
Stale 狀態(tài)到期后,會(huì)被啟動(dòng)的垃圾回收起回收刪除。
通過以下命令可查看當(dāng)前網(wǎng)絡(luò)命名空間(network namespace) 中 arp 表項(xiàng)及其狀態(tài):
ip neigh
如:
本機(jī)確認(rèn):這是代指本機(jī)收到了一個(gè)源 mac 地址匹配的網(wǎng)絡(luò)包,這個(gè)網(wǎng)絡(luò)包表示此次網(wǎng)絡(luò)通信的“上一跳”即是該 mac 地址的機(jī)器,能收到這個(gè)網(wǎng)絡(luò)包即說明該 mac 地址可達(dá)。因此即可把該表項(xiàng)轉(zhuǎn)為 Reachable 狀態(tài)。通過這一機(jī)制,內(nèi)核可減少 ARP 的通信需求。
以下列出了該機(jī)制中主要涉及的內(nèi)核參數(shù):
參數(shù) | 含義 | 默認(rèn)值 |
---|---|---|
/proc/sys/net/ipv4/neigh/default/base_reachable_time | Reachable 狀態(tài)基礎(chǔ)過期時(shí)間,每個(gè)表項(xiàng)過期時(shí)間是在[1/2base_reachable_time,3/2base_reachable_time]之間 | 30秒 |
/proc/sys/net/ipv4/neigh/default/base_reachable_time_ms | Reachable 狀態(tài)基礎(chǔ)過期時(shí)間,毫秒表示 | 30秒 |
/proc/sys/net/ipv4/neigh/default/gc_stale_time | Stale 狀態(tài)過期時(shí)間 | 60秒 |
/proc/sys/net/ipv4/neigh/default/delay_first_probe_time | delay 狀態(tài)過期到 Probe 的時(shí)間 | 5秒 |
/proc/sys/net/ipv4/neigh/default/gc_interval | gc 啟動(dòng)的周期時(shí)間 | 30秒 |
/proc/sys/net/ipv4/neigh/default/gc_thresh2 | 少于這個(gè)值,gc 不會(huì)啟動(dòng) | 2048 |
/proc/sys/net/ipv4/neigh/default/gc_thresh3 | ARP表的最多紀(jì)錄的軟限制,允許超過該數(shù)字5秒 | 4096 |
/proc/sys/net/ipv4/neigh/default/gc_thresh4 | ARP表的最多紀(jì)錄的硬限制,大于該數(shù)目,gc立即啟動(dòng),并強(qiáng)制回收 | 8192 |
其中,gc 相關(guān)的內(nèi)核參數(shù)是對(duì)**所有網(wǎng)卡(interface)**生效的。但是各種到期時(shí)間的設(shè)置是僅對(duì)單獨(dú)網(wǎng)卡(interface)生效的,default 值僅對(duì)新增接口設(shè)備生效。
由其緩存表項(xiàng)的狀態(tài)機(jī)我們知道,不是所有的表項(xiàng)都會(huì)被回收,只有 Stale 狀態(tài)過期后,F(xiàn)ailed 的表項(xiàng)可能會(huì)被回收。另外,ARP 緩存表項(xiàng)的垃圾回收是觸發(fā)式的,需要回收的表項(xiàng)不一定立刻會(huì)被回收,ARP 緩存表項(xiàng)的垃圾回收有四種啟動(dòng)邏輯:
arp 表項(xiàng)數(shù)量 < gc_thresh2,不啟動(dòng)。
gc_thresh2 =< arp 表項(xiàng)數(shù)量 <= gc_thresh3,按照 gc_interval 定期啟動(dòng)
gc_thresh3 < arp 表項(xiàng)數(shù)量 <= gc_thresh4,5秒后啟動(dòng)
arp 表項(xiàng)數(shù)量 > gc_thresh4,立即啟動(dòng)
對(duì)于不可回收的表項(xiàng),垃圾回收即便啟動(dòng)了也不會(huì)對(duì)其進(jìn)行回收。因此當(dāng)不可回收的表項(xiàng)數(shù)量大于 gc_thresh4 的時(shí)候,垃圾回收也無能為力了。
我們知道,每個(gè)獨(dú)立的網(wǎng)絡(luò)命名空間是有完整的網(wǎng)絡(luò)協(xié)議棧的。那么,ARP 緩存的垃圾回收也是每個(gè)命名空間單獨(dú)處理的嗎?
從涉及的內(nèi)核參數(shù)可以看出,gc 相關(guān)的內(nèi)核參數(shù)是對(duì)所有接口設(shè)備生效的,因此,這里可以推測(cè)垃圾回收的閾值也是子機(jī)級(jí)別生效的,而不是按網(wǎng)絡(luò)命名空間。
這里做了一個(gè)簡單的實(shí)驗(yàn)來驗(yàn)證:
在節(jié)點(diǎn) default ns 上的 gc_thresh2, gc_thresh3 和 gc_thresh4 設(shè)置成60 。
在節(jié)點(diǎn)上創(chuàng)建了 19 個(gè)獨(dú)立網(wǎng)卡模式的 Pod
任意選擇一個(gè) pod ping 其他的 pod,以此產(chǎn)生 arp 緩存
用 shell 腳本掃描節(jié)點(diǎn)上的所有 pod,計(jì)算 arp 表項(xiàng)的和,可以得到:
可以發(fā)現(xiàn), 各命名空間的累計(jì) arp 表項(xiàng)的數(shù)目在每次達(dá)到 60 之后就會(huì)快速下降,也就是達(dá)到 60 之后就產(chǎn)生了垃圾回收。重復(fù)幾次都是類似的結(jié)果,因此,這說明了垃圾回收在計(jì)算 ARP 表項(xiàng)是否觸發(fā)閾值時(shí),是計(jì)算各命名空間的累計(jì)值,也就是按子機(jī)級(jí)別生效,而非命名空間級(jí)別。
由前面的介紹我們知道,垃圾回收機(jī)制并非回收任意 ARP 緩存,因此,當(dāng)所有可達(dá)狀態(tài)的 ARP 表項(xiàng)打滿 ARP 緩存表時(shí),也即達(dá)到 gc_thresh4 時(shí),會(huì)發(fā)生什么行為?可以推測(cè),此時(shí)舊的無法回收,新的 ARP 表項(xiàng)也無法插入,新的網(wǎng)絡(luò)包會(huì)無法發(fā)送,也即發(fā)生了本次文章所描述的問題。
為了驗(yàn)證這一點(diǎn),繼續(xù)在以上環(huán)境中實(shí)驗(yàn):
將任意兩個(gè) Pod 的基礎(chǔ)老化時(shí)間 base_reachable_time 調(diào)長到 1800秒,以此產(chǎn)生不可回收的 ARP 表項(xiàng)。
設(shè)置 gc_thresh4 為 40,以此更容易觸發(fā)問題
選擇調(diào)整了老化時(shí)間的 pod ping 其他的 pod,以此產(chǎn)生 arp 緩存。
可以發(fā)現(xiàn),當(dāng)?shù)竭_(dá)閾值的時(shí)候,ping 會(huì)產(chǎn)生丟包或不通:
查看內(nèi)核日志 dmesg -T,可以看到文章開頭描述的信息:neighbour: arp_cache: neighbor table overflow!
以上實(shí)驗(yàn)說明了,不可回收的 ARP 表項(xiàng)打滿 ARP 表會(huì)讓新的表項(xiàng)無法插入,從而網(wǎng)絡(luò)不通。
要回答這個(gè)問題,我們先簡單看一下 TKE 各網(wǎng)絡(luò)模式的原理介紹
該網(wǎng)絡(luò)模式下,每個(gè)節(jié)點(diǎn)上的容器 IP 是預(yù)先分配到節(jié)點(diǎn)上的,這些 IP 同屬一個(gè)子網(wǎng),且每個(gè)節(jié)點(diǎn)就是一個(gè)小子網(wǎng)。我們知道,ARP 協(xié)議是為二層通信服務(wù)的,因此,該網(wǎng)絡(luò)方案中,每個(gè) Pod 的網(wǎng)絡(luò)命名空間內(nèi)的 ARP 表最大可能保存了節(jié)點(diǎn)上所有其他 Pod 的 ARP 表項(xiàng),最后節(jié)點(diǎn)的 ARP 表項(xiàng)的數(shù)量最大即為 節(jié)點(diǎn)子網(wǎng) IP 數(shù)的平方,如節(jié)點(diǎn)的子網(wǎng)大小是128,則其 ARP 表項(xiàng)最大可能為 127 的平方,約 16000。
該網(wǎng)絡(luò)模式下,每個(gè)節(jié)點(diǎn)會(huì)綁定輔助彈性網(wǎng)卡,節(jié)點(diǎn)上的 Pod 共享使用該輔助網(wǎng)卡,每個(gè) Pod 內(nèi)不會(huì)做網(wǎng)絡(luò)包的路由,只會(huì)有一條 ARP 表項(xiàng),實(shí)際的路由控制在節(jié)點(diǎn)的 default 命名空間內(nèi)完成。因此,該網(wǎng)絡(luò)模式下,ARP 緩存表幾乎是共享的,又因?yàn)榫W(wǎng)卡只能屬于 1 個(gè)子網(wǎng),因此每個(gè)節(jié)點(diǎn)的 Pod ARP 緩存表只能存儲(chǔ)一個(gè)子網(wǎng)的 IP-MAC 映射關(guān)系,至多數(shù)量為各網(wǎng)卡所在子網(wǎng)內(nèi) IP 的數(shù)量和,如子網(wǎng)是 /22,即含有約 1000 個(gè) ip, 那么 arp 表項(xiàng)也大概有 1000,由于節(jié)點(diǎn)網(wǎng)卡配額一般不超過 10,因此該節(jié)點(diǎn)的最大 ARP 表項(xiàng)一般不超過 10000。
獨(dú)立網(wǎng)卡模式是 TKE 團(tuán)隊(duì)推出的下一代“零損耗”容器網(wǎng)絡(luò)方案,其基本原理如下圖所示:
即母機(jī)虛擬出的彈性網(wǎng)卡,直接置于容器中,使容器獲得與 CVM 子機(jī)一樣的網(wǎng)絡(luò)通信能力和網(wǎng)絡(luò)管理能力,大大提升了容器網(wǎng)絡(luò)的數(shù)據(jù)面能力,真正做到“零損耗”。
目前,獨(dú)立網(wǎng)卡網(wǎng)絡(luò)方案已在 TKE 產(chǎn)品中開放白名單測(cè)試,歡迎內(nèi)外部客戶體驗(yàn)試用。
以上網(wǎng)絡(luò)方案中,每個(gè) Pod 都會(huì)獨(dú)占一個(gè)網(wǎng)卡,也會(huì)擁有獨(dú)立的命名空間和獨(dú)立的 ARP 緩存表。而每個(gè)網(wǎng)卡都可以屬于不同的子網(wǎng)。因此,在獨(dú)立網(wǎng)卡模式里,ARP 緩存表項(xiàng)數(shù)量至多為同可用區(qū)的子網(wǎng) IP 數(shù)量之和。這一數(shù)量量級(jí)是可以很輕易上萬的,很容易就突破了默認(rèn)的 ARP 緩存設(shè)置。也就觸發(fā)了這個(gè)問題。
從以上的分析可以看出,這個(gè)問題,調(diào)大垃圾回收的閾值,可以比較好的解決問題。因此,臨時(shí)的解決方案,就是調(diào)大 ARP 緩存表的垃圾回收閾值:
echo 8192 > /proc/sys/net/ipv4/neigh/default/gc_thresh2echo 16384 > /proc/sys/net/ipv4/neigh/default/gc_thresh3echo 32768 > /proc/sys/net/ipv4/neigh/default/gc_thresh4
ARP 緩存打滿之后,Pod 就會(huì)網(wǎng)絡(luò)不通。初看起來很簡單,但是其背后的 ARP 緩存老化和垃圾回收機(jī)制也是比較復(fù)雜的。查詢了很多資料,但是都對(duì)“垃圾回收閾值是對(duì)各命名空間的 ARP 表項(xiàng)累積值生效還是單獨(dú)生效”,“垃圾回收會(huì)回收哪些表項(xiàng)”,“表項(xiàng)打滿后的具體行為如何”等問題說不清、道不明。因此,筆者嘗試通過幾個(gè)小實(shí)驗(yàn)驗(yàn)證了具體的行為模式。相比直接閱讀晦澀的內(nèi)核源碼,實(shí)驗(yàn)法也許也是一個(gè)研究問題和理解機(jī)制的捷徑了。希望能夠幫助到各位讀者。
關(guān)于TKE容器網(wǎng)絡(luò)中的ARP Overflow問題探究及其解決方法是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。