做者朱瑜堅,騰訊雲後臺開發工程師,熟悉 CNI 容器網絡相關技術,負責騰訊雲 TKE 的容器網絡的構建和相關網絡組件的開發維護工做,做爲主力開發實現了 TKE 下一代容器網絡方案。shell
最近,某內部客戶的 TKE VPC-CNI 模式的獨立網卡集羣上出現了 pod 間訪問不通的狀況,問題 pod ping 不通任何其餘 pod 和節點。緩存
查看 dmesg 內核日誌,有以下報錯信息:neighbour: arp_cache: neighbor table overflow!(下圖爲後續復現的日誌截圖)網絡
而且,這個集羣規模較大,約有 1000 個節點,30000 個 pod,基本能夠懷疑是因爲集羣規模較大,致使 ARP 表項過多,從而引發 ARP Overflow 的問題。數據結構
名詞 | 說明 |
---|---|
TKE | 全稱 Tencent Kubernetes Engine, 騰訊雲容器服務,是基於原生 kubernetes 提供以容器爲核心的、高度可擴展的高性能容器管理服務 |
VPC-CNI 模式 | 是容器服務 TKE 基於 CNI 和 VPC 彈性網卡實現的容器網絡能力 |
Pod | Pod 是 kubernetes 的基本資源管理單位,擁有獨立的網絡命名空間,1個 Pod 可包含多個容器 |
從如上報錯信息可知,這個問題的基本緣由在於 ARP 緩存表打滿了。這裏涉及到內核的 ARP 緩存垃圾回收機制。當 ARP 表項太多且又沒有可回收的表項的時候,新表項就會沒法插入。性能
這就致使網絡包發送時沒法找到對應的硬件地址(MAC)。使得網絡包不能發送。測試
那麼具體什麼狀況會致使新表項沒法插入呢?回答這個問題,咱們須要先深刻了解一下 ARP 緩存老化及垃圾回收機制。spa
如上圖,是整個 ARP 表項的生命週期及其狀態機。日誌
咱們知道,對於 TCP/IP 網絡包發送時,網絡棧須要對端的 MAC 地址才能讓網絡包轉換成二層的數據結構——幀,從而在網絡中傳輸。而對於不一樣廣播域的 IP 地址,其對端 MAC 地址爲網關,發送端會將網絡包發給網關讓其轉發,而對於同廣播域中的 IP 地址,其對端 MAC 地址即與 IP 地址對應。code
而經過 IP 地址找到 MAC 地址就是 ARP 協議的主要工做內容。ARP 協議的工做過程此處再也不贅述,而經過 ARP 協議找到 IP 地址對應的 MAC 地址後,會將該對應關係存儲在本機上一段時間,以減小 ARP 協議的通訊頻率,加快網絡包的發送。該對應關係,即 ARP 緩存表項,其狀態機或整個生命週期可描述以下:blog
經過如下命令可查看當前網絡命名空間(network namespace) 中 arp 表項及其狀態:
ip neigh
如:
本機確認:這是代指本機收到了一個源 mac 地址匹配的網絡包,這個網絡包表示這次網絡通訊的「上一跳」便是該 mac 地址的機器,能收到這個網絡包即說明該 mac 地址可達。所以便可把該表項轉爲 Reachable 狀態。經過這一機制,內核可減小 ARP 的通訊需求。
如下列出了該機制中主要涉及的內核參數:
參數 | 含義 | 默認值 |
---|---|---|
/proc/sys/net/ipv4/neigh/default/base_reachable_time | Reachable 狀態基礎過時時間,每一個表項過時時間是在[1/2base_reachable_time,3/2base_reachable_time]之間 | 30秒 |
/proc/sys/net/ipv4/neigh/default/base_reachable_time_ms | Reachable 狀態基礎過時時間,毫秒錶示 | 30秒 |
/proc/sys/net/ipv4/neigh/default/gc_stale_time | Stale 狀態過時時間 | 60秒 |
/proc/sys/net/ipv4/neigh/default/delay_first_probe_time | delay 狀態過時到 Probe 的時間 | 5秒 |
/proc/sys/net/ipv4/neigh/default/gc_interval | gc 啓動的週期時間 | 30秒 |
/proc/sys/net/ipv4/neigh/default/gc_thresh1 | 少於這個值,gc 不會啓動 | 2048 |
/proc/sys/net/ipv4/neigh/default/gc_thresh2 | ARP表的最多紀錄的軟限制,容許超過該數字5秒 | 4096 |
/proc/sys/net/ipv4/neigh/default/gc_thresh3 | ARP表的最多紀錄的硬限制,大於該數目,gc當即啓動,並強制回收 | 8192 |
其中,gc 相關的內核參數是對全部網卡(interface)生效的。可是各類到期時間的設置是僅對單獨網卡(interface)生效的,default 值僅對新增接口設備生效。
由其緩存表項的狀態機咱們知道,不是全部的表項都會被回收,只有 Stale 狀態過時後,Failed 的表項可能會被回收。另外,ARP 緩存表項的垃圾回收是觸發式的,須要回收的表項不必定馬上會被回收,ARP 緩存表項的垃圾回收有四種啓動邏輯:
對於不可回收的表項,垃圾回收即使啓動了也不會對其進行回收。所以當不可回收的表項數量大於 gc_thresh3 的時候,垃圾回收也無能爲力了。
咱們知道,每一個獨立的網絡命名空間是有完整的網絡協議棧的。那麼,ARP 緩存的垃圾回收也是每一個命名空間單獨處理的嗎?
從涉及的內核參數能夠看出,gc 相關的內核參數是對全部接口設備生效的,所以,這裏能夠推測垃圾回收的閾值也是子機級別生效的,而不是按網絡命名空間。
這裏作了一個簡單的實驗來驗證:
能夠發現, 各命名空間的累計 arp 表項的數目在每次達到 60 以後就會快速降低,也就是達到 60 以後就產生了垃圾回收。重複幾回都是相似的結果,所以,這說明了垃圾回收在計算 ARP 表項是否觸發閾值時,是計算各命名空間的累計值,也就是按子機級別生效,而非命名空間級別。
由前面的介紹咱們知道,垃圾回收機制並不是回收任意 ARP 緩存,所以,當全部可達狀態的 ARP 表項打滿 ARP 緩存表時,也即達到 gc_thresh3 時,會發生什麼行爲?能夠推測,此時舊的沒法回收,新的 ARP 表項也沒法插入,新的網絡包會沒法發送,也即發生了本次文章所描述的問題。
爲了驗證這一點,繼續在以上環境中實驗:
查看內核日誌 dmesg -T,能夠看到文章開頭描述的信息:neighbour: arp_cache: neighbor table overflow!
以上實驗說明了,不可回收的 ARP 表項打滿 ARP 表會讓新的表項沒法插入,從而網絡不通。
要回答這個問題,咱們先簡單看一下 TKE 各網絡模式的原理介紹
該網絡模式下,每一個節點上的容器 IP 是預先分配到節點上的,這些 IP 同屬一個子網,且每一個節點就是一個小子網。咱們知道,ARP 協議是爲二層通訊服務的,所以,該網絡方案中,每一個 Pod 的網絡命名空間內的 ARP 表最大可能保存了節點上全部其餘 Pod 的 ARP 表項,最後節點的 ARP 表項的數量最大即爲 節點子網 IP 數的平方,如節點的子網大小是128,則其 ARP 表項最大可能爲 127 的平方,約 16000。
該網絡模式下,每一個節點會綁定輔助彈性網卡,節點上的 Pod 共享使用該輔助網卡,每一個 Pod 內不會作網絡包的路由,只會有一條 ARP 表項,實際的路由控制在節點的 default 命名空間內完成。所以,該網絡模式下,ARP 緩存表幾乎是共享的,又由於網卡只能屬於 1 個子網,所以每一個節點的 Pod ARP 緩存表只能存儲一個子網的 IP-MAC 映射關係,至多數量爲各網卡所在子網內 IP 的數量和,如子網是 /22,即含有約 1000 個 ip, 那麼 arp 表項也大概有 1000,因爲節點網卡配額通常不超過 10,所以該節點的最大 ARP 表項通常不超過 10000。
獨立網卡模式是 TKE 團隊推出的下一代「零損耗」容器網絡方案,其基本原理以下圖所示:
即母機虛擬出的彈性網卡,直接置於容器中,使容器得到與 CVM 子機同樣的網絡通訊能力和網絡管理能力,大大提高了容器網絡的數據面能力,真正作到「零損耗」。
目前,獨立網卡網絡方案已在 TKE 產品中開放白名單測試,歡迎內外部客戶體驗試用。
以上網絡方案中,每一個 Pod 都會獨佔一個網卡,也會擁有獨立的命名空間和獨立的 ARP 緩存表。而每一個網卡均可以屬於不一樣的子網。所以,在獨立網卡模式裏,ARP 緩存表項數量至多爲同可用區的子網 IP 數量之和。這一數量量級是能夠很輕易上萬的,很容易就突破了默認的 ARP 緩存設置。也就觸發了這個問題。
從以上的分析能夠看出,這個問題,調大垃圾回收的閾值,能夠比較好的解決問題。所以,臨時的解決方案,就是調大 ARP 緩存表的垃圾回收閾值:
echo 8192 > /proc/sys/net/ipv4/neigh/default/gc_thresh1echo 16384 > /proc/sys/net/ipv4/neigh/default/gc_thresh2echo 32768 > /proc/sys/net/ipv4/neigh/default/gc_thresh3
ARP 緩存打滿以後,Pod 就會網絡不通。初看起來很簡單,可是其背後的 ARP 緩存老化和垃圾回收機制也是比較複雜的。查詢了不少資料,可是都對「垃圾回收閾值是對各命名空間的 ARP 表項累積值生效仍是單獨生效」,「垃圾回收會回收哪些表項」,「表項打滿後的具體行爲如何」等問題說不清、道不明。所以,筆者嘗試經過幾個小實驗驗證了具體的行爲模式。相比直接閱讀晦澀的內核源碼,實驗法也許也是一個研究問題和理解機制的捷徑了。但願可以幫助到各位讀者。
【騰訊雲原生】雲說新品、雲研新術、雲遊新活、雲賞資訊,掃碼關注同名公衆號,及時獲取更多幹貨!!