大規(guī)模微服務(wù)利器:eBPF 與 Kubernetes

Linux 內(nèi)核是一切的堅(jiān)實(shí)基礎(chǔ),例如,內(nèi)核提供了 cgroup、namespace 等特性。
Kubernetes CNI 插件串聯(lián)起了關(guān)鍵路徑(critical path)上的組件。例如,從網(wǎng)絡(luò)的 視角看,包括:
廣義的 Pod 連通性:一個(gè)容器創(chuàng)建之后,CNI 插件會給它創(chuàng)建網(wǎng)絡(luò)設(shè)備,移動到容 器的網(wǎng)絡(luò)命名空間。
IPAM:CNI 向 IPAM 發(fā)送請求,為容器分配 IP 地址,然后配置路由。
Kubernetes 的 Service 處理和負(fù)載均衡功能。
網(wǎng)絡(luò)策略的生效(network policy enforcement)。
監(jiān)控和排障。
容器的部署密度越來越高(increasing Pod density)。
容器的生命周期越來越短(decreasing Pod lifespan)。甚至短到秒級或毫秒級。
https://www.cncf.io/wp-content/uploads/2020/03/CNCF_Survey_Report.pdf
https://www.cncf.io/wp-content/uploads/2020/03/CNCF_Survey_Report.pdf


So I can work with crazy people, that’s not the problem. They just need to sell their crazy stuff to me using non-crazy arguments, and in small and well-defined pieces. When I ask for killer features, I want them to lull me into a safe and cozy world where the stuff they are pushing is actually useful to mainline people first.
In other words, every new crazy feature should be hidden in a nice solid “Trojan Horse” gift: something that looks obviously good at first sight.
Linus Torvalds,
https://lore.kernel.org/lkml/[email protected]/



Cilium agent 生成 eBPF 程序。
用 LLVM 編譯 eBPF 程序,生成 eBPF 對象文件(object file,*.o)。
用 eBPF loader 將對象文件加載到 Linux 內(nèi)核。
校驗(yàn)器(verifier)對 eBPF 指令會進(jìn)行合法性驗(yàn)證,以確保程序是安全的,例如 ,無非法內(nèi)存訪問、不會 crash 內(nèi)核、不會有無限循環(huán)等。
對象文件被即時(shí)編譯(JIT)為能直接在底層平臺(例如 x86)運(yùn)行的 native code。
如果要在內(nèi)核和用戶態(tài)之間共享狀態(tài),BPF 程序可以使用 BPF map,這種一種共享存儲 ,BPF 側(cè)和用戶側(cè)都可以訪問。
BPF 程序就緒,等待事件觸發(fā)其執(zhí)行。對于這個(gè)例子,就是有數(shù)據(jù)包到達(dá)網(wǎng)絡(luò)設(shè)備時(shí),觸發(fā) BPF 程序的執(zhí)行。
BPF 程序?qū)κ盏降陌M(jìn)行處理,例如 mangle。最后返回一個(gè)裁決(verdict)結(jié)果。
根據(jù)裁決結(jié)果,如果是 DROP,這個(gè)包將被丟棄;如果是 PASS,包會被送到更網(wǎng)絡(luò)棧的 更上層繼續(xù)處理;如果是重定向,就發(fā)送給其他設(shè)備。
最重要的一點(diǎn):不能 crash 內(nèi)核。
執(zhí)行起來,與內(nèi)核模塊(kernel module)一樣快。
提供穩(wěn)定的 API。



