1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        【收藏】BPF 技術介紹及學習路線分享

        共 13293字,需瀏覽 27分鐘

         ·

        2021-12-14 15:08

        來自【分布式實驗室


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


        BPF是什么?


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

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

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

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

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

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


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

        • 一個新的虛擬機(VM)設計,可以有效地工作在基于寄存器結構的CPU之上;

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


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

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

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

        下圖是eBPF工作原理演示:


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


        BPF技術發(fā)展史


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


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

        在了解BPF的超能之前,我們先來看下當前Linux內核有哪些困難?

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

        • 強安全,即不能允許不可信的代碼運行在內核中,這是頭等重要的事情

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

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


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

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

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

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


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

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

          • BPF驗證機制很像Chrome瀏覽器對于JavaScript腳本的沙盒機制。

          • 沒有實際加載BPF程序所需的權限

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

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


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

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


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

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


        BPF的超能力


        第一個,BPF Hooks,即BPF鉤子,也就是在內核中,哪些地方可以加載BPF程序,在目前的Linux內核中已經(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)調用,加上用戶空間的各種動態(tài)信息,都能加載BPF程序,可以說是無所不能。它們在內核中形成不同的BPF程序類型,在加載時會有類型判斷。

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


        第二個核心技能點——BPF Map。

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

        • Hash tables,Arrays

        • LRU(Least Recently Used)

        • Ring Buffer

        • Stack Trace

        • LPM(Longest Prefix match)


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


        值得一提的是:

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

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


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

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


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

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

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


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

        BPF技術雖然強大,但是為了保證內核的處理安全和及時響應,內核對于BPF 技術也給予了諸多限制,如下是幾個重點限制:

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

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

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

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

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


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

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

        BPF應用場景


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

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

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

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

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

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

        如何通過eBPF程序實現(xiàn)請求轉發(fā)的原理分析:

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


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


        2、Falco,來自老牌安全廠商Sysdig開源的關注云原生運行時安全的項目。

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

        Falco解決方案:Falco是第一個加入CNCF的關注云原生運行時安全的開源項目,目前是威脅Kubernetes平臺監(jiān)測引擎的事實標準,還可以監(jiān)測意外的應用行為和運行時發(fā)出的威脅警告。

        如何使用eBPF程序實現(xiàn)實時應用監(jiān)控:

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

        下面幾個樣例:




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

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

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

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


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


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


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


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


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

        • https://ebpf.io,最全BPF學習資源網(wǎng)站,主要由Cilium團隊維護,上面會及時更新BPF技術的文檔和視頻。

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

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

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


        學習技術還是得從源代碼開始:

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

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


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

        學習技術也需要溝通交流:

        • https://cilium.slack.com/archives/C4XCTGYEM,為Cilium提供的關于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最強BPF布道師,他的博客都是關于Linux系統(tǒng)優(yōu)化的,觀點獨到,每一篇都值得一讀;

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

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

        • Thomas Graf,Cilium之父,Isovalent的CTO,他也是eBPF和Cilium的強力布道師,能說會道,各種大會上都有他的風采;

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


        BPF書籍:

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

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

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

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


        另外建議大家可以跟蹤各種大會上的eBPF技術分享。

        最開始提到的最近兩年的KubeCon上的eBPF相關Session。

        下面是最新的幾個session詳細鏈接:

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

        • 深入了解服務網(wǎng)格數(shù)據(jù)平面性能和調優(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,這個會一周前剛結束,可以說是BPF技術的專題會,上面有非常多的eBPF實踐案例以及未來可能增加的功能列表,比如BPF Map是否能resize,而不是一上來就定義好大小。

        羅列下使用BPF技術的項目:

        • 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)絡優(yōu)化方案

        • Kernel Chaos With BPF by PingCAP

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

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


        更多IT公司都在嘗試使用BPF技術到各個領域中。


        我是如何學習BPF技術的


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

        整個學習過程,總的來說我是先看了很多英文文章,因為當時中文社區(qū)關于BPF技術的文章非常少,然后設計編寫自己的BPF程序,希望把它跑起來并獲得預期的結果,期間會有很多問題發(fā)生,就會不停地去調試代碼,最終通過寫博客,把每次有目的的學習過程和成果,記錄總結并分享出來。

        其中要給大家重點說的就是學習之初要做計劃。

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

        下圖是我剛開始制定的BPF學習計劃:


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

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

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

        完成了第一階段,就會對這項技術的背景和術語有了初步的認識,接下來就是選取一個興趣點作為切入口,深入了解這項技術的使用場景和工作原理,也就是第二階段——動手實踐。

        我自己對使用BPF進行網(wǎng)絡優(yōu)化這個領域很感興趣,因此它變成了我動手學習的切入口。下面是我的第一個網(wǎng)絡層面的XDP BPF程序:


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

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

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

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

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

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

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


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

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

        再分享一點關于如何閱讀理解代碼的TIPS:

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

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

        • 下載Linux內核代碼,編譯運行BPF示例程序

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

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


        學習BPF給我?guī)淼氖斋@


        • 能夠靜下心來看Linux內核代碼,這件事聽起來簡單,做起來不易,因為有了學習興趣有學習目標,我開始習慣于閱讀那些看起來冗長晦澀的代碼

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

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


        如果對BPF技術感興趣想深入了解的,可以關注我博客的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:當然可以,通過kubectl delete -f [你用來部署cilium的yaml],是可以刪除所有的Cilium相關資源的,不會影響其他CNI插件的部署。

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

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

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

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


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

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

        Linux學習指南

        有收獲,點個在看?

        瀏覽 220
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产精品久久久久婷婷五月 | 午夜视频啊啊啊 | 国产精品美女久久久久久久久 | 国产三级裸露镜头合集 | 男女激情国产 | 日本欧美视频 | 女人19毛片A片水真多下载 | 乡村活寡妇在做爰 | 国产有码在线观看 | 高清无码视频免费版本在线观看 |