偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

理解 Net Device Ingress 和 Egress 雙重角色

云計(jì)算 云原生
本文我們從一個(gè)簡(jiǎn)單的物理網(wǎng)卡開始,然后對(duì) Veth、 Bridge 還有 Tc eBPF ,分別展開聊聊。

本文是書稿《圖解 VPC & K8s 網(wǎng)絡(luò)模型》其中一篇。書稿還在繼續(xù)寫,進(jìn)度不快也不慢,因?yàn)槎绮患币膊辉?。好肉需要慢燉,好書需要多磨?/span>

為什么要單獨(dú)講這個(gè)話題呢?因?yàn)槲以诤屯掠懻?K8s 網(wǎng)絡(luò)尤其是網(wǎng)絡(luò)數(shù)據(jù)流向的時(shí)候,會(huì)反復(fù)提及到網(wǎng)絡(luò)設(shè)備,無論它是物理的還是虛擬的。而網(wǎng)絡(luò)設(shè)備在我們所討論到的數(shù)據(jù)流場(chǎng)景里,時(shí)而在接收數(shù)據(jù),時(shí)而在發(fā)送數(shù)據(jù)。也就是說它同時(shí)扮演著雙重身份:Ingress 和 Egress。

另外我在整理 eBPF 相關(guān)的內(nèi)容,尤其是 tc eBPF 的時(shí)候,再一次發(fā)現(xiàn)如果不能準(zhǔn)確地在數(shù)據(jù)流中識(shí)別出網(wǎng)絡(luò)設(shè)備是 Ingress 還是 Egress ,就無法將代碼邏輯和實(shí)際運(yùn)行結(jié)果對(duì)上號(hào),更勿談能理解tc eBPF 了。

這樣的雙重角色扮演就如同一個(gè)調(diào)皮的孩子,總是帶上面具在錯(cuò)綜復(fù)雜的網(wǎng)絡(luò)里面東躲西藏,肆意玩耍。而當(dāng)你好不容易抓到它時(shí),卻讓你猜猜此時(shí)此刻他是誰。

簡(jiǎn)單來說:對(duì)于網(wǎng)卡而言,無論它是物理的還是虛擬的,對(duì)于 Ingress 角色,它是首先觸碰到數(shù)據(jù)的人,而對(duì)于 Egress 角色,它是最后一個(gè)碰到數(shù)據(jù)的人。

本文我們從一個(gè)簡(jiǎn)單的物理網(wǎng)卡開始,然后對(duì) veth、 bridge 還有 tc eBPF ,分別展開聊聊:

  • 當(dāng)網(wǎng)卡扮演 Ingress 角色時(shí),它從哪里接收數(shù)據(jù),又將數(shù)據(jù)遞交給了誰?
  • 當(dāng)網(wǎng)卡扮演 Egress 角色時(shí),它從哪里接收數(shù)據(jù),又將數(shù)據(jù)遞交給了誰?

1、單個(gè)物理網(wǎng)卡

圖片


圖1

這是一個(gè)簡(jiǎn)單的圖,圖中有一張物理網(wǎng)卡。我們的臺(tái)式機(jī)通常是這樣的配置。橘色的線代表著輸入流程,而藍(lán)色的線表示輸出流程。

(1)輸入流程 Ingress

對(duì)于這張網(wǎng)卡而言,輸入過程伴隨著以下幾個(gè)重要的事情:物理網(wǎng)卡首先接收到物理信號(hào) -> 物理網(wǎng)卡通過 DMA 機(jī)制將數(shù)據(jù)保存至其專屬的 RingBuffer 里面 -> 向 CPU 發(fā)起中斷 -> OS kernel thread ksoftirqd/x 不斷地消費(fèi) RingBuffer 里面的數(shù)據(jù)。

這里的 ksoftirqd 是一個(gè)內(nèi)核線程,每個(gè) CPU 一個(gè),x 為 CPU 編號(hào)。如 ksoftirqd/0 為 0 號(hào) CPU 上運(yùn)行的內(nèi)核線程。

ksoftirqd/x 將數(shù)據(jù)以 skb 為處理粒度依次穿過鏈路層、網(wǎng)絡(luò)層、TCP/UDP 傳輸層 。不過 skb 在鏈路層和網(wǎng)絡(luò)層還可能直接 forward 給其它網(wǎng)卡,那這樣的話傳輸層就不會(huì)收到這個(gè) skb 了。

整個(gè)過程如圖 2 所示,你可以從整體上感受一下。標(biāo)號(hào) 1 及 1.x 為數(shù)據(jù)輸入和生產(chǎn)過程,這是本文的重點(diǎn)。而標(biāo)號(hào) 3 為數(shù)據(jù)消費(fèi)過程,它帶著 skb 從入口處的 net_rx_action() 沿著協(xié)議棧由底向上穿越協(xié)議棧,這個(gè)過程對(duì)本文所述的所有 Ingress 場(chǎng)景都是通用的,故后文不再贅述這部分。

圖片

圖2

總結(jié):當(dāng)物理網(wǎng)卡扮演 Ingress 角色時(shí),它從主機(jī)外接收數(shù)據(jù),將數(shù)據(jù)遞交給了環(huán)形隊(duì)列,然后由 ksoftirqd/x 進(jìn)行后續(xù)的處理,這個(gè)處理過程也稱為網(wǎng)絡(luò)棧下半部分。

(2)輸出過程 Egress

從圖 1 中,我們大致可以看出來,對(duì)于輸出過程,數(shù)據(jù)來源有兩種,分別是通過 ip_forward() 過程和通過 ip_local_out() 過程送過來的數(shù)據(jù)。我們還會(huì)發(fā)現(xiàn),在發(fā)送數(shù)據(jù)的路徑上,這兩個(gè)過程只是起點(diǎn)有些不同,剩下的路程大家都一樣。

ip_forward() 過程與 skb 在 IP 層路由結(jié)果強(qiáng)相關(guān)。如圖 3 所示,具體來說經(jīng)過路由的判定,可能需要把 skb forward 至本機(jī)網(wǎng)絡(luò)設(shè)備或者網(wǎng)絡(luò)中的其它主機(jī)處理,不過無論是哪種情況,都需要將 skb 送往本機(jī)的一個(gè)網(wǎng)絡(luò)設(shè)備。

圖片

圖3

而 ip_local_out() 過程則對(duì)應(yīng)了本機(jī)進(jìn)程通過 socket 發(fā)送數(shù)據(jù)的場(chǎng)景,如圖 4 所示。這張圖最后標(biāo)注的“觸發(fā) NET_RX 類型軟中斷”是數(shù)據(jù)已經(jīng)被網(wǎng)卡發(fā)送完后發(fā)生的事情,中斷的目的是為了清理 skb ,略過不表。

圖片

圖 4 ,圖片來源:“開發(fā)內(nèi)功修煉”公眾號(hào)

總結(jié):當(dāng)物理網(wǎng)卡扮演 Egress 角色時(shí),它從本機(jī) TCP/IP 協(xié)議棧接收數(shù)據(jù),將數(shù)據(jù)通過驅(qū)動(dòng)程序送離本機(jī)。

2、veth-pair

是不是覺得單個(gè)網(wǎng)卡的場(chǎng)景其實(shí)很容易分辨出來 Ingress 和 Egress ?

別得意,我們來加點(diǎn)難度。我們知道 K8s 的默認(rèn) CNI flannel 用到了 veth 。veth 是什么以及它的特性二哥就不細(xì)說了。我們聊一個(gè)話題:圖 5 中,當(dāng)左側(cè)進(jìn)程向右側(cè)進(jìn)程通信發(fā)送數(shù)據(jù)時(shí), 左端的 veth_left 是 Ingress 還是 Egress ? 右端的 veth_right 呢?

圖片

圖 5

結(jié)合圖 5 上的箭頭示意,答案應(yīng)該不難猜。對(duì) veth_left 來說,它扮演的是 Egress 角色,因?yàn)檫M(jìn)程需要通過它把數(shù)據(jù)發(fā)送出去。對(duì) veth_right 而言是 Ingress ,因?yàn)樗枰?fù)責(zé)接收數(shù)據(jù)并把它送給右側(cè)的進(jìn)程。

下一個(gè)問題:既然  veth_left 扮演了 Egress 角色,流量從離開 network namespace 1 之后去哪里了?既然 veth_right 是 Ingress ,那它從哪里接收到流量的?

答案都在圖 6 里面。圖中標(biāo)號(hào) 2 及 2.x 在進(jìn)行數(shù)據(jù)發(fā)送的工作,都屬于 veth_left 的 Egress 的過程,這個(gè)過程是發(fā)生在 network namespace 1 里面的,函數(shù)調(diào)用棧和圖 4 一樣。而標(biāo)號(hào) 3 為數(shù)據(jù)消費(fèi)也即 veth_right 的 Ingress 過程,這個(gè)過程和物理網(wǎng)卡一模一樣。

圖片

圖 6

總結(jié):既然 veth 是一對(duì)虛擬網(wǎng)卡,那我們把對(duì)它倆的總結(jié)放在一起。

當(dāng) veth 網(wǎng)卡扮演 Egress 角色時(shí),如圖 7 中的 veth_left,它從其所在的 network namespace TCP/IP 協(xié)議棧接收數(shù)據(jù),并將數(shù)據(jù)遞交給了 per CPU input_pkt_queue 隊(duì)列,并觸發(fā)軟件中斷。

當(dāng) veth 網(wǎng)卡扮演 Ingress 角色時(shí),如圖 7 中的 veth_right,它并沒有物理網(wǎng)卡那種環(huán)形隊(duì)列,而是由 ksoftirqd/x 直接從 per CPU input_pkt_queue 隊(duì)列讀取  veth_left 塞進(jìn)來的數(shù)據(jù)。

veth_left 和 veth_right 共享了同一個(gè) queue 。典型的生產(chǎn)者 / 消費(fèi)者設(shè)計(jì)模式的視感有沒有?

圖片

圖 7

3、bridge

上一節(jié),二哥把 veth pair 單獨(dú)拿出來和大家一起觀賞??伤鼈兘K究不是花瓶,它們被創(chuàng)造出來是要有實(shí)際使用價(jià)值的。veth 典型使用場(chǎng)景就是把一端插入到 bridge 里面,如圖 8 所示。

從 veth 的特性來說,流量從下圖 veth1-left 流出后,會(huì)進(jìn)入 veth1-right ,這也就意味著流量進(jìn)入了網(wǎng)橋。

我想這個(gè)時(shí)候你可以確定 veth1-left 是 Egress ,而 veth1-right 是 Ingress 。那么對(duì)于 bridge 的 Port 1 和 Port 2 呢?再進(jìn)一步,對(duì)于 veth2-left 和 veth2-right 呢 ?

圖片

圖 8

其實(shí)對(duì)于 bridge 這種虛擬的網(wǎng)橋,它的 port 口也是一個(gè)虛擬的概念,說得更直白一點(diǎn),在內(nèi)核里它就是一個(gè)數(shù)據(jù)結(jié)構(gòu):struct net_bridge_port 。這個(gè)結(jié)構(gòu)里有 3 個(gè)重要的成員:br / port_no / dev 。下面的代碼用于插入網(wǎng)絡(luò)設(shè)備到 bridge ,這 3 個(gè)成員的作用顯而易見。

//file: net/bridge/br_if.c
static struct net_bridge_port *new_nbp(struct net_bridge *br,
struct net_device *dev)
{
//申請(qǐng)插口對(duì)象
struct net_bridge_port *p;
p = kzalloc(sizeof(*p), GFP_KERNEL);
//初始化插口
index = find_portno(br);
p->br = br;
p->dev = dev;
p->port_no = index;
...
}

對(duì)于圖 8 來說, Port 1 (net_bridge_port) 就是一個(gè)粘合劑,左手 bridge ,右手 veth1-right 。理解了這點(diǎn)也就明白了對(duì)于 bridge 的 Port 而言,它是沒有所謂的 Ingress 和 Egress 的概念的。

Port 1 接收數(shù)據(jù)其實(shí)是 veth1-right 在 Ingress,而 bridge 把這個(gè)流量 forward 給 veth2-right 時(shí),veth2-right 其實(shí)在扮演 Egress 角色。那流量從 veth2-right 傳至 veth2-left 的過程和 veth1-left 向 veth1-right 發(fā)送數(shù)據(jù)的過程是完全一樣的。

總結(jié):當(dāng) veth 這樣的虛擬網(wǎng)卡插入在 bridge 上時(shí):

圖8 中 veth1-left 扮演 Egress 角色,它從其所在的 network namespace TCP/IP 協(xié)議棧接收數(shù)據(jù),將數(shù)據(jù)遞交給了 per CPU input_pkt_queue 隊(duì)列,并觸發(fā)軟件中斷。

veth1-right 扮演 Ingress 角色,它并沒有物理網(wǎng)卡那種環(huán)形隊(duì)列,而是由 ksoftirqd/x 直接從 per CPU input_pkt_queue 隊(duì)列讀取  veth1-left 塞進(jìn)來的數(shù)據(jù)。當(dāng) ksoftirqd/x 把流量送至鏈路層時(shí),從 br_forward() 開始進(jìn)入 forward 流程。這個(gè)流程的效果就是流量從 veth1-right 轉(zhuǎn)至 veth2-right 發(fā)送出去了。

那自然 veth2-right 這個(gè)時(shí)候就扮演了 Egress 角色,veth2-left 扮演了 Ingress 角色。

4、veth-pair plus

如果你沒有暈的話,那抖索一下精神,我們開始 veth-pair 的進(jìn)階版。

上一節(jié)我們看到 veth 和 bridge 搭配使用的場(chǎng)景。veth 另一端一定要插在 bridge 上嗎?從圖 9 你也看到了,答案是:不一定。

圖片

圖 9

現(xiàn)在我們知道,在圖 9 中,從 container-1 發(fā)出的流量經(jīng)過 veth 發(fā)出后,veth-p 會(huì)以 Ingress 角色開始接收。根據(jù)前文的解釋,當(dāng)網(wǎng)卡進(jìn)行 Ingress 時(shí),流量會(huì)被 ksoftirqd/x 送往協(xié)議棧進(jìn)一步處理。這個(gè)處理的過程當(dāng)然也就包括了圖 9 中的路由過程。

圖 9 這里巧妙的地方是:流量是產(chǎn)生于容器內(nèi),但對(duì)這份流量的路由卻發(fā)生在主機(jī) root(default) network namespance 里面,使用的也是主機(jī)的路由表。如果路由結(jié)果發(fā)現(xiàn)需要把這份流量發(fā)往其它主機(jī),那自然流量就從主機(jī)的 eth0 這個(gè)網(wǎng)卡設(shè)備離開了。在這個(gè)過程中,主機(jī)其實(shí)扮演了網(wǎng)關(guān)的角色。

說到這里,你能理解圖 10 的工作過程了嗎?它是 K8s host-gateway 網(wǎng)絡(luò)模型,顧名思義,這種網(wǎng)絡(luò)模型以 host 為 gateway ,更具體地說,host 的 root network namespace 充當(dāng)了路由的角色。


圖片

圖 10


5、tc eBPF

如果你對(duì) tc 和 eBPF 了解得不多或者不感興趣,可以跳過這部分。

以 Cilium 為代表的 K8s CNI 提供商一直在嘗試使用 eBPF 代替 iptables 以便優(yōu)化服務(wù)網(wǎng)格數(shù)據(jù)面性能。其中 bpf_redicrect() 函數(shù)即為其中一項(xiàng)優(yōu)化產(chǎn)出。

bpf_redicrect() 函數(shù)的特性用一句話就能解釋清楚:當(dāng) veth Ingress 時(shí),將流量直接通過 bpf_redirect() 重定向到另一個(gè) veth Ingress。如圖 11 所示。

不過如果你對(duì) veth pair 哪一端在何時(shí)會(huì)扮演 Ingress 角色了解得不是很清楚的話,上面這句話其實(shí)會(huì)把你繞暈。

圖片

圖 11

但在看完二哥這篇文章后,希望你不會(huì)再暈了。在圖 11 中,從右下 Pod 出來的流量會(huì)流到位于 host network ns 這一端的 veth 上,這個(gè) veth 是以 Ingress 角色工作的。

你看到在它身上附上了一個(gè) eBPF 小蜜蜂圖標(biāo),表示這個(gè)時(shí)候 eBPF 程序會(huì)介入執(zhí)行,執(zhí)行的結(jié)果就是流量被直接通過 dev_forward_skb()  forward 給了另外一個(gè)同樣位于 host network ns 端的 veth (如圖 11 箭頭所指的那個(gè) veth),當(dāng)然對(duì)這個(gè) veth 而言,它會(huì)扮演 Egress 角色。