網(wǎng)卡收到一個(gè)包(通過 DMA 放到 ring-buffer)。
包經(jīng)過 XDP hook 點(diǎn)。
內(nèi)核給包分配內(nèi)存,此時(shí)才有了大家熟悉的 skb(包的內(nèi)核結(jié)構(gòu)體表示),然后 送到內(nèi)核協(xié)議棧。
包經(jīng)過 GRO 處理,對分片包進(jìn)行重組。
包進(jìn)入 tc(traffic control)的 ingress hook。接下來,所有橙色的框都是 Netfilter 處理點(diǎn)。
Netfilter:在 PREROUTING hook 點(diǎn)處理 raw table 里的 iptables 規(guī)則。
包經(jīng)過內(nèi)核的連接跟蹤(conntrack)模塊。
Netfilter:在 PREROUTING hook 點(diǎn)處理 mangle table 的 iptables 規(guī)則。
Netfilter:在 PREROUTING hook 點(diǎn)處理 nat table 的 iptables 規(guī)則。
進(jìn)行路由判斷(FIB:Forwarding Information Base,路由條目的內(nèi)核表示,譯者注) 。接下來又是四個(gè) Netfilter 處理點(diǎn)。
Netfilter:在 FORWARD hook 點(diǎn)處理 mangle table 里的iptables 規(guī)則。
Netfilter:在 FORWARD hook 點(diǎn)處理 filter table 里的iptables 規(guī)則。
Netfilter:在 POSTROUTING hook 點(diǎn)處理 mangle table 里的iptables 規(guī)則。
Netfilter:在 POSTROUTING hook 點(diǎn)處理 nat table 里的iptables 規(guī)則。
包到達(dá) TC egress hook 點(diǎn),會進(jìn)行出方向(egress)的判斷,例如判斷這個(gè)包是到本 地設(shè)備,還是到主機(jī)外。
對大包進(jìn)行分片。根據(jù) step 15 判斷的結(jié)果,這個(gè)包接下來可能會:發(fā)送到一個(gè)本機(jī) veth 設(shè)備,或者一個(gè)本機(jī) service endpoint, 或者,如果目的 IP 是主機(jī)外,就通過網(wǎng)卡發(fā)出去。





當(dāng)時(shí)有 OpenvSwitch(OVS)、tc(Traffic control),以及內(nèi)核中的 Netfilter 子系 統(tǒng)(包括 iptables、ipvs、nftalbes 工具),可以用這些工具對 datapath 進(jìn)行“編程”:。
BPF 當(dāng)時(shí)用于 tcpdump,在內(nèi)核中盡量前面的位置抓包,它不會 crash 內(nèi)核;此 外,它還用于 seccomp,對系統(tǒng)調(diào)用進(jìn)行過濾(system call filtering),但當(dāng)時(shí) 使用的非常受限,遠(yuǎn)不是今天我們已經(jīng)在用的樣子。
此外就是前面提到的 feature creeping 問題,以及 tc 和 netfilter 的代碼重復(fù)問題,因?yàn)檫@兩個(gè)子系統(tǒng)是競爭關(guān)系。
OVS 當(dāng)時(shí)被認(rèn)為是內(nèi)核中最先進(jìn)的數(shù)據(jù)平面,但它最大的問題是:與內(nèi)核中其他網(wǎng) 絡(luò)模塊的集成不好。此外,很多核心的內(nèi)核開發(fā)者也比較抵觸 OVS,覺得它很怪。
tc、OVS、netfilter 可以對 datapath 進(jìn)行“編程”:但前提是 datapath 知道你想做什 么(but only if the datapath knows what you want to do)。
只能利用這些工具或模塊提供的既有功能。
eBPF 能夠讓你創(chuàng)建新的 datapahth(eBPF lets you create the datapath instead)。
描述 eBPF 的 RFC 引起了廣泛討論,但普遍認(rèn)為侵入性太強(qiáng)了(改動太大)。
另外,當(dāng)時(shí) nftables (inspired by BPF) 正在上升期,它是一個(gè)與 eBPF 有點(diǎn)類似的 BPF 解釋器,大家不想同時(shí)維護(hù)兩個(gè)解釋器。
用一個(gè)擴(kuò)展(extended)指令集逐步、全面替換原來老的 BPF 解釋器。
自動新老 BPF 轉(zhuǎn)換:in-kernel translation。
后續(xù) patch 將 eBPF 暴露給 UAPI,并添加了 verifier 代碼和 JIT 代碼。
更多后續(xù) patch,從核心代碼中移除老的 BPF。


