容器網路中的 Iptables 包路徑

發表於2023-09-21

前面我們分析了《資料包如何遊走於 Iptables 規則之間》,那麼在容器網路這種更復雜的場景中資料包是如何在 iptables 的各個規則之間遊走的呢?

為了搞清楚這個問題,我們首先有一些前置概念需要了解。

前置概念

network namespace

namespace 是容器隔離的基礎,而 network namespace 則使得每個 namespace 獨享 IP address、port、routing tables、iptables 等網路相關資源。這就意味著,資料包在容器和宿主機上經歷的 iptables 是不一樣的。

veth pair

veth pair 是容器網路的命脈,因為容器靠這個技術實現跨名稱空間通訊(namespace 把容器關了起來,veth pair 又按需把容器放了出來)。簡單理解,資料從一個 veth 進去,就會從另一個 veth 出來。這個實現也很簡潔,主要在 veth_xmit 函式中,大家可以到參考連結中稍微閱讀下。

容器組網

目前有三大主流模式。

overlay

簡單來講,就是容器網路是構建在宿主機網路上的另一層網路,容器 IP 本身在宿主機網路上不可路由,跨主機通訊需要藉助封包手段才能讓容器互聯。典型案例:Flannel(VXLAN 模式)、Calico(IPIP 模式)、Weave 等。

underlay

容器和宿主機共享一張網路,典型案例:MACVLAN、SR-IOV。由於共享網路,不存在封包過程,所以效能很好。

路由

路由模式其實是 Underlay 模式的一種特例,它的跨主機通訊是透過路由轉發來實現的,也沒有封包這個過程,所以效能也較好。

進入主題

我們以路由模式為例,如圖是一個典型的 node


圖 1

當 pod1 準備往其他 node 上的 pod 發資料時,pod1 內部的 iptables 路徑是這樣的:

image.png
圖 2

該 node 上是這樣的:

image.png
圖 3

veth 收到包後,這個包已經來到了宿主機 namespace,經宿主機路由規則判斷,要走宿主機 eth0 網路卡將包發出到宿主機網路上,所以是走的 forward 鏈 和 postrouting 鏈。
假設目的地址不是另一個 pod ip 而是網路外部地址,比如 google.com,則 postrouting 中會有相應的 snat 規則。


我們再來加個碼,假設 node 上有一些加密元件,將 pod 到 pod 之間的流量加密,那麼該 node 上就是這樣的:

image.png
圖 4

veth 收到包後,這個包已經來到了宿主機 namespace,經宿主機路由規則判斷,流量需要被加密,於是走到加密網路卡,所以走的還是 forward 鏈和 postrouting 鏈,區別在於,經過加密網路卡後,資料進入加密程式,加密程式完成對包的加密後,從宿主機 namespace 發出,直接到主網路卡 eth0,所以走的是 output 鏈和 postrouting 鏈。
加密程式和加密網路卡之間的關聯在《流量劫持技術哪家強?》中已有表述,主要有:涉及使用者態的 tun/tap 技術,以及僅核心態的 wireguard 技術。

對於接受端,基本就是上面的圖反過來,就不贅述了。

注:要得出這些結論,需要用到《資料包如何遊走於 Iptables 規則之間?》中提到的技術。當然,自己用 ebpf 等工具去 trace 也未嘗不可,就是麻煩點。

參考

相關文章