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

追蹤 Kubernetes 中的數(shù)據(jù)包

云計(jì)算 云原生
統(tǒng)計(jì)一下在三個場景中,經(jīng)過內(nèi)核網(wǎng)絡(luò)協(xié)議棧的處理次數(shù)都是兩次(包括 netfilter 的處理。),即使是同 pod 或者同節(jié)點(diǎn)內(nèi)。而這兩種情況實(shí)際都發(fā)生在同一個內(nèi)核空間中。

網(wǎng)絡(luò)和操作系統(tǒng)內(nèi)核,對我來說是既陌生又滿是吸引,希望能夠撥開層層迷霧找到背后的真相。

在 ??上一篇文章?? 中我深入探討了 Kubernetes 網(wǎng)絡(luò)模型,這次我想更深入一點(diǎn):了解數(shù)據(jù)包在 Kubernetes 中的傳輸,為學(xué)習(xí) Kubernetes 的 eBPF 網(wǎng)絡(luò)加速做準(zhǔn)備,加深對網(wǎng)絡(luò)和操作系統(tǒng)內(nèi)核的理解。 文中可能有疏漏之處,還望大家賜教。

在開始之前,我可以用一句話來總結(jié)我的學(xué)習(xí)成果:數(shù)據(jù)包的流轉(zhuǎn)其實(shí)就是一個網(wǎng)絡(luò)套接字描述符(Socket File Descriptor,中文有點(diǎn)冗長,以下簡稱 socket fd)的尋址過程。 它不是簡單的指 socket fd 的內(nèi)存地址,還包括它的網(wǎng)絡(luò)地址。

在 Unix 和類 Unix 系統(tǒng)中,一切皆文件,也可以通過文件描述符來操作 socket。

基礎(chǔ)知識

數(shù)據(jù)包

既然要討論數(shù)據(jù)包的流轉(zhuǎn),先看看什么是數(shù)據(jù)包。

網(wǎng)絡(luò)數(shù)據(jù)包(network packet),也稱為網(wǎng)絡(luò)數(shù)據(jù)報(network datagram)或網(wǎng)絡(luò)幀(Network frame),是通過計(jì)算機(jī)網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)單位。拿最常見的 TCP 數(shù)據(jù)包來看包含如下幾個部分:

  • Ethernet header:鏈路層信息,主要包括目的 MAC 地址和源 MAC 地址,以及報文的格式,這里是 IP 包。
  • IP header:網(wǎng)絡(luò)層信息,主要包括長度、源 IP 地址和目的 IP 地址以及報文的格式,當(dāng)然這里必須是 TCP 包。
  • TCP header:傳輸層信息,包括源端口和目的端口。
  • 數(shù)據(jù):一般是第 7 層的數(shù)據(jù),比如 HTTP 等。

這里沒有介紹的 checksum 和 FCS 通常是用來檢查數(shù)據(jù)包在傳輸過程中是否被篡改或者發(fā)生了錯誤。

圖片

應(yīng)用程序使用 socket 向網(wǎng)絡(luò)發(fā)送數(shù)據(jù)的過程可以簡單理解為使用頭信息封裝數(shù)據(jù)的過程:TCP 數(shù)據(jù)包、IP 數(shù)據(jù)包、Ethernet 數(shù)據(jù)包;反過來,從網(wǎng)絡(luò)接收以太網(wǎng)數(shù)據(jù)包到應(yīng)用程序可以處理的數(shù)據(jù),就是解包的過程。封包和解包的過程是由內(nèi)核網(wǎng)絡(luò)協(xié)議棧來完成的。

下面分別說一下 socket 和內(nèi)核網(wǎng)絡(luò)協(xié)議棧的處理。

socket 套接字

Socket 是一種在計(jì)算機(jī)網(wǎng)絡(luò)中使用的編程接口,位于用戶空間(用戶應(yīng)用程序運(yùn)行的空間)和內(nèi)核網(wǎng)絡(luò)協(xié)議棧(內(nèi)核中對數(shù)據(jù)進(jìn)行封包和解包的組件)之間。

圖片

作為編程接口,socket 提供了如下操作(只列出部分):

  • socket
  • connect
  • bind
  • listen
  • accept
  • 數(shù)據(jù)傳輸
  • send
  • sendto
  • sendmsg
  • recv
  • recvfrom
  • recvmsg
  • getsockname
  • getpeername
  • getsockopt? 、setsockopt 獲取或設(shè)置 socket 層或協(xié)議層選項(xiàng)
  • close

通過下面的圖,可以直觀感受各個操作的作用:

圖片

開始講解內(nèi)核網(wǎng)絡(luò)協(xié)議棧之前,先說下數(shù)據(jù)包在內(nèi)存中的數(shù)據(jù)結(jié)構(gòu):sk_buff[1]。

sk_buff

