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

追蹤 Kubernetes 中的數據包

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

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

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

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

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

基礎知識

數據包

既然要討論數據包的流轉,先看看什么是數據包。

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

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

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

圖片

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

下面分別說一下 socket 和內核網絡協(xié)議棧的處理。

socket 套接字

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

圖片

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

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

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

圖片

開始講解內核網絡協(xié)議棧之前,先說下數據包在內存中的數據結構:sk_buff[1]。

sk_buff

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

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

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

圖片

內核網絡協(xié)議棧

封包

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

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

解包

NIC 收到網絡發(fā)來的數據包(這里不深入講解 direct memory access、netfilter、traffic control):

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

Kubernetes 的網絡模型

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

Kubernetes 中的數據包流轉

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

同 pod 內的容器間通信

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

圖片

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

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

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

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

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

圖片

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

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

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

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

圖片

總結

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

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

下篇繼續(xù)。

參考資料

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

責任編輯:武曉燕 來源: 云原生指北
相關推薦

2023-07-16 23:11:36

DNS查詢kubelet

2017-08-22 11:30:15

LinuxWireshark過濾數據包

2013-01-28 13:32:52

路由器網絡設置數據傳輸

2012-12-04 09:54:33

路由器數據包TCP

2017-03-28 13:25:14

Linux網絡數據包

2013-01-21 15:11:39

路由器數據包路由技術

2020-11-18 07:54:31

太網數據包架構

2021-07-15 09:57:39

Wireshark數據包長度

2017-04-07 09:30:49

Linux網絡數據包

2019-04-29 07:53:11

TCP數據包TCP網絡編程

2013-05-21 14:41:42

數據包分析內聯(lián)監(jiān)控

2010-05-26 17:42:29

IPv6數據包

2011-11-28 16:03:49

wireshark數據包

2010-12-15 14:04:11

Ngrep

2021-05-12 00:07:27

TCPIP協(xié)議

2022-01-14 10:59:07

數據包tcpdump

2014-07-09 09:43:59

2020-11-23 10:25:44

tcpdump數據包Linux

2024-06-07 06:29:49

2018-01-18 09:05:05

存儲數據包分層
點贊
收藏

51CTO技術棧公眾號