這個(gè)過程也可以用下面這樣的函數(shù)調(diào)用層次圖來表示。

pkt -> NIC -> TC ingress -> handle_ing()
|-verdict = tc_classify() // exec BPF code
| |-bpf_redirect() // return verdict
|
|-switch (verdict) {
case TC_ACK_REDIRECT:
skb_do_redirect() // to the target net device
|-if ingress:
| dev_forward_skb()
|-else:
dev_queue_xmit()


下面是網(wǎng)易輕舟的一篇文章里面所附的圖。它畫出了網(wǎng)易輕舟基于 Cilium 網(wǎng)絡(luò)方案的探索和實(shí)踐細(xì)節(jié),包括跨節(jié)點(diǎn) Pod 間通信、同節(jié)點(diǎn) Pod 間通信、Pod 訪問外網(wǎng)等各類常見的場(chǎng)景。

圖中  cilium_net/cilium_host? 是一對(duì) veth pair ,它們?cè)?Kernel 4.19? + Cilium ?1.8? 部署中已經(jīng)沒什么作用了(事實(shí)上社區(qū)在考慮去掉它們)。

我想有了上面所有的鋪墊和知識(shí),至少對(duì)標(biāo)號(hào) ① ② 所示的流程,你應(yīng)該能看得懂了。

圖片

圖 12


6、總結(jié)

文末,二哥來做個(gè)小總結(jié):

  1. 對(duì)于網(wǎng)卡而言,無論它是物理的還是虛擬的,對(duì)于 Ingress 角色,它是首先觸碰到數(shù)據(jù)的人,而對(duì)于 Egress 角色,它是最后一個(gè)碰到數(shù)據(jù)的人。
  2. 對(duì)于 Ingress 過程,無論是物理網(wǎng)卡還是虛擬網(wǎng)卡,在它接收到數(shù)據(jù)后,總是通過 ksoftirqd/x 進(jìn)行網(wǎng)絡(luò)棧下半部分處理。
  3. 對(duì)于 Egress 過程,無論是物理網(wǎng)卡還是虛擬網(wǎng)卡,在它從鏈路層那里拿到數(shù)據(jù)后,總是通過網(wǎng)卡驅(qū)動(dòng)程序?qū)?shù)據(jù)送離本設(shè)備。
  4. ?Ingress 過程和 Egress 過程在內(nèi)核中的處理路徑完全不同,也更無對(duì)稱可言。
  5. 對(duì)于 veth ,無論是搭配 bridge 還是用于 host-gateway 場(chǎng)景,在數(shù)據(jù)流經(jīng)過的關(guān)鍵位置區(qū)分是 Ingress 還是 Egress ,有助于理解系統(tǒng)對(duì)數(shù)據(jù)流的處理行為。
  6. tc eBPF 強(qiáng)依賴 Ingress 和 Egress,理解了它們也才能更好地理解 bpf_redirect() 。
責(zé)任編輯:姜華 來源: 二哥聊云原生
相關(guān)推薦

2022-03-03 08:42:10

NodePortServiceKubernetes

2022-03-15 08:36:34

NginxKubernetesIngress

2023-11-20 07:19:33

2022-08-12 09:00:00

網(wǎng)絡(luò)安全職業(yè)角色

2021-07-11 12:12:49

.NETJWTjson

2009-07-31 18:37:45

ASP.NET MVC

2020-10-08 15:15:45

智能

2016-08-05 13:01:41

混合云

2021-03-18 09:07:20

Nginx原理實(shí)踐

2016-11-11 00:33:25

雙重檢查鎖定延遲初始化線程

2013-03-25 10:37:24

2016-08-31 09:56:58

云計(jì)算

2009-04-24 09:43:09

.NETASP.NET框架

2009-06-18 09:56:44

ADO.NET對(duì)象模型

2009-03-26 10:11:47

2021-06-07 13:53:38

ServiceIngressKubernetes

2009-07-29 17:31:00

2021-10-22 21:39:11

InspectorV8 JS

2009-12-22 13:55:41

ASP.NETWebService

2009-10-27 11:16:20

VB.NET應(yīng)用框架
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)