成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

追蹤 Kubernetes 中的數據包

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

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

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

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

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

基礎知識

數據包

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

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

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

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

圖片

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

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

socket 套接字

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

圖片

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

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

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

圖片

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

sk_buff

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

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

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

圖片

內核網絡協議棧

封包

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

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

解包

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

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

Kubernetes 的網絡模型

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

Kubernetes 中的數據包流轉

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

同 pod 內的容器間通信

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

圖片

同節點上的 pod 間通信

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

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

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

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

圖片

不同節點的 pod 間通信

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

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

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

圖片

總結

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

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

下篇繼續。

參考資料

[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

數據包分析內聯監控

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協議

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技術棧公眾號

主站蜘蛛池模板: 色综合一区二区 | 久草电影网| 嫩草国产 | 伊人伊成久久人综合网站 | 国产高清一区二区三区 | 日韩av高清 | 一区二区三区四区视频 | 99爱视频| 狠狠操狠狠操 | 日韩精品一区二区三区视频播放 | 91玖玖| 亚洲一区二区三区在线 | 久久免费视频2 | 午夜影院黄 | 国产黑丝av| 免费视频二区 | 天天操天天干天天透 | 91精品国产综合久久福利软件 | 羞羞视频免费在线观看 | 夜夜草导航 | 国产精品成人国产乱 | 日操夜操| aaa综合国产 | av永久 | 羞羞视频免费观 | 国产精品成人在线 | 欧美精品第一页 | 青青草网 | 成人精品免费视频 | 亚洲福利视频一区二区 | 精品久草| 国产精品一级在线观看 | 中文字幕一区二区三区在线观看 | 国产成人精品一区二 | 99小视频| 日本天堂一区 | 久久手机在线视频 | 亚洲精品一区中文字幕乱码 | 国产精品久久久久久福利一牛影视 | 老司机深夜福利网站 | a在线免费观看 |