<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>

          【收藏】BPF 技術(shù)介紹及學(xué)習(xí)路線分享

          共 13293字,需瀏覽 27分鐘

           ·

          2021-12-14 15:08

          來自【分布式實(shí)驗(yàn)室


          近兩年BPF技術(shù)躍然成為了一項(xiàng)熱門技術(shù),在剛剛結(jié)束的KubeCon 2020 Europe會(huì)議上有7個(gè)關(guān)于BPF的技術(shù)分享, 而在KubeCon 2020 China會(huì)議上也已有了3個(gè)關(guān)于BPF技術(shù)的中文分享,分別來自騰訊和PingCAP,涉足網(wǎng)絡(luò)優(yōu)化和系統(tǒng)追蹤等領(lǐng)域。在中文社區(qū)里,包括阿里巴巴、網(wǎng)易、字節(jié)跳動(dòng)等國內(nèi)第一梯隊(duì)IT公司也越來越關(guān)注BPF這項(xiàng)新技術(shù)。本文主要介紹BPF技術(shù)發(fā)展和應(yīng)用,以及我是如何學(xué)習(xí)BPF技術(shù)的。


          BPF是什么?


          需要回答B(yǎng)PF是什么?就得先回答為什么需要BPF?

          多年前很多程序,例如網(wǎng)絡(luò)監(jiān)控器,都是作為用戶級(jí)進(jìn)程運(yùn)行的。為了分析只在內(nèi)核空間運(yùn)行的數(shù)據(jù),它們必須將這些數(shù)據(jù)從內(nèi)核空間復(fù)制到用戶空間的內(nèi)存中去,并進(jìn)行上下文切換。

          這與直接在內(nèi)核空間分析這些數(shù)據(jù)相比,導(dǎo)致了巨大的性能開銷。

          而隨著近年來網(wǎng)絡(luò)速度和流量井噴式增長,一些應(yīng)用程序必須處理大量的數(shù)據(jù)(如音頻、視頻流媒體數(shù)據(jù))。要在用戶空間監(jiān)控分析那么多的流量數(shù)據(jù)已經(jīng)不可行了,因而BPF應(yīng)運(yùn)而生——一種在內(nèi)核空間執(zhí)行高效安全的程序的機(jī)制。

          BPF全稱是「Berkeley Packet Filter」,翻譯過來是「伯克利包過濾器」,顧名思義,它是在伯克利大學(xué)誕生的,1992年Steven McCanne和Van Jacobson寫了一篇論文:《The BSD Packet Filter: A New Architecture for User-level Packet Capture》,第一次提出了BPF技術(shù),在文中,作者描述了他們?nèi)绾卧赨nix內(nèi)核實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)包過濾,這種新的技術(shù)比當(dāng)時(shí)最先進(jìn)的數(shù)據(jù)包過濾技術(shù)快20倍。

          下圖為BPF概覽,來自上面的論文:


          BPF 在數(shù)據(jù)包過濾上引入了兩大革新:

          • 一個(gè)新的虛擬機(jī)(VM)設(shè)計(jì),可以有效地工作在基于寄存器結(jié)構(gòu)的CPU之上;

          • 應(yīng)用程序使用緩存只復(fù)制與過濾數(shù)據(jù)包相關(guān)的數(shù)據(jù),不會(huì)復(fù)制數(shù)據(jù)包的所有信息,最大程度地減少BPF 處理的數(shù)據(jù),提高處理效率。


          我們熟悉的tcpdump就是基于BPF技術(shù),成為了站在神器肩膀上的神器。

          發(fā)展到現(xiàn)在名稱升級(jí)為eBPF:extended Berkeley Packet Filter。演進(jìn)成一套通用執(zhí)行引擎,提供了可基于系統(tǒng)或程序事件高效安全執(zhí)行特定代碼的通用能力,通用能力的使用者不再局限于內(nèi)核開發(fā)者。其使用場景不再僅僅是網(wǎng)絡(luò)分析,可以基于eBPF開發(fā)性能分析、系統(tǒng)追蹤、網(wǎng)絡(luò)優(yōu)化等多種類型的工具和平臺(tái)。

          eBPF由執(zhí)行字節(jié)碼指令、存儲(chǔ)對象和幫助函數(shù)組成,字節(jié)碼指令在內(nèi)核執(zhí)行前必須通過BPF驗(yàn)證器的驗(yàn)證,同時(shí)在啟用BPF JIT模式的內(nèi)核中,會(huì)直接將字節(jié)碼指令轉(zhuǎn)成內(nèi)核可執(zhí)行的本地指令運(yùn)行,具有很高的執(zhí)行效率。

          下圖是eBPF工作原理演示:


          原來的BPF就被稱為cBPF(classic BPF),目前已基本廢棄。當(dāng)前Linux 內(nèi)核只運(yùn)行eBPF,內(nèi)核會(huì)將cBPF透明轉(zhuǎn)換成eBPF再執(zhí)行。下文提到的BPF字樣沒有特別說明的話,是泛指cBPF和eBPF。


          BPF技術(shù)發(fā)展史


          從1992年發(fā)布以來,BPF技術(shù)快速發(fā)展,除了技術(shù)本身得到了升級(jí),基于它的工具和平臺(tái)也如雨后春筍一般層出不窮,下面是我整理的BPF技術(shù)發(fā)展史,里面羅列幾個(gè)重要的eBPF發(fā)展里程碑和基于eBPF技術(shù)的工具和平臺(tái)的誕生事件,其中包括BCC、Cilium、Falco、bpftrace、kubectl-trace,還有最近非常熱門的騰訊云獨(dú)創(chuàng)的IPVS-BPF模式。


          那么對于Linux內(nèi)核開發(fā)來說,BPF究竟有哪些超能力,吸引了這么多的開發(fā)者紛紛「入局」?

          在了解BPF的超能之前,我們先來看下當(dāng)前Linux內(nèi)核有哪些困難?

          傳統(tǒng)的Linux內(nèi)核開發(fā)需要實(shí)現(xiàn)以下3個(gè)目標(biāo):

          • 強(qiáng)安全,即不能允許不可信的代碼運(yùn)行在內(nèi)核中,這是頭等重要的事情

          • 高性能,作為承載千百萬服務(wù)的操作系統(tǒng)內(nèi)核,如果沒有高性能的保障,互聯(lián)網(wǎng)蓬勃發(fā)展將收到嚴(yán)重影響

          • 持續(xù)交付,在越來越多應(yīng)用進(jìn)入到云原生時(shí)代的今天,持續(xù)交付這個(gè)命題,一點(diǎn)都不陌生,而在內(nèi)核開發(fā)領(lǐng)域,這點(diǎn)也至關(guān)重要,每次功能的升級(jí),都需要你重新安裝新的系統(tǒng),大多數(shù)人都不會(huì)買賬。我們希望做到跟Chrome瀏覽器升級(jí)一樣,用戶都不會(huì)注意到升級(jí)完成了(除非有一些視覺上的變化),實(shí)現(xiàn)真正的無縫升級(jí)。


          想要實(shí)現(xiàn)上面的目標(biāo),沒有想象中那么簡單。

          我們來看進(jìn)行Linux內(nèi)核開發(fā)的一般解決方案以及它們的缺陷。

          • 直接修改內(nèi)核代碼進(jìn)行開發(fā),通過API暴露能力,可能要等上n年用戶才能更新到這個(gè)版本來使用,而且每次的功能更新都可能需要重新編譯打包內(nèi)核代碼。

          • 開發(fā)新的可即時(shí)加載的內(nèi)核模塊,用戶可以在運(yùn)行時(shí)加載到Linux內(nèi)核中,從而實(shí)現(xiàn)擴(kuò)展內(nèi)核功能的目的。然而每次內(nèi)核版本的官方更新,可能會(huì)引起內(nèi)核API的變化,因此你編寫的內(nèi)核模塊可能會(huì)隨著每一個(gè)內(nèi)核版本的發(fā)布而不可用,這樣就必須得為每次的內(nèi)核版本更新調(diào)整你的模塊代碼,你得非常小心,不然就會(huì)讓內(nèi)核直接崩潰。


          來看BPF帶來的解決方案,它是如何實(shí)現(xiàn)上面3個(gè)目標(biāo)的:

          • 強(qiáng)安全:BPF驗(yàn)證器(verifier)會(huì)保證每個(gè)程序能夠安全運(yùn)行,它會(huì)去檢查將要運(yùn)行到內(nèi)核空間的程序的每一行是否安全可靠,如果檢查不通過,它將拒絕這個(gè)程序被加載到內(nèi)核中去,從而保證內(nèi)核本身不會(huì)崩潰,這是不同于開發(fā)內(nèi)核模塊的。比如以下幾種情況是無法通過的BPF驗(yàn)證器的:

            • BPF驗(yàn)證機(jī)制很像Chrome瀏覽器對于JavaScript腳本的沙盒機(jī)制。

            • 沒有實(shí)際加載BPF程序所需的權(quán)限

            • 訪問任意內(nèi)核空間的內(nèi)存數(shù)據(jù)

              將任意內(nèi)核空間的內(nèi)存數(shù)據(jù)暴露給用戶空間


          • 高性能:一旦通過了BPF驗(yàn)證器,那么它就會(huì)進(jìn)入JIT編譯階段,利用Just-In-Time編譯器,編譯生成的是通用的字節(jié)碼,它是完全可移植的,可以在x86和ARM等任意球CPU架構(gòu)上加載這個(gè)字節(jié)碼,這樣我們能獲得本地編譯后的程序運(yùn)行速度,而且是安全可靠的。

          • 持續(xù)交付:通過JIT編譯后,就會(huì)把編譯后的程序附加到內(nèi)核中各種系統(tǒng)調(diào)用的鉤子(hook)上,而且可以在不影響系統(tǒng)運(yùn)行的情況下,實(shí)時(shí)在線地替換這些運(yùn)行在Linux內(nèi)核中的BPF程序。舉個(gè)例子,拿一個(gè)處理網(wǎng)絡(luò)數(shù)據(jù)包的應(yīng)用程序來說,在每秒都要處理幾十萬個(gè)數(shù)據(jù)包的情況下,在一個(gè)數(shù)據(jù)包和下一個(gè)數(shù)據(jù)包之間,加載到網(wǎng)絡(luò)系統(tǒng)調(diào)用hook上的BPF程序是可以自動(dòng)替換的,可以預(yù)見到的結(jié)果是,上一個(gè)數(shù)據(jù)包是舊版本的程序在處理,而下一個(gè)數(shù)據(jù)包就會(huì)看到新版本的程序了,沒有任何的中斷。這就是無縫升級(jí),從而實(shí)現(xiàn)持續(xù)交付的能力。


          因此,大名鼎鼎的系統(tǒng)性能優(yōu)化專家Brendan Gregg對于BPF的到來,就給出了以下的名言:

          “Super powers have finally come to Linux” — Brendan Gregg


          BPF的超能力


          第一個(gè),BPF Hooks,即BPF鉤子,也就是在內(nèi)核中,哪些地方可以加載BPF程序,在目前的Linux內(nèi)核中已經(jīng)有了近10種的鉤子,如下所示:

          • kernel functions(kprobes)

          • userspace functions(uprobes)

          • system calls

          • fentry/fexit

          • Tracepoints

          • network devices(tc/xdp)

          • network routes

          • TCP congestion algorithms

          • sockets(data level)


          從文件打開、創(chuàng)建TCP鏈接、Socket鏈接到發(fā)送系統(tǒng)消息等幾乎所有的系統(tǒng)調(diào)用,加上用戶空間的各種動(dòng)態(tài)信息,都能加載BPF程序,可以說是無所不能。它們在內(nèi)核中形成不同的BPF程序類型,在加載時(shí)會(huì)有類型判斷。

          下圖的內(nèi)核代碼片段是用來判斷BPF程序類型:


          第二個(gè)核心技能點(diǎn)——BPF Map。

          一個(gè)程序通常復(fù)雜的邏輯都有一個(gè)必不可少的部分,那就是記錄數(shù)據(jù)的狀態(tài)。對于BPF程序來說,可以在哪里存儲(chǔ)數(shù)據(jù)狀態(tài)、統(tǒng)計(jì)信息和指標(biāo)信息呢?這就是BPF Map的作用,BPF程序本身只有指令,不會(huì)包含實(shí)際數(shù)據(jù)及其狀態(tài)。我們可以在BPF程序創(chuàng)建BPF Map,這個(gè)Map像其他編程語言具有的Map數(shù)據(jù)結(jié)構(gòu)類似,也有很多類型,常用的就是Hash和Array類型,如下所示:

          • Hash tables,Arrays

          • LRU(Least Recently Used)

          • Ring Buffer

          • Stack Trace

          • LPM(Longest Prefix match)


          下圖所示是一個(gè)典型的BPF Map創(chuàng)建代碼:


          值得一提的是:

          • BPF Map是可以被用戶空間訪問并操作的

          • BPF Map是可以與BPF程序分離的,即當(dāng)創(chuàng)建一個(gè)BPF Map的BPF程序運(yùn)行結(jié)束后,該BPF Map還能存在,而不是隨著程序一起消亡


          基于上面兩個(gè)特點(diǎn),意味著我們可以利用BPF Map持久化數(shù)據(jù),在不丟失重要數(shù)據(jù)的同時(shí),更新BPF程序邏輯,實(shí)現(xiàn)在不同程序之間共享信息,在收集統(tǒng)計(jì)信息或指標(biāo)等場景下,尤其有用。

          第三個(gè)核心技能點(diǎn)——BPF Helper Function,即BPF輔助函數(shù)。


          它們是面向開發(fā)者的,提供操作BPF程序和BPF Map的工具類函數(shù)。由于內(nèi)核本身會(huì)有不定期更新迭代,如果直接調(diào)用內(nèi)核模塊,那天可能就不能用了,因此通過定義和維護(hù)BPF輔助函數(shù),由BPF輔助函數(shù)來去面對后端的內(nèi)核函數(shù)的變化,對開發(fā)者透明,形成穩(wěn)定API接口。

          例如,BPF程序不知道如何生成一個(gè)隨機(jī)數(shù),有一個(gè)BPF輔助函數(shù)會(huì)可以幫你檢索并詢問內(nèi)核,完成“給我一個(gè)隨機(jī)數(shù)”的任務(wù),或者“從BPF Map中讀取某個(gè)值”等等。任何一種與操作系統(tǒng)內(nèi)核的交互都是通過BPF輔助函數(shù)來完成的,由于這些都是穩(wěn)定的API,所以BPF程序可以跨內(nèi)核版本進(jìn)行移植。

          下圖是部分BPF輔助函數(shù)的列表:


          介紹完這些BPF超能力的技能點(diǎn),接下來要講講超能力也有限制的地方。

          BPF技術(shù)雖然強(qiáng)大,但是為了保證內(nèi)核的處理安全和及時(shí)響應(yīng),內(nèi)核對于BPF 技術(shù)也給予了諸多限制,如下是幾個(gè)重點(diǎn)限制:

          • eBPF程序不能調(diào)用任意的內(nèi)核參數(shù),只限于內(nèi)核模塊中列出的BPF Helper函數(shù),函數(shù)支持列表也隨著內(nèi)核的演進(jìn)在不斷增加

          • eBPF程序不允許包含無法到達(dá)的指令,防止加載無效代碼,延遲程序的終止

          • eBPF程序中循環(huán)次數(shù)限制且必須在有限時(shí)間內(nèi)結(jié)束

          • eBPF堆棧大小被限制在MAX_BPF_STACK,截止到內(nèi)核Linux 5.8版本,被設(shè)置為512。目前沒有計(jì)劃增加這個(gè)限制,解決方法是改用BPF Map,它的大小是無限的。

          • eBPF字節(jié)碼大小最初被限制為4096條指令,截止到內(nèi)核Linux 5.8版本, 當(dāng)前已將放寬至100萬指令(BPF_COMPLEXITY_LIMIT_INSNS),對于無權(quán)限的BPF程序,仍然保留4096條限制(BPF_MAXINSNS)


          更多相關(guān)信息可以查看這里:https://github.com/DavadDi/bpf_study#23-ebpf-的限制

          隨著技術(shù)的發(fā)展和演進(jìn),限制也在逐步放寬或者提供了對應(yīng)的解決方案。

          BPF應(yīng)用場景


          接下來我們通過3個(gè)案例分析,來看下具有強(qiáng)大超能力的BPF在實(shí)際環(huán)境中的應(yīng)用場景:

          1、Cilium,是首款完全基于eBPF程序?qū)崿F(xiàn)了kube-proxy的所有功能的Kubernetes CNI網(wǎng)絡(luò)插件,無需依賴iptables和IPVS。

          我們知道kube-proxy基于iptables的服務(wù)負(fù)載均衡功能在大規(guī)模容器場景下具有嚴(yán)重的性能瓶頸,同時(shí)由于容器的創(chuàng)建和銷毀非常頻繁,基于IP做身份關(guān)聯(lián)的故障排除和安全審計(jì)等也很難實(shí)現(xiàn)。

          Cilium作為一款Kubernetes CNI插件,從一開始就是為大規(guī)模和高度動(dòng)態(tài)的容器環(huán)境而設(shè)計(jì),并且?guī)砹薃PI級(jí)別感知的網(wǎng)絡(luò)安全管理功能,通過使用基于Linux內(nèi)核特性的新技術(shù)——BPF,提供了基于Service/Pod/Container作為標(biāo)識(shí),而非傳統(tǒng)的IP地址,來定義和加強(qiáng)容器和Pod之間網(wǎng)絡(luò)層、應(yīng)用層的安全策略。因此,Cilium不僅將安全控制與尋址解耦來簡化在高度動(dòng)態(tài)環(huán)境中應(yīng)用安全性策略,而且提供傳統(tǒng)網(wǎng)絡(luò)第3層、4層隔離功能,以及基于http層上隔離控制,來提供更強(qiáng)的安全性隔離。

          另外,由于BPF可以動(dòng)態(tài)地插入控制Linux系統(tǒng)的程序,實(shí)現(xiàn)了強(qiáng)大的安全可視化功能,而且這些變化是不需要更新應(yīng)用代碼或重啟應(yīng)用服務(wù)本身就可以生效,因?yàn)锽PF是運(yùn)行在系統(tǒng)內(nèi)核中的。

          以上這些特性,使Cilium能夠在大規(guī)模容器環(huán)境中也具有高度可伸縮性、可視化以及安全性。

          如何通過eBPF程序?qū)崿F(xiàn)請求轉(zhuǎn)發(fā)的原理分析:

          Cilium通過將eBPF程序加載到內(nèi)核的幾個(gè)網(wǎng)絡(luò)Hook上,包括TC,XDP,實(shí)現(xiàn)了原來Kube-Proxy請求轉(zhuǎn)發(fā)的能力。在內(nèi)核網(wǎng)絡(luò)棧中,這兩個(gè)網(wǎng)絡(luò)hook都要比kube-proxy所依賴的iptables處于更早的網(wǎng)絡(luò)前端,還沒有生成完全的網(wǎng)絡(luò)報(bào)文的上下文(包含更復(fù)雜的元數(shù)據(jù)結(jié)構(gòu)),因此具有更高的網(wǎng)絡(luò)數(shù)據(jù)處理效率,如下圖所示:


          配合eBPF Map存儲(chǔ)后端Pod地址和端口,實(shí)現(xiàn)高效查詢和更新。


          2、Falco,來自老牌安全廠商Sysdig開源的關(guān)注云原生運(yùn)行時(shí)安全的項(xiàng)目。

          當(dāng)前問題:目前云原生時(shí)代Kubernetes技術(shù)解決了基礎(chǔ)架構(gòu)平臺(tái)Day 1 Operation問題,而Day 2 Operation包含了monitor,maintain,和 troubleshoot等一系列運(yùn)行時(shí)工作,其中「云原生安全問題」已經(jīng)引起越來越多的注意。

          Falco解決方案:Falco是第一個(gè)加入CNCF的關(guān)注云原生運(yùn)行時(shí)安全的開源項(xiàng)目,目前是威脅Kubernetes平臺(tái)監(jiān)測引擎的事實(shí)標(biāo)準(zhǔn),還可以監(jiān)測意外的應(yīng)用行為和運(yùn)行時(shí)發(fā)出的威脅警告。

          如何使用eBPF程序?qū)崿F(xiàn)實(shí)時(shí)應(yīng)用監(jiān)控:

          Falco主要使用了raw_tracepoint的系統(tǒng)調(diào)用hook,檢測應(yīng)用進(jìn)程的啟動(dòng)和退出,然后通過Perf類型的BPF Map將檢測到的數(shù)據(jù)發(fā)送回用戶空間,實(shí)現(xiàn)監(jiān)控的pipeline。官方Falco已自帶了很多默認(rèn)監(jiān)控規(guī)則,具體可以查看Falco pod中的/etc/falco/falco_rules.yaml文件。

          下面幾個(gè)樣例:




          最近兩年KubeCon大會(huì)上都有Falco的精彩talk,都是來自Sysdig的神,介紹了Falco的運(yùn)作原理和使用場景,是了解掌握Falco非常好的材料,其中Kris Nova是個(gè)非常cool的技術(shù)女神,她的PPT也非常有個(gè)性,是基于命令行的。

          更多Falco部署使用內(nèi)容可以看我的這篇博文:https://davidlovezoe.club/wordpress/archives/831

          3、Kubectl-trace,一款基于bpftrace的kubectl插件,幫助用戶追蹤排查Kubernetes應(yīng)用的運(yùn)行情況。

          首先介紹下bpftrace,它是一種高階的描述系統(tǒng)追蹤的語言,其優(yōu)勢在于可以通過一行腳本(One-Liner)實(shí)現(xiàn)多種應(yīng)用追蹤能力,如下圖所示:


          通過和BCC集成,能實(shí)現(xiàn)更強(qiáng)追蹤能力。如果你想要的腳本比較復(fù)雜,可以放在一個(gè)擴(kuò)展名為bt的文件里,如下圖所示的bashreadline.bt:


          回到我們的kubectl-trace,它的能力就是可以把定義好的bpftrace腳本attach到指定的節(jié)點(diǎn)、Pod上,來追蹤腳本里定義的目標(biāo)。具體來說,kubectl-trace插件在Kubernetes集群內(nèi)是通過名為trace-runner的job形式指定執(zhí)行一個(gè)bpftrace程序,如下圖所示:


          而在這個(gè)trace-runner job的Pod中,它的工作原理就是一個(gè)原生BPF程序原生的工作流程了,通過加載BPF程序(即bpftrace生成的)到kprobes,uprobes,tracepoints等系統(tǒng)調(diào)用hook上,并把程序的輸出重定向到磁盤上,以便進(jìn)行事后查詢,整體工作流程如下圖所示:


          蓬勃發(fā)展的BPF社區(qū)和生態(tài)


          各種社區(qū)網(wǎng)站,是學(xué)習(xí)BPF的好去處:

          • https://ebpf.io,最全BPF學(xué)習(xí)資源網(wǎng)站,主要由Cilium團(tuán)隊(duì)維護(hù),上面會(huì)及時(shí)更新BPF技術(shù)的文檔和視頻。

          • https://lwn.net/Kernel/Index/#Berkeley_Packet_Filter,LWN是學(xué)習(xí)Linux內(nèi)核技術(shù)的最好的網(wǎng)站,這個(gè)BPF分類文章集合,記錄了很多BPF里程碑事件的前前后后,既學(xué)會(huì)了知識(shí),又明白了背景。

          • https://cilium.readthedocs.io/en/stable/bpf/,Cilium提供的BPF文檔,是我看到過的最具實(shí)戰(zhàn)價(jià)值的BPF手冊,值得好好閱讀。

          • https://www.kernel.org/doc/html/latest/bpf/bpf_devel_QA.html,開發(fā)BPF必讀Q&A,里面是維護(hù)BPF內(nèi)核代碼的大佬給出的代碼開發(fā)建議,讀了能明白社區(qū)是如何運(yùn)作BPF的。


          學(xué)習(xí)技術(shù)還是得從源代碼開始:

          • https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git/,這個(gè)repo是Linux社區(qū)官方維護(hù)的獨(dú)立BPF代碼倉庫,一旦發(fā)布新版本后,代碼就不會(huì)大改,只接受bug fix,相當(dāng)于master repo,最終會(huì)merge到Linux內(nèi)核代碼主干中。

          • https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/,這個(gè)repo也是Linux社區(qū)官方維護(hù)的BPF代碼倉庫,更新頻繁,用于引入新功能或現(xiàn)有功能優(yōu)化,穩(wěn)定后merge到上面的master repo,相當(dāng)于feature repo。


          看到最近的commits里,不乏有國人的貢獻(xiàn),感興趣的話,來參與吧~

          學(xué)習(xí)技術(shù)也需要溝通交流:

          • https://cilium.slack.com/archives/C4XCTGYEM,為Cilium提供的關(guān)于eBPF的thread,有什么疑問都可以去問

          • https://github.com/DavadDi/bpf_study,狄衛(wèi)華老師的收集的BPF文章和教程,有問題可以去提issue

          • https://github.com/nevermosby/linux-bpf-learning,本人編寫的BPF教程,歡迎來提issue和PR


          BPF大神們:

          • Brendan Gregg,來自Netflix最強(qiáng)BPF布道師,他的博客都是關(guān)于Linux系統(tǒng)優(yōu)化的,觀點(diǎn)獨(dú)到,每一篇都值得一讀;

          • Alexei Starovoitov,eBPF創(chuàng)造者,目前在Facebook就職,經(jīng)常能在內(nèi)核代碼commit中看到他的蹤跡;

          • Daniel Borkmann,eBPF kernel co-maintainer,目前在Cilium所在的公司Isovalent就職,是給eBPF增加feature的能力者;

          • Thomas Graf,Cilium之父,Isovalent的CTO,他也是eBPF和Cilium的強(qiáng)力布道師,能說會(huì)道,各種大會(huì)上都有他的風(fēng)采;

          • Quentin Monnet,BPFTool co-maintainer,Quentin是在stackoverflow上bpf問題的killer,Twitter有關(guān)于eBPF的系列實(shí)戰(zhàn)短文,值得細(xì)品。


          BPF書籍:

          • 《Linux Observability with BPF》,作者David Calavera和Lorenzo Fontana, 這本書篇幅不長,是來自sysdig的兩位大佬寫的BPF手冊書,推薦入門閱讀

          • 《Linux內(nèi)核觀測技術(shù)BPF》,是最近剛出版的第一本BPF中文書籍,為上面英文書的翻譯版本,由范彬和狄衛(wèi)華兩位翻譯

          • 《BPF Performance Tools》,這是Brendan Gregg大神對于BPF技術(shù)如何做系統(tǒng)性能優(yōu)化的一本集大成者的秘籍,BPF學(xué)習(xí)者必備。

          • 《Systems Performance: Enterprise and the Cloud, 2nd Edition》,這是Brendan Gregg大神系統(tǒng)優(yōu)化書籍的第二版,篇幅較長,但是值得一啃。


          另外建議大家可以跟蹤各種大會(huì)上的eBPF技術(shù)分享。

          最開始提到的最近兩年的KubeCon上的eBPF相關(guān)Session。

          下面是最新的幾個(gè)session詳細(xì)鏈接:

          • 繞過conntrack,使用eBPF增強(qiáng) IPVS優(yōu)化k8s網(wǎng)絡(luò)性能:https://v.qq.com/x/page/s3137ehoq8i.html

          • 深入了解服務(wù)網(wǎng)格數(shù)據(jù)平面性能和調(diào)優(yōu):https://v.qq.com/x/page/v3137ax6zss.html

          • Kubernetes中用于混沌與跟蹤的BPF:https://v.qq.com/x/page/f3130lpe0iv.html

          • https://kccnceu20.sched.com/event/ZejN/tutorial-using-bpf-in-cloud-native-environments-alban-crequy-marga-manterola-kinvolk

          • https://kccnceu20.sched.com/event/Zeoz/hubble-ebpf-based-observability-for-kubernetes-sebastian-wicki-isovalent

          • https://kccnceu20.sched.com/event/Zexb/designing-a-grpc-interface-for-kernel-tracing-with-ebpf-leonardo-di-donato-sysdig

          • https://kccnceu20.sched.com/event/ZemQ/ebpf-and-kubernetes-little-helper-minions-for-scaling-microservices-daniel-borkmann-cilium

          • https://kccnceu20.sched.com/event/Zewd/intro-to-falco-intrusion-detection-for-containers-shane-lawrence-shopify

          • https://kccnceu20.sched.com/event/ZetL/seccomp-security-profiles-and-you-a-practical-guide-duffie-cooley-vmware

          • https://kccnceu20.sched.com/event/ZeqL/k8s-in-the-datacenter-integrating-with-preexisting-bare-metal-environments-max-stritzinger-bloomberg


          LPC 2020 Networking and BPF Summit,這個(gè)會(huì)一周前剛結(jié)束,可以說是BPF技術(shù)的專題會(huì),上面有非常多的eBPF實(shí)踐案例以及未來可能增加的功能列表,比如BPF Map是否能resize,而不是一上來就定義好大小。

          羅列下使用BPF技術(shù)的項(xiàng)目:

          • Tcpdump

          • BCC,BPFTrace,kubectl-trace from IOVisor

          • Cilium from Isovalent

          • Falco from Sysdig

          • Katran from Facebook

          • Bottlerocket from Amazon


          中文社區(qū)有:

          • 騰訊云IPVS-BPF K8S網(wǎng)絡(luò)優(yōu)化方案

          • Kernel Chaos With BPF by PingCAP

          • 網(wǎng)易輕舟做系統(tǒng)檢測和網(wǎng)絡(luò)優(yōu)化

          • 字節(jié)跳動(dòng)做高性能網(wǎng)絡(luò)ACL管理


          更多IT公司都在嘗試使用BPF技術(shù)到各個(gè)領(lǐng)域中。


          我是如何學(xué)習(xí)BPF技術(shù)的


          先來說說我和BPF的緣起。我第一次接觸BPF技術(shù)是在今年年初,看到了介紹Cilium這款Kubernetes網(wǎng)絡(luò)插件的視頻,它能通過BPF程序?qū)崿F(xiàn)了所有Kube-proxy功能,而且把請求轉(zhuǎn)發(fā)效率提升了近50%,覺得非常不可思議,然后就決定深入了解下BPF這項(xiàng)超能力技術(shù)。

          整個(gè)學(xué)習(xí)過程,總的來說我是先看了很多英文文章,因?yàn)楫?dāng)時(shí)中文社區(qū)關(guān)于BPF技術(shù)的文章非常少,然后設(shè)計(jì)編寫自己的BPF程序,希望把它跑起來并獲得預(yù)期的結(jié)果,期間會(huì)有很多問題發(fā)生,就會(huì)不停地去調(diào)試代碼,最終通過寫博客,把每次有目的的學(xué)習(xí)過程和成果,記錄總結(jié)并分享出來。

          其中要給大家重點(diǎn)說的就是學(xué)習(xí)之初要做計(jì)劃。

          做計(jì)劃對大多數(shù)人來說,是獲得成功結(jié)果的必要條件,而做計(jì)劃的過程是我認(rèn)為就是全盤思考的過程。當(dāng)然計(jì)劃不是一成不變的,以你自己的學(xué)習(xí)節(jié)奏和輸出效率,可以在過程中按需進(jìn)行適當(dāng)調(diào)整。

          下圖是我剛開始制定的BPF學(xué)習(xí)計(jì)劃:


          第一階段主要是學(xué)習(xí)和翻譯經(jīng)典英文材料,跟“多讀書,讀好書”道理一樣,翻譯材料也是這樣,首選要去優(yōu)秀的社區(qū),然后去選優(yōu)質(zhì)的材料,通過逐句逐句地翻譯,就能理解這項(xiàng)技術(shù)的方方面面。這個(gè)過程有點(diǎn)像讀文檔翻譯文檔,但是比看文檔有趣多了,因?yàn)檫@種優(yōu)質(zhì)的材料里一般都會(huì)有精彩的故事,讓你知道技術(shù)的誕生和發(fā)展其背后真正的驅(qū)動(dòng)力。

          BPF的優(yōu)秀社區(qū)是哪家?我選擇了上面提到的LWN.net社區(qū),最早全稱為Linux Weekly News。現(xiàn)在內(nèi)容已經(jīng)不單單是Linux了,涉足廣泛。很多資深I(lǐng)T圈人士都會(huì)給LWN供稿,內(nèi)容詳實(shí)有深度,值得反復(fù)閱讀。

          而在選取材料時(shí),由于不同階段的閱讀目標(biāo)不同,初級(jí)階段建議選擇沒有太多技術(shù)細(xì)節(jié)的,能講明白BPF技術(shù)是什么?解決什么問題?以及發(fā)展歷程,就可以作為候選。

          完成了第一階段,就會(huì)對這項(xiàng)技術(shù)的背景和術(shù)語有了初步的認(rèn)識(shí),接下來就是選取一個(gè)興趣點(diǎn)作為切入口,深入了解這項(xiàng)技術(shù)的使用場景和工作原理,也就是第二階段——?jiǎng)邮謱?shí)踐。

          我自己對使用BPF進(jìn)行網(wǎng)絡(luò)優(yōu)化這個(gè)領(lǐng)域很感興趣,因此它變成了我動(dòng)手學(xué)習(xí)的切入口。下面是我的第一個(gè)網(wǎng)絡(luò)層面的XDP BPF程序:


          目的非常簡單,就是所有經(jīng)過XDP鉤子的網(wǎng)絡(luò)數(shù)據(jù)包,全部drop掉,也就是形成了“丟包”的結(jié)果,這就是業(yè)界最出名的一個(gè)XDP BPF應(yīng)用場景的雛形——Facebook基于XDP實(shí)現(xiàn)高效的防DDoS攻擊,其本質(zhì)上就是實(shí)現(xiàn)盡可能早地實(shí)現(xiàn)「丟包」,而不去消耗系統(tǒng)資源創(chuàng)建完整的網(wǎng)絡(luò)棧鏈路,即「early drop」。

          像上面這樣,通過準(zhǔn)備動(dòng)手實(shí)驗(yàn)環(huán)境,寫代碼,調(diào)試代碼,這一步步的過程中一定會(huì)出現(xiàn)預(yù)料之外的問題,不用怕,要有耐心去啃,雖然耗時(shí)會(huì)可能會(huì)非常長,但要有不達(dá)目的不罷休的毅力。

          我的自己的一個(gè)經(jīng)歷,就是在調(diào)試TC BPF程序時(shí),發(fā)現(xiàn)結(jié)果總是不符合預(yù)期,然后就不停地調(diào)試代碼,同時(shí)也對用來調(diào)試的BPF輔助函數(shù)bpf_trace_printk()進(jìn)行了深入地研究(鏈接是我當(dāng)初整理的關(guān)于這個(gè)函數(shù)的思維導(dǎo)圖:https://github.com/nevermosby/linux-bpf-learning/blob/master/bpf/bpf_trace_printk_definition.pdf),從而了解到了BPF底層實(shí)現(xiàn),包括它是由11個(gè)64位寄存器、1個(gè)計(jì)數(shù)器和1個(gè)512字節(jié)BPF stack組成。寄存器命名規(guī)則是r0-r10,每個(gè)寄存器都有專屬的作用:

          • r0保存了調(diào)用一次輔助函數(shù)后的返回值

          • r1 – r5 保存了從BPF程序到輔助函數(shù)的參數(shù)列表

          • r6 – r9 是用來保存中間值的寄存器,它可以被多個(gè)輔助函數(shù)調(diào)用

          • r10 是唯一的只讀寄存器,包含訪問BPF stack的指針


          上面這些都是你不罷休的成果,要相信由付出必有回報(bào)。

          第三階段,就是我現(xiàn)在正在做的事情,總結(jié)和分享。成功的實(shí)踐一定會(huì)讓你有輸出的欲望,我選擇博客作為我的輸出渠道,當(dāng)然大家也可以去選擇其他的渠道。對我而言,通過文字和圖片把一件事情娓娓道道是個(gè)很舒服的方式。而把這些內(nèi)容再分享出去,讓更多的人了解這項(xiàng)技術(shù)并獲得收獲,會(huì)令你自己感到快樂,這就是分享的意義。

          再分享一點(diǎn)關(guān)于如何閱讀理解代碼的TIPS:

          • 在線閱讀Linux內(nèi)核代碼的好去處:https://elixir.bootlin.com/linux/v5.8.7/source

          • 快速定位函數(shù)的定義和引用

          • 下載Linux內(nèi)核代碼,編譯運(yùn)行BPF示例程序

          • 參見博文: https://davidlovezoe.club/compile-bpf-examples

          • 根據(jù)示例程序,寫自己的BPF程序,并跑起來


          學(xué)習(xí)BPF給我?guī)淼氖斋@


          • 能夠靜下心來看Linux內(nèi)核代碼,這件事聽起來簡單,做起來不易,因?yàn)橛辛藢W(xué)習(xí)興趣有學(xué)習(xí)目標(biāo),我開始習(xí)慣于閱讀那些看起來冗長晦澀的代碼

          • 理解Linux系統(tǒng)調(diào)用、文件系統(tǒng)等功能模塊的工作原理,正式由于能靜下心來讀代碼,所以那些原本認(rèn)為這輩子都看不懂的東西,竟然慢慢變得清晰起來

          • 寫文章可以鍛煉很多其他軟技能,比如畫圖,錄視頻,做視頻等等,寫技術(shù)博客就是這么一件痛并快樂著的事情


          如果對BPF技術(shù)感興趣想深入了解的,可以關(guān)注我博客的BPF系列文章:https://davidlovezoe.club/wordpress/archives/tag/bpf以及GitHub上配套的BPF源碼repo:https://github.com/nevermosby/linux-bpf-learning/。


          Q&A


          Q:真正使用BPF,或者想了解透徹,是否一定要看源碼?
          A :我的建議是要看源代碼,不一定要每句都理解,但是要知道其基本工作原理。是精讀還是泛讀,可以根據(jù)你的使用需求來。

          Q:部署Cilium后,能否回退回Calico或者其他插件?
          A:當(dāng)然可以,通過kubectl delete -f [你用來部署cilium的yaml],是可以刪除所有的Cilium相關(guān)資源的,不會(huì)影響其他CNI插件的部署。

          Q:Cilium距離應(yīng)用生產(chǎn)環(huán)境還存在什么問題?
          A:個(gè)人覺得還是內(nèi)核版本的要求比較高,Cilium官方推薦是使用內(nèi)核5.XX以上的系統(tǒng)來部署,但是絕大多數(shù)企業(yè)可能都停留在3.XX或4.XX。

          Q:看不懂代碼,只是需要排查定位故障,有什么資料學(xué)習(xí)分享?
          A :https://cilium.readthedocs.io/en/stable/bpf/,Cilium提供的BPF文檔,是我看到過的最具實(shí)戰(zhàn)價(jià)值的BPF手冊,有基本原理的介紹和命令行BPFTool工具的使用方法。

          Q:eBPF現(xiàn)在是alpha版本嗎,以后內(nèi)核升級(jí)的話,eBPF的API會(huì)有大的變動(dòng)嗎?另外是從那個(gè)內(nèi)核版本引進(jìn)的eBPF呢?BPF是不是比eBPF缺少很多接口?
          A:eBPF是2014年誕生的,Linux內(nèi)核是在3.15之后引入eBPF的,目前已經(jīng)非常成熟,很多國外IT企業(yè)都是生產(chǎn)使用的,包括Facebook、Netflix、Google。Google最近把的GKE平臺(tái)升級(jí)成默認(rèn)使用eBPF模式的Cilium網(wǎng)絡(luò)方案了。內(nèi)核升級(jí)不會(huì)影響eBPF的API,本質(zhì)上說eBPF沒有所謂的對外API接口,它對外暴露的是各種鉤子hook,用來插入用C語言或其他語言寫的eBPF程序編譯后的字節(jié)碼文件。現(xiàn)在老的BPF(也就是cBPF)已經(jīng)基本廢棄了,開發(fā)者面向的都是具有eBPF的Linux環(huán)境。

          Q:是否改變預(yù)設(shè)BPF Map的大小討論的意義是什么,是基于不同操作系統(tǒng)的應(yīng)用以及場景的問題嗎?
          A :當(dāng)前情況是聲明創(chuàng)建一個(gè)BPF Map是固定大小的,往里面存數(shù)據(jù)是動(dòng)態(tài)的。有些應(yīng)用場景的需求,希望可以動(dòng)態(tài)地?cái)U(kuò)容BPF Map大小,這樣比再聲明一個(gè)更大的BPF Map更高效。


          Q:文中提到BPF map在BPF程序運(yùn)行完畢后還可以獨(dú)立存在,那比如我卸掉Cilium之后這個(gè)map要如何回收?
          A:BPF map持久化是通過掛載到磁盤上,Cilium官方的做法是mount bpffs/sys/fs/bpf -t bpf,就像刪除文件一樣,刪除這個(gè)目錄下的文件即可。

          Q:請問下,kubectl-trace對OS系統(tǒng)版本(內(nèi)核版本),Kubenetes的版本之類有要求嗎?
          A :有的,因?yàn)樗鼤?huì)運(yùn)行eBPF程序到你的目標(biāo)節(jié)點(diǎn)上,所以節(jié)點(diǎn)OS內(nèi)核版本肯定是要支持eBPF的,推薦是5.XX以上。需要的Kubenetes版本官方倒是沒有提及,我這邊v1.16和v.17試過都可以。

          Linux學(xué)習(xí)指南

          有收獲,點(diǎn)個(gè)在看?

          瀏覽 220
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  亚欧中文在线 | 无码Aⅴ | 娇小小小泬BBB亚洲 | 欧美乱伦AA片 | 无码人妻一区二区三区免费n鬼沢 |