日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
追蹤Kubernetes中的數(shù)據(jù)包

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

作者:張曉輝 2023-03-27 00:13:26

云計算

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

成都創(chuàng)新互聯(lián)公司是專業(yè)的銅鼓網(wǎng)站建設公司,銅鼓接單;提供網(wǎng)站設計制作、網(wǎng)站制作,網(wǎng)頁設計,網(wǎng)站設計,建網(wǎng)站,PHP網(wǎng)站建設等專業(yè)做網(wǎng)站服務;采用PHP框架,可快速的進行銅鼓網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!

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

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

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

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

基礎知識

數(shù)據(jù)包

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

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

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

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

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

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

socket 套接字

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

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

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

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

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

sk_buff

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

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

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

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

封包

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

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

解包

NIC 收到網(wǎng)絡發(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)絡接口等
  3. 將鏈路層信息保存在 sk_buff 的 mac_header 字段中,并“移除”數(shù)據(jù)包中的鏈路層信息(移動指針)
  4. 接下來開始網(wǎng)絡協(xié)議棧的處理
  5. 將網(wǎng)絡層信息保存在 network_header 字段中
  6. 調(diào)用 tc ingress
  7. “移除”網(wǎng)絡層信息
  8. 將傳輸層信息保存在 transport_header 字段中
  9. 調(diào)用 netfilter(PRE_ROUTING)
  10. 查找路由
  11. 合并多個分包
  12. 調(diào)用 netfilter(LOCAL_IN)
  13. “移除”傳輸層信息
  14. 查找監(jiān)聽目標端口的 socket,或者發(fā)送 reset
  15. 將數(shù)據(jù)寫入 socket 的接收隊列中
  16. 發(fā)信號通知有數(shù)據(jù)寫入隊列
  17. 至此內(nèi)核網(wǎng)絡協(xié)議棧的操作完成
  18. sk_buff 從 socket 接收隊列中出隊
  19. 將數(shù)據(jù)寫入應用程序的緩沖區(qū)
  20. 釋放 sk_buff

Kubernetes 的網(wǎng)絡模型

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

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進行傳輸。

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

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

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

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

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

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

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

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

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

總結(jié)

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

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

下篇繼續(xù)。

參考資料

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


網(wǎng)站名稱:追蹤Kubernetes中的數(shù)據(jù)包
文章起源:http://www.5511xx.com/article/cohpese.html