<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          容器網(wǎng)絡(luò)|深入理解Cilium

          共 10130字,需瀏覽 21分鐘

           ·

          2022-02-12 23:02


          本文翻譯自 2019 年 DigitalOcean 的工程師 Nate Sweet 在 KubeCon 的一篇分享:

          Understanding (and Troubleshooting) the eBPF Datapath in Cilium 。

          由于水平有限,本文不免存在遺漏或錯誤之處。如有疑問,請查閱原文。


          • 1 為什么要關(guān)注 eBPF?

            • 1.1 網(wǎng)絡(luò)成為瓶頸

            • 1.2 eBPF 無處不在

            • 1.3 性能就是金錢

          • 2 eBPF 是什么?

          • 3 為什么 eBPF 如此強(qiáng)大?

            • 3.1 快速

            • 3.2 靈活

            • 3.3 數(shù)據(jù)與功能分離

          • 4 eBPF 簡史

          • 5 Cilium 是什么,為什么要關(guān)注它?

          • 6 內(nèi)核數(shù)據(jù)通路?datapath

          • 7 Kubernets、Cilium 和 Kernel:原子對象對應(yīng)關(guān)系


          1.1 網(wǎng)絡(luò)成為瓶頸

          大家已經(jīng)知道網(wǎng)絡(luò)成為瓶頸,但我是從下面這個角度考慮的:近些年業(yè)界使用網(wǎng)絡(luò)的方式 ,使其成為瓶頸(it is the bottleneck in a way that is actually pretty recent) 。

          • 網(wǎng)絡(luò)一直都是 I/O 密集型的,但直到最近,這件事情才變得尤其重要。

          • 分布式任務(wù)(workloads)業(yè)界一直都在用,但直到近些年,這種模型才成為主流。?雖然何時成為主流眾說紛紜,但我認(rèn)為最早不會早于 90 年代晚期。

          • 公有云的崛起,我認(rèn)為可能是網(wǎng)絡(luò)成為瓶頸的最主要原因。

          這種情況下,用于管理依賴和解決瓶頸的工具都已經(jīng)過時了。

          但像 eBPF 這樣的技術(shù)使得網(wǎng)絡(luò)調(diào)優(yōu)和整流(tune and shape this traffic)變得簡單很多。?eBPF 提供的許多能力是其他工具無法提供的,或者即使提供了,其代價也要比 eBPF 大 的多

          1.2 eBPF 無處不在

          eBPF 正在變得無處不在,我們可能會爭論這到底是一件好事還是壞事(eBPF 也確實帶了一 些安全問題),但當(dāng)前無法忽視的事實是:Linux 內(nèi)核的網(wǎng)絡(luò)開發(fā)者們正在將 eBPF 應(yīng)用 于各種地方(putting it everywhere)。其結(jié)果是,eBPF 與內(nèi)核的默認(rèn)收發(fā)包路徑( datapath)耦合得越來越緊(more and more tightly coupled with the default datapath)。

          1.3 性能就是金錢

          “Metrics are money”, 這是今年 Paris Kernel Recipes 峰會上,來自 Synthesio 的 Aurelian Rougemont 的 精彩分享。

          他展示了一些史詩級的調(diào)試(debugging)案例,感興趣的可以去看看;但更重要的是,他 從更高層次提出了這樣一個觀點(diǎn):理解這些東西是如何工作的,最終會產(chǎn)生資本收益( understanding how this stuff works translates to money)。為客戶節(jié)省金錢,為 自己帶來收入。

          如果你能從更少的資源中榨取出更高的性能,使軟件運(yùn)行更快,那 顯然你對公司的貢獻(xiàn)就更大。Cilium 就是這樣一個能讓你帶來更大價值的工具。

          在進(jìn)一步討論之前,我先簡要介紹一下 eBPF 是什么,以及為什么它如此強(qiáng)大。

          BPF 程序有多種類型,圖 2.1 是其中一種,稱為 XDP BPF 程序。

          • XDP 是?eXpress DataPath(特快數(shù)據(jù)路徑)。

          • XDP 程序可以直接加載到網(wǎng)絡(luò)設(shè)備上。

          • XDP 程序在數(shù)據(jù)包收發(fā)路徑上很前面的位置就開始執(zhí)行,下面會看到例子。

          BPF 程序開發(fā)方式:

          1. 編寫一段 BPF 程序

          2. 編譯這段 BPF 程序

          3. 用一個特殊的系統(tǒng)調(diào)用將編譯后的代碼加載到內(nèi)核

          這實際上就是編寫了一段內(nèi)核代碼,并動態(tài)插入到了內(nèi)核(written kernel code and dynamically inserted it into the kernel)。

          圖 2.1. eBPF 代碼示例:丟棄源 IP 命中黑名單的 ARP 包

          圖 2.1 中的程序使用了一種稱為?map?的東西,這是一種特殊的數(shù)據(jù)結(jié)構(gòu),可用于?在內(nèi)核和用戶態(tài)之間傳遞數(shù)據(jù),例如通過一個特殊的系統(tǒng)從用戶態(tài)向 map 里插入數(shù)據(jù)。

          這段程序的功能:丟棄所有源 IP 命中黑名單的 ARP 包。右側(cè)四個框內(nèi)的代碼功能:

          1. 初始化以太幀結(jié)構(gòu)體(ethernet packet)。

          2. 如果不是 ARP 包,直接退出,將包交給內(nèi)核繼續(xù)處理。

          3. 至此已確定是 ARP,因此初始化一個 ARP 數(shù)據(jù)結(jié)構(gòu),對包進(jìn)行下一步處理。例 如,提取出 ARP 中的源 IP,去之前創(chuàng)建好的黑名單中查詢該 IP 是否存在。

          4. 如果存在,返回丟棄判決(XDP_DROP);否則,返回允許通行判決(?XDP_PASS),內(nèi)核會進(jìn)行后續(xù)處理。

          你可能不會相信,就這樣一段簡單的程序,會讓服務(wù)器性能產(chǎn)生質(zhì)的飛躍,因為它此時已 經(jīng)擁有了一條極為高效的網(wǎng)絡(luò)路徑(an extremely efficient network path)。

          三方面原因:

          1. 快速(fast)

          2. 靈活(flexible)

          3. 數(shù)據(jù)與功能分離(separates data from functionality)


          3.1 快速

          eBPF 幾乎總是比 iptables 快,這是有技術(shù)原因的。

          • eBPF 程序本身并不比 iptables 快,但 eBPF 程序更短。

          • iptables 基于一個非常龐大的內(nèi)核框架(Netfilter),這個框架出現(xiàn)在內(nèi)核 datapath 的多個地方,有很大冗余。

          因此,同樣是實現(xiàn) ARP drop 這樣的功能,基于 iptables 做冗余就會非常大,導(dǎo)致性能很低。

          3.2 靈活

          這可能是最主要的原因。你可以用 eBPF 做幾乎任何事情。

          eBPF 基于內(nèi)核提供的一組接口,運(yùn)行 JIT 編譯的字節(jié)碼,并將計算結(jié)果返回給內(nèi)核。例如?內(nèi)核只關(guān)心 XDP 程序的返回是 PASS, DROP 還是 REDIRECT。至于在 XDP 程序里做什么, 完全看你自己。

          3.3 數(shù)據(jù)與功能分離

          eBPF separates data from functionality.

          nftables?和?iptables?也能干這個事情,但功能沒有 eBPF 強(qiáng)大。例如,eBPF 可以使 用 per-cpu 的數(shù)據(jù)結(jié)構(gòu),因此能取得更極致的性能。

          eBPF 真正的優(yōu)勢是將“數(shù)據(jù)與功能分離”這件事情做地非常干凈(clean separation):可以在 eBPF 程序不中斷的情況下修改它的運(yùn)行方式。具體方式是修改它訪 問的配置數(shù)據(jù)或應(yīng)用數(shù)據(jù),例如黑名單里規(guī)定的 IP 列表和域名。

          這里是簡單介紹幾句,后面 datapath 才是重點(diǎn)。

          兩篇論文,可讀性還是比較好的,感興趣的自行閱讀:

          • Steven McCanne, et al, in 1993 -?The BSD Packet Filter

          • Jeffrey C. Mogul, et al, in 1987 - first open source implementation of a packet filter.

          我認(rèn)為理解 eBPF 代碼還比較簡單,多看看內(nèi)核代碼就行了,但配置和編寫 eBPF 就要難多了。

          Cilium 是一個很好的 eBPF 之上的通用抽象,覆蓋了分布式系統(tǒng)的絕大多數(shù)場景。Cilium 封裝了 eBPF,提供一個更上層的 API。如果你使用的是 Kubernetes,那你至少應(yīng)該聽說過 Cilium。

          Cilium 提供了 CNI 和 kube-proxy replacement 功能,相比 iptables 性能要好很多。

          接下來開始進(jìn)入本文重點(diǎn)。

          本節(jié)將介紹數(shù)據(jù)包是如何穿過 network datapath(網(wǎng)絡(luò)數(shù)據(jù)路徑)的:包括從硬件到 內(nèi)核,再到用戶空間。

          這里將只介紹?Cilium 所使用的 eBPF 程序,其中有 Cilium logo 的地方,都是 datapath 上 Cilium 重度使用 BPF 程序的地方。

          本文不會過多介紹硬件相關(guān)內(nèi)容,因為理解 eBPF 基本不需要硬件知識,但顯然理解了硬件 原理也并無壞處。另外,由于時間限制,我將只討論接收部分。

          6.1 L1 -> L2(物理層 -> 數(shù)據(jù)鏈路層)


          網(wǎng)卡收包簡要流程:

          1. 網(wǎng)卡驅(qū)動初始化。

            1. 網(wǎng)卡獲得一塊物理內(nèi)存,作用收發(fā)包的緩沖區(qū)(ring-buffer)。這種方式稱為 DMA(直接內(nèi)存訪問)。

            2. 驅(qū)動向內(nèi)核 NAPI(New API)注冊一個輪詢(poll )方法。

          2. 網(wǎng)卡從云上收到一個包,將包放到 ring-buffer。

          3. 如果此時 NAPI 沒有在執(zhí)行,網(wǎng)卡就會觸發(fā)一個硬件中斷(HW IRQ),告訴處理器 DMA 區(qū)域中有包等待處理。

          4. 收到硬中斷信號后,處理器開始執(zhí)行 NAPI。

          5. NAPI 執(zhí)行網(wǎng)卡注冊的 poll 方法開始收包。

          關(guān)于 NAPI poll 機(jī)制:

          • 這是 Linux 內(nèi)核中的一種通用抽象,任何等待不可搶占狀態(tài)發(fā)生(wait for a preemptible state to occur)的模塊,都可以使用這種注冊回調(diào)函數(shù)的方式。

          • 驅(qū)動注冊的這個 poll 是一個主動式 poll(active poll),一旦執(zhí)行就會持續(xù)處理 ,直到?jīng)]有數(shù)據(jù)可供處理,然后進(jìn)入 idle 狀態(tài)。

          • 在這里,執(zhí)行 poll 方法的是運(yùn)行在某個或者所有 CPU 上的內(nèi)核線程(kernel thread)。?雖然這個線程沒有數(shù)據(jù)可處理時會進(jìn)入 idle 狀態(tài),但如前面討論的,在當(dāng)前大部分分布 式系統(tǒng)中,這個線程大部分時間內(nèi)都是在運(yùn)行的,不斷從驅(qū)動的 DMA 區(qū)域內(nèi)接收數(shù)據(jù)包。

          • poll 會告訴網(wǎng)卡不要再觸發(fā)硬件中斷,使用軟件中斷(softirq)就行了。此后這些 內(nèi)核線程會輪詢網(wǎng)卡的 DMA 區(qū)域來收包。之所以會有這種機(jī)制,是因為硬件中斷代價太 高了,因為它們比系統(tǒng)上幾乎所有東西的優(yōu)先級都要高。

          我們接下來還將多次看到這個廣義的 NAPI 抽象,因為它不僅僅處理驅(qū)動,還能處理許多 其他場景。內(nèi)核用 NAPI 抽象來做驅(qū)動讀取(driver reads)、epoll 等等。

          NAPI 驅(qū)動的 poll 機(jī)制將數(shù)據(jù)從 DMA 區(qū)域讀取出來,對數(shù)據(jù)做一些準(zhǔn)備工作,然后交給比 它更上一層的內(nèi)核協(xié)議棧。

          6.2 L2 續(xù)(數(shù)據(jù)鏈路層 - 續(xù))

          同樣,這里不會深入展開驅(qū)動層做的事情,而主要關(guān)注內(nèi)核所做的一些更上層的事情,例如

          • 分配 socket buffers(skb)

          • BPF

          • iptables

          • 將包送到網(wǎng)絡(luò)棧(network stack)和用戶空間

          Step 1:NAPI poll

          首先,NAPI poll 機(jī)制不斷調(diào)用驅(qū)動實現(xiàn)的 poll 方法,后者處理 RX 隊列內(nèi)的包,并最終 將包送到正確的程序。這就到了我們前面的 XDP 類型程序。

          Step 2:XDP 程序處理

          如果驅(qū)動支持 XDP,那 XDP 程序?qū)⒃?poll 機(jī)制內(nèi)執(zhí)行。如果不支持,那 XDP 程序?qū)⒅荒?strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">在更后面執(zhí)行(run significantly upstack,見 Step 6),性能會變差, 因此確定你使用的網(wǎng)卡是否支持 XDP 非常重要。

          XDP 程序返回一個判決結(jié)果給驅(qū)動,可以是 PASS, TRANSMIT, 或 DROP。

          • Transmit 非常有用,有了這個功能,就可以用 XDP?實現(xiàn)一個 TCP/IP 負(fù)載均衡器。XDP 只適合對包進(jìn)行較小修改,如果是大動作修改,那這樣的 XDP 程序的性能 可能并不會很高,因為這些操作會降低 poll 函數(shù)處理 DMA ring-buffer 的能力。

          • 更有趣的是 DROP 方法,因為一旦判決為 DROP,這個包就可以直接原地丟棄了,而 無需再穿越后面復(fù)雜的協(xié)議棧然后再在某個地方被丟棄,從而節(jié)省了大量資源。如果本次 分享我只能給大家一個建議,那這個建議就是:在 datapath 越前面做 tuning 和 dropping 越好,這會顯著增加系統(tǒng)的網(wǎng)絡(luò)吞吐。

          • 如果返回是 PASS,內(nèi)核會繼續(xù)沿著默認(rèn)路徑處理包,到達(dá)?clean_rx()?方法。

          Step 3clean_rx():創(chuàng)建 skb

          如果返回是 PASS,內(nèi)核會繼續(xù)沿著默認(rèn)路徑處理包,到達(dá)?clean_rx()?方法。

          這個方法創(chuàng)建一個 socket buffer(skb)對象,可能還會更新一些統(tǒng)計信息,對 skb 進(jìn)行硬件校驗和檢查,然后將其交給?gro_receive()?方法。

          Step 4gro_receive()

          GRO 是一種較老的硬件特性(LRO)的軟件實現(xiàn),功能是對分片的包進(jìn)行重組然后交給更 上層,以提高吞吐。

          GRO 給協(xié)議棧提供了一次將包交給網(wǎng)絡(luò)協(xié)議棧之前,對其檢查校驗和 、修改協(xié)議頭和發(fā)送應(yīng)答包(ACK packets)的機(jī)會。

          1. 如果 GRO 的 buffer 相比于包太小了,它可能會選擇什么都不做。

          2. 如果當(dāng)前包屬于某個更大包的一個分片,調(diào)用?enqueue_backlog?將這個分片放到某個 CPU 的包隊列。當(dāng)包重組完成后,會交給?receive_skb()?方法處理。

          3. 如果當(dāng)前包不是分片包,直接調(diào)用?receive_skb(),進(jìn)行一些網(wǎng)絡(luò)棧最底層的處理。

          Step 5receive_skb()

          receive_skb()?之后會再次進(jìn)入 XDP 程序點(diǎn)。

          6.3 L2 -> L3(數(shù)據(jù)鏈路層 -> 網(wǎng)絡(luò)層)

          Step 6:通用 XDP 處理(gXDP)

          receive_skb()?之后,我們又來到了另一個 XDP 程序執(zhí)行點(diǎn)。這里可以通過?receive_xdp()?做一些通用(generic)的事情,因此我在圖中將其標(biāo)注為?(g)XDP

          Step 2 中提到,如果網(wǎng)卡驅(qū)動不支持 XDP,那 XDP 程序?qū)⒀舆t到更后面執(zhí)行,這個?“更后面”的位置指的就是這里的?(g)XDP

          Step 7:Tap 設(shè)備處理

          圖中有個?*check_taps?框,但其實并沒有這個方法:receive_skb()?會輪詢所有的 socket tap,將包放到正確的 tap 設(shè)備的緩沖區(qū)。

          tap 設(shè)備監(jiān)聽的是三層協(xié)議(L3 protocols),例如 IPv4、ARP、IPv6 等等。如果 tap 設(shè) 備存在,它就可以操作這個 skb 了。

          Step 8tc(traffic classifier)處理

          接下來我們遇到了第二種 eBPF 程序:tc eBPF。

          tc(traffic classifier,流量分類器)是 Cilium 依賴的最基礎(chǔ)的東西,它提供了多種功 能,例如修改包(mangle,給 skb 打標(biāo)記)、重路由(reroute)、丟棄包(drop),這 些操作都會影響到內(nèi)核的流量統(tǒng)計,因此也影響著包的排隊規(guī)則(queueing discipline )。

          Cilium 控制的網(wǎng)絡(luò)設(shè)備,至少被加載了一個 tc eBPF 程序。

          譯者注:如何查看已加載的 eBPF 程序,可參考 Cilium Network Topology and Traffic Path on AWS。

          Step 9:Netfilter 處理

          如果 tc BPF 返回 OK,包會再次進(jìn)入 Netfilter。

          Netfilter 也會對入向的包進(jìn)行處理,這里包括?nftables?和?iptables?模塊。

          有一點(diǎn)需要記住的是:Netfilter 是網(wǎng)絡(luò)棧的下半部分(the “bottom half” of the network stack),因此 iptables 規(guī)則越多,給網(wǎng)絡(luò)棧下半部分造成的瓶頸就越大。

          *def_dev_protocol?框是二層過濾器(L2 net filter),由于 Cilium 沒有用到任何 L2 filter,因此這里我就不展開了。

          Step 10:L3 協(xié)議層處理:ip_rcv()

          最后,如果包沒有被前面丟棄,就會通過網(wǎng)絡(luò)設(shè)備的?ip_rcv()?方法進(jìn)入?yún)f(xié)議棧的三層( L3)—— 即 IP 層 —— 進(jìn)行處理。

          接下來我們將主要關(guān)注這個函數(shù),但這里需要提醒大家的是,Linux 內(nèi)核也支持除了 IP 之 外的其他三層協(xié)議,它們的 datapath 會與此有些不同。

          6.4 L3 -> L4(網(wǎng)絡(luò)層 -> 傳輸層)

          Step 11:Netfilter L4 處理

          ip_rcv()?做的第一件事情是再次執(zhí)行 Netfilter 過濾,因為我們現(xiàn)在是從四層(L4)的 視角來處理 socker buffer。因此,這里會執(zhí)行 Netfilter 中的任何四層規(guī)則(L4 rules )。

          Step 12ip_rcv_finish()?處理

          Netfilter 執(zhí)行完成后,調(diào)用回調(diào)函數(shù)?ip_rcv_finish()。

          ip_rcv_finish()?立即調(diào)用?ip_routing()?對包進(jìn)行路由判斷。

          Step 13ip_routing()?處理

          ip_routing()?對包進(jìn)行路由判斷,例如看它是否是在 lookback 設(shè)備上,是否能 路由出去(could egress),或者能否被路由,能否被 unmangle 到其他設(shè)備等等。

          在 Cilium 中,如果沒有使用隧道模式(tunneling),那就會用到這里的路由功能。相比 隧道模式,路由模式會的 datapath 路徑更短,因此性能更高。

          Step 14:目的是本機(jī):ip_local_deliver()?處理

          根據(jù)路由判斷的結(jié)果,如果包的目的端是本機(jī),會調(diào)用?ip_local_deliver()?方法。

          ip_local_deliver()?會調(diào)用?xfrm4_policy()。

          Step 15xfrm4_policy()?處理

          xfrm4_policy()?完成對包的封裝、解封裝、加解密等工作。例如,IPSec 就是在這里完成的。

          最后,根據(jù)四層協(xié)議的不同,ip_local_deliver()?會將最終的包送到 TCP 或 UDP 協(xié)議 棧。這里必須是這兩種協(xié)議之一,否則設(shè)備會給源 IP 地址回一個?ICMP destination unreachable?消息。

          接下來我將拿 UDP 協(xié)議作為例子,因為 TCP 狀態(tài)機(jī)太復(fù)雜了,不適合這里用于理解 datapath 和數(shù)據(jù)流。但不是說 TCP 不重要,Linux TCP 狀態(tài)機(jī)還是非常值得好好學(xué)習(xí)的。

          6.5 L4(傳輸層,以 UDP 為例)

          Step 16udp_rcv()?處理

          udp_rcv()?對包的合法性進(jìn)行驗證,檢查 UDP 校驗和。然后,再次將包送到?xfrm4_policy()?進(jìn)行處理。

          Step 17xfrm4_policy()?再次處理

          這里再次對包執(zhí)行 transform policies 是因為,某些規(guī)則能指定具體的四層協(xié)議,所以只 有到了協(xié)議層之后才能執(zhí)行這些策略。

          Step 18:將包放入?socket_receive_queue

          這一步會拿端口(port)查找相應(yīng)的 socket,然后將 skb 放到一個名為?socket_receive_queue?的鏈表。

          Step 19:通知 socket 收數(shù)據(jù):sk_data_ready()

          最后,udp_rcv()?調(diào)用?sk_data_ready()?方法,標(biāo)記這個 socket 有數(shù)據(jù)待收。

          本質(zhì)上,一個 socket 就是 Linux 中的一個文件描述符,這個描述符有一組相關(guān)的文件操 作抽象,例如?read、write?等等。

          網(wǎng)絡(luò)棧下半部分小結(jié)

          以上?Step 1~19 就是 Linux 網(wǎng)絡(luò)棧下半部分(bottom half of the network stack)的全部內(nèi)容。

          接下來我們還會介紹幾個內(nèi)核函數(shù),但它們都是與進(jìn)程上下文相關(guān)的。

          6.6 L4 - User Space

          下圖左邊是一段 socket listening 程序,這里省略了錯誤檢查,而且?epoll?本質(zhì)上也 是不需要的,因為 UDP 的 recv 方法以及在幫我們 poll 了。

          由于大家還是對 TCP 熟悉一些,因此在這里我假設(shè)這是一段 TCP 代碼。事實上當(dāng)我們調(diào) 用?recvmsg()?方法時,內(nèi)核所做的事情就和上面這段代碼差不多。對照右邊的圖:

          1. 首先初始化一個 epoll 實例和一個 UDP socket,然后告訴 epoll 實例我們想 監(jiān)聽這個 socket 上的 receive 事件,然后等著事件到來。

          2. 當(dāng) socket buffer 收到數(shù)據(jù)時,其 wait queue 會被上一節(jié)的?sk_data_ready()?方法置位(標(biāo)記)。

          3. epoll 監(jiān)聽在 wait queue,因此 epoll 收到事件通知后,提取事件內(nèi)容,返回給用戶空間。

          4. 用戶空間程序調(diào)用?recv?方法,它接著調(diào)用?udp_recv_msg?方法,后者又會 調(diào)用?cgroup eBPF 程序?—— 這是本文出現(xiàn)的第三種 BPF 程序。Cilium 利用 cgroup eBPF 實現(xiàn) socket level 負(fù)載均衡,這非常酷:

            • 一般的客戶端負(fù)載均衡對客戶端并不是透明的,即,客戶端應(yīng)用必須將負(fù)載均衡邏輯內(nèi)置到應(yīng)用里。

            • 有了 cgroup BPF,客戶端根本感知不到負(fù)載均衡的存在。

          5. 本文介紹的最后一種 BPF 程序是?sock_ops BPF,用于 socket level 整流(traffic shaping ),這對某些功能至關(guān)重要,例如客戶端級別的限速(rate limiting)。

          6. 最后,我們有一個用戶空間緩沖區(qū),存放收到的數(shù)據(jù)。

          以上就是?Cilium 基于 eBPF 的內(nèi)核收包之旅(traversing the kernel’s datapath)。太壯觀了!

          KubernetesCiliumKernel
          Endpoint (includes Pods)Endpointtc, cgroup socket BPF, sock_ops BPF, XDP
          Network PolicyCilium Network PolicyXDP, tc, sock-ops
          Service (node ports, cluster ips, etc)ServiceXDP, tc
          NodeNodeip-xfrm (for encryption), ip tables for initial decapsulation routing (if vxlan), veth-pair, ipvlan

          以上就是 Kubernetes 的所有網(wǎng)絡(luò)對象(the only artificial network objects)。什么意思??這就是 k8s CNI 所依賴的全部網(wǎng)絡(luò)原語(network primitives)。例如,LoadBalancer 對象只是 ClusterIP 和 NodePort 的組合,而后二者都屬于 Service 對象,所以他們并不 是一等對象。

          這張圖非常有價值,但不幸的是,實際情況要比這里列出的更加復(fù)雜,因為 Cilium 本身的 實現(xiàn)是很復(fù)雜的。這有兩個主要原因,我覺得值得拿出來討論和體會:

          首先,內(nèi)核 datapath 要遠(yuǎn)比我這里講的復(fù)雜。

          1. 前面只是非常簡單地介紹了協(xié)議棧每個位置(Netfilter、iptables、eBPF、XDP)能執(zhí)行的動作。

          2. 這些位置提供的處理能力是不同的。例如

            1. XDP 可能是能力最受限的,因為它只是設(shè)計用來做快速丟包(fast dropping)和?非本地重定向(non-local redirecting);但另一方面,它又是最快的程序,因為 它在整個 datapath 的最前面,具備對整個 datapath 進(jìn)行短路處理(short circuit the entire datapath)的能力。

            2. tc 和 iptables 程序能方便地 mangle 數(shù)據(jù)包,而不會對原來的轉(zhuǎn)發(fā)流程產(chǎn)生顯著影響。

          理解這些東西非常重要,因為這是Cilium 乃至廣義 datapath 里非常核心的東西。如果遇到底層網(wǎng)絡(luò)問題,或者需要做 Cilium/kernel調(diào)優(yōu),那你必須要理解包的收發(fā)/轉(zhuǎn)發(fā)路徑,有時你會發(fā)現(xiàn)包的某些路徑非常反直覺。

          第二個原因是,eBPF還非常新,某些最新特性只有在 5.x 內(nèi)核中才有。尤其是 XDP BPF, 可能一個節(jié)點(diǎn)的內(nèi)核版本支持,調(diào)度到另一臺節(jié)點(diǎn)時,可能就不支持。

          參考

          https://kccncna19.sched.com/event/Uae7/understanding-and-troubleshooting-the-ebpf-datapath-in-cilium-nathan-sweet-digitalocean


          瀏覽 45
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人国产一区二区三区精品麻豆 | 大屌肏屄视频 | 成人黄色视频网站在线 | 97视频自拍 | 99久久人妻精品无码二区 |