networking
tracing
XDP 合并到內(nèi)核,支持在驅(qū)動的 ingress 層 attach BPF 程序。
nfp 最為第一家網(wǎng)卡及驅(qū)動,支持將 eBPF 程序 offload 到 cls_bpf & XDP hook 點(diǎn)。
通過 eBPF 實(shí)現(xiàn)高效的 label-based policy、NAT64、tunnel mesh、容器連通性。
整個(gè) datapath & forwarding 邏輯全用 eBPF 實(shí)現(xiàn),不再需要 Docker 或 OVS 橋接設(shè)備。
Netflix on eBPF for tracing: ‘Linux BPF superpowers’
Facebook 公布了生產(chǎn)環(huán)境 XDP+eBPF 使用案例(DDoS & LB)
用 XDP/eBPF 重寫了原來基于 IPVS 的 L4LB,性能 10x。
eBPF 經(jīng)受住了嚴(yán)苛的考驗(yàn):從 2017 開始,每個(gè)進(jìn)入 facebook.com 的包,都是經(jīng)過了 XDP & eBPF 處理的。
Cloudflare 將 XDP+BPF 集成到了它們的 DDoS mitigation 產(chǎn)品。
成功將其組件從基于 Netfilter 遷移到基于 eBPF。
到 2018 年,它們的 XDP L4LB 完全接管生產(chǎn)環(huán)境。
擴(kuò)展閱讀:http://arthurchiao.art/blog/cloudflare-arch-and-bpf-zh/
eBPF patch 合并到 bpf & bpf-next kernel trees on git.kernel.org
拆分 eBPF 郵件列表:[email protected] (archive at: lore.kernel.org/bpf/)
eBPF PR 經(jīng)內(nèi)核網(wǎng)絡(luò)部分的 maintainer David S. Miller 提交給 Linus Torvalds
Kubernetes CNI
Identity-based L3-L7 policy
ClusterIP Services
DPDK 需要重寫網(wǎng)卡驅(qū)動,需要額外維護(hù)用戶空間的驅(qū)動代碼。
AF_XDP 在復(fù)用內(nèi)核網(wǎng)卡驅(qū)動的情況下,能達(dá)到與 DPDK 一樣的性能。
Google 貢獻(xiàn)了 BPF LSM(安全),部署在了他們的數(shù)據(jù)中心服務(wù)器上。
BPF verifier 防護(hù) Spectre 漏洞(2018 年轟動世界的 CPU bug):even verifying safety on speculative program paths。
主流云廠商開始通過 SRIOV 支持 XDP:AWS(ena driver),Azure(hv_netvsc driver)……
Cilium 1.8 支持基于 XDP 的 Service 負(fù)載均衡和 host network policies。
Facebook 開發(fā)了基于 BPF 的 TCP 擁塞控制模塊。
Microsoft 基于 BPF 重寫了將他們的 Windows monitoring 工具。



347 個(gè)貢獻(xiàn)者,貢獻(xiàn)了 4,935 個(gè) patch 到 BPF 子系統(tǒng)。
BPF 內(nèi)核郵件列表日均 50 封郵件(高峰經(jīng)常超過日均 100)。
23,395 mails since mailing list git archive was added in Feb 2019
每天合并 4 個(gè)新 patch。patch 接受率 30% 左右。
30 個(gè)程序(different program),27 種 BPF map 類型,141 個(gè) BPF helpers,超過 3,500 個(gè)測試。
2 個(gè) BPF kernel maintainers & team of 6 senior core reviewers。
主要貢獻(xiàn)來自:Isovalent(Cilium),F(xiàn)acebook and Google


Facebook:L4LB、DDoS、tracing。
Netflix:BPF 重度用戶,例如生產(chǎn)環(huán)境 tracing。
Google:Android、服務(wù)器安全以及其他很多方面。
Cloudflare:L4LB、DDoS。
Cilium


$ kubectl -n kube-system delete ds kube-proxy

在 socket 層運(yùn)行的 BPF 程序
在 XDP 和 tc 層運(yùn)行的 BPF 程序