sk_buff 是 Linux 內(nèi)核中用于管理網(wǎng)絡(luò)數(shù)據(jù)包的數(shù)據(jù)結(jié)構(gòu),它包含了接收和發(fā)送的網(wǎng)絡(luò)數(shù)據(jù)包的各種信息和屬性,如數(shù)據(jù)包的協(xié)議、數(shù)據(jù)長度、源和目標(biāo)地址等。sk_buff 是一種可以在網(wǎng)絡(luò)層和數(shù)據(jù)鏈路層之間傳遞的數(shù)據(jù)結(jié)構(gòu),可以被用于所有類型的網(wǎng)絡(luò)協(xié)議棧,例如 TCP/IP、UDP、ICMP 等。

sk_buff 在 Linux 內(nèi)核中廣泛應(yīng)用于網(wǎng)絡(luò)協(xié)議棧的各個層級,如數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層等。sk_buff 數(shù)據(jù)結(jié)構(gòu)的字段很多,有 4 個重要的字段且都是指針類型。sk_buff 在不同層的使用,就是通過修改這些指針來完成的:加 header (封包)和移除 header(解包)。

這個過程操作做的是指針,數(shù)據(jù)是零拷貝的,可以極大地提升效率。

圖片

內(nèi)核網(wǎng)絡(luò)協(xié)議棧

封包

應(yīng)用程序使用 socket 的 sendmsg 操作發(fā)送數(shù)據(jù)(這里不深入講解 netfilter、traffic control、queue discipline):

  1. 先分配 sk_buff
  2. 接下來開始網(wǎng)絡(luò)協(xié)議棧的處理
  3. 設(shè)置傳輸層信息(這里是 TCP 頭中的源和目的端口)
  4. 根據(jù)目標(biāo) IP 查找路由
  5. 設(shè)置網(wǎng)絡(luò)層信息(源和目的 IP 地址等)
  6. 調(diào)用 netfilter(LOCAL_OUT)
  7. 設(shè)置接口(interface)和協(xié)議(protocol)
  8. 調(diào)用 netfilter(POST_ROUTING)
  9. 如果包過長,分段傳輸
  10. L2 尋址,即查找可以擁有目標(biāo) IP 地址的設(shè)備的 MAC 地址
  11. 設(shè)置鏈路層信息,
  12. 至此內(nèi)核網(wǎng)絡(luò)協(xié)議棧的操作完成
  13. 調(diào)用 tc(traffic control)egress(可以對包進(jìn)行重定向)
  14. 進(jìn)入隊(duì)列 queue discipline(qdisc)
  15. 寫入 NIC(network interface controler)
  16. 發(fā)送到網(wǎng)絡(luò)

解包

NIC 收到網(wǎng)絡(luò)發(fā)來的數(shù)據(jù)包(這里不深入講解 direct memory access、netfilter、traffic control):

  1. 將數(shù)據(jù)包寫如 DMA 中(Direct Memory Access 直接內(nèi)存訪問,不需要依賴 CPU,由 NIC 直接寫入到內(nèi)存中)
  2. 分配 sk_buff,并填充元數(shù)據(jù),比如 protocol 為 Ethernet 類型,接收數(shù)據(jù)包的網(wǎng)絡(luò)接口等
  3. 將鏈路層信息保存在 sk_buff 的 mac_header 字段中,并“移除”數(shù)據(jù)包中的鏈路層信息(移動指針)
  4. 接下來開始網(wǎng)絡(luò)協(xié)議棧的處理
  5. 將網(wǎng)絡(luò)層信息保存在 network_header 字段中
  6. 調(diào)用 tc ingress
  7. “移除”網(wǎng)絡(luò)層信息
  8. 將傳輸層信息保存在 transport_header 字段中
  9. 調(diào)用 netfilter(PRE_ROUTING)
  10. 查找路由
  11. 合并多個分包
  12. 調(diào)用 netfilter(LOCAL_IN)
  13. “移除”傳輸層信息
  14. 查找監(jiān)聽目標(biāo)端口的 socket,或者發(fā)送 reset
  15. 將數(shù)據(jù)寫入 socket 的接收隊(duì)列中
  16. 發(fā)信號通知有數(shù)據(jù)寫入隊(duì)列
  17. 至此內(nèi)核網(wǎng)絡(luò)協(xié)議棧的操作完成
  18. sk_buff 從 socket 接收隊(duì)列中出隊(duì)
  19. 將數(shù)據(jù)寫入應(yīng)用程序的緩沖區(qū)
  20. 釋放 sk_buff

Kubernetes 的網(wǎng)絡(luò)模型

另一部分的基礎(chǔ)知識就是 Kubernetes 的網(wǎng)絡(luò)模型了,可以參考之前的那篇 深入探索 Kubernetes 網(wǎng)絡(luò)模型和網(wǎng)絡(luò)通信。

Kubernetes 中的數(shù)據(jù)包流轉(zhuǎn)

這里繼續(xù)討論之前文章中的三種通信場景,pod 間的通信使用 pod IP 地址。如果要討論通過 Service 來訪問,則要加入 netfilter 的討論篇幅會增加不少。

同 pod 內(nèi)的容器間通信

pod 內(nèi)兩個容器間的方式通常使用回環(huán)地址 127.0.0.1?,在封包的 #4 路由過程中確定了使用回環(huán)網(wǎng)卡 lo進(jìn)行傳輸。

圖片

同節(jié)點(diǎn)上的 pod 間通信

curl? 發(fā)出的請求在封包 #4 過程中確定使用 eth0? 接口。然后通過與 eth0? 相連的隧道 veth1 到達(dá)節(jié)點(diǎn)的根網(wǎng)絡(luò)空間。

veth1? 通過網(wǎng)橋 cni0? 與其他 pod 相連虛擬以太接口 vethX? 相連。在封包 #10 L2 尋址中,ARP 請求通過網(wǎng)橋發(fā)送給所有相連的接口是否擁有原始請求中的目的 IP 地址(這里是 10.42.1.9)

拿到了 veth0? 的 MAC 地址后,在封包 #11 中設(shè)置數(shù)據(jù)包的鏈路層信息。數(shù)據(jù)包發(fā)出后,經(jīng)過 veth0? 隧道進(jìn)入 pod httpbin? 的 eth0 接口中,然后開始解包的過程。

解包的過程沒啥特別,確定了 httpbin 使用的 socket。

圖片

不同節(jié)點(diǎn)的 pod 間通信

這里稍微不同,就是在通過 cni0? 發(fā)送 ARP 請求沒有收到應(yīng)答,使用根命名空間也就是主機(jī)的路由表,確定了目標(biāo)主機(jī) IP 地址后,然后通過主機(jī)的 eth0 放 ARP 請求并收到目標(biāo)主機(jī)的響應(yīng)。將其 MAC 地址在封包 #11 中寫入。

數(shù)據(jù)包發(fā)送到目標(biāo)主機(jī)后,開始解包的過程,最終進(jìn)入目標(biāo) pod。

在集群層面有一張路由表,里面存儲著每個節(jié)點(diǎn)的 Pod IP 網(wǎng)段(節(jié)點(diǎn)加入到集群時會分配一個 Pod 網(wǎng)段(Pod CIDR),比如在 k3s 中默認(rèn)的 Pod CIDR 是 10.42.0.0/16?,節(jié)點(diǎn)獲取到的網(wǎng)段是 10.42.0.0/24、10.42.1.0/24、10.42.2.0/24,依次類推)。通過節(jié)點(diǎn)的 Pod IP 網(wǎng)段可以判斷出請求 IP 的節(jié)點(diǎn),然后請求被發(fā)送到該節(jié)點(diǎn)。

圖片

總結(jié)

統(tǒng)計(jì)一下在三個場景中,經(jīng)過內(nèi)核網(wǎng)絡(luò)協(xié)議棧的處理次數(shù)都是兩次(包括 netfilter 的處理。),即使是同 pod 或者同節(jié)點(diǎn)內(nèi)。而這兩種情況實(shí)際都發(fā)生在同一個內(nèi)核空間中。

假如同一個內(nèi)核空間中的兩個 socket 可以直接傳輸數(shù)據(jù),是不是就可以省掉內(nèi)核網(wǎng)絡(luò)協(xié)議棧處理帶來的延遲?

下篇繼續(xù)。

參考資料

[1] sk_buff: https://elixir.bootlin.com/linux/latest/source/include/linux/skbuff.h#L843

責(zé)任編輯:武曉燕 來源: 云原生指北
相關(guān)推薦

2023-07-16 23:11:36

DNS查詢kubelet

2017-08-22 11:30:15

LinuxWireshark過濾數(shù)據(jù)包

2013-01-28 13:32:52

路由器網(wǎng)絡(luò)設(shè)置數(shù)據(jù)傳輸

2020-11-18 07:54:31

太網(wǎng)數(shù)據(jù)包架構(gòu)

2021-07-15 09:57:39

Wireshark數(shù)據(jù)包長度

2019-04-29 07:53:11

TCP數(shù)據(jù)包TCP網(wǎng)絡(luò)編程

2017-04-07 09:30:49

Linux網(wǎng)絡(luò)數(shù)據(jù)包

2012-12-04 09:54:33

路由器數(shù)據(jù)包TCP

2013-01-21 15:11:39

路由器數(shù)據(jù)包路由技術(shù)

2017-03-28 13:25:14

Linux網(wǎng)絡(luò)數(shù)據(jù)包

2013-05-21 14:41:42

數(shù)據(jù)包分析內(nèi)聯(lián)監(jiān)控

2010-12-15 14:04:11

Ngrep

2022-01-14 10:59:07

數(shù)據(jù)包tcpdump

2021-05-12 00:07:27

TCPIP協(xié)議

2014-07-09 09:43:59

2024-06-07 06:29:49

2020-11-23 10:25:44

tcpdump數(shù)據(jù)包Linux

2010-05-26 17:42:29

IPv6數(shù)據(jù)包

2011-11-28 16:03:49

wireshark數(shù)據(jù)包

2009-07-04 20:31:46

點(diǎn)贊
收藏

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