將 Service 的 IP:Port 映射到具體的 backend pods,并做負(fù)載均衡。
當(dāng)應(yīng)用發(fā)起 connect、sendmsg、recvmsg 等請求(系統(tǒng)調(diào)用)時(shí),攔截這些請求, 并根據(jù)請求的IP:Port 映射到后端 pod,直接發(fā)送過去。反向進(jìn)行相反的變換。
不需要包級別(packet leve)的地址轉(zhuǎn)換(NAT)。在系統(tǒng)調(diào)用時(shí),還沒有創(chuàng)建包,因此性能更高。
省去了 kube-proxy 路徑中的很多中間節(jié)點(diǎn)(intermediate node hops) 可以看出,應(yīng)用對這種攔截和重定向是無感知的(符合 Kubernetes Service 的設(shè)計(jì))。
因此,如果 Pod 流量直接從 node 出宿主機(jī),必須確保它能正常回來。而 node IP 一般都是全局可達(dá)的,集群外也可以訪問,所以常見的解決方案就是:在 Pod 通過 node 出集群時(shí),對其進(jìn)行 SNAT,將源 IP 地址換成 node IP 地址;應(yīng)答包回來時(shí),再進(jìn)行相 反的 DNAT,這樣包就能回到 Pod 了。

將東西向流量放在離 socket 層盡量近的地方做。
將南北向流量放在離驅(qū)動(XDP 和 tc)層盡量近的地方做。

Cilium XDP eBPF 模式能處理接收到的全部 10Mpps(packets per second)。
Cilium tc eBPF 模式能處理 3.5Mpps。
kube-proxy iptables 只能處理 2.3Mpps,因?yàn)樗?hook 點(diǎn)在收發(fā)包路徑上更后面的位置。
kube-proxy ipvs 模式這里表現(xiàn)更差,它相比 iptables 的優(yōu)勢要在 backend 數(shù)量很多的時(shí)候才能體現(xiàn)出來。

XDP 性能最好,是因?yàn)?XDP BPF 在驅(qū)動層執(zhí)行,不需要將包 push 到內(nèi)核協(xié)議棧。
kube-proxy 不管是 iptables 還是 ipvs 模式,都在處理軟中斷(softirq)上消耗了大量 CPU。

設(shè)想在將來,Linux 只會保留一個(gè)非常小的核心內(nèi)核(tiny core kernel),其他所有 內(nèi)核功能都由用戶定義,并用 BPF 實(shí)現(xiàn)(而不再是開發(fā)內(nèi)核模塊的方式)。
這樣可以減少受攻擊面,因?yàn)榇藭r(shí)的核心內(nèi)核非常小;另外,所有 BPF 代碼都會經(jīng)過 verifer 校驗(yàn)。
極大減少 ‘static’ feature creep,資源(例如 CPU)可以用在更有意義的地方。
設(shè)想一下,未來 Kubernetes 可能會內(nèi)置 custom BPF-tailored extensions,能根據(jù)用戶的應(yīng)用自動適配(optimize needs for user workloads);例如,判斷 pod 是跑在數(shù)據(jù)中心,還是在嵌入式系統(tǒng)上。



- END -
推薦閱讀 31天拿下K8s含金量最高的CKA+CKS證書! 運(yùn)維工程師不得不看的經(jīng)驗(yàn)教訓(xùn)和注意事項(xiàng) Kubernetes 的這些核心資源原理,你一定要了解 終于搞懂了服務(wù)器為啥產(chǎn)生大量的TIME_WAIT! Kubernetes 網(wǎng)絡(luò)方案之炫酷的 Cilium Prometheus+InfluxDB+Grafana 打造高逼格監(jiān)控平臺 民生銀行 IT運(yùn)維故障管理 可視化案例 這些 K8S 日常故障處理集錦,運(yùn)維請收藏~ Linux 這些工具堪稱神器! 豬八戒網(wǎng) CI/CD 最佳實(shí)踐之路 從零開始搭建創(chuàng)業(yè)公司DevOps技術(shù)棧 12年資深運(yùn)維老司機(jī)的成長感悟 搭建一套完整的企業(yè)級 K8s 集群(kubeadm方式)
點(diǎn)亮,服務(wù)器三年不宕機(jī)


