---
# System prepended metadata

title: 2025 香港 KubeCon 參加心得：Cilium 如何達到高性能網路

---

# 2025 香港 KubeCon 參加心得：Cilium 如何達到高性能網路

聽了很多個議程，挑了以下議程跟大家分享：
Simplifying the Networking and Security Stack With Cilium, Hubble, and Tetragon

以下文章皆來自講者分享的內容。

# Cilium 如何達到高性能網路

## 1. 什麼是 eBPF

![image](https://hackmd.io/_uploads/BJo58CoEex.png)

eBPF 是 Linux Kernel 的技術，你可以編寫一些程序放在 Kernel 當中，當特定的事件發生的時候，Kernel 會自動調用你的程序來實現你想要的功能。

Cilium 其實就是很多 eBPF 的程序來實現網路的轉發、安全性和可觀測。

![image](https://hackmd.io/_uploads/SJfi9RjNgg.png)

除了這些之外，Cilium 其實還使用到了 envoy 來實現 Service Mesh 和 7 層相關的功能，根據上圖，大家可以得知，Cilium 已經可以部署到大多數的雲上了，而且大多數的 Kubernetes 的發行版都已經支持了。

## 2. Cilium features

![image](https://hackmd.io/_uploads/Syh_jAjNxg.png)

以上是 Cilium 網路部分支持的功能，今天主要關注的是最左上角**高性能網路**的部分。

## 3. Standard Container Networking

Letʼs look at a standard container networking packet path:
* The pod to ClusterIP service that backend pod is on the same node.
* The pod access the Internet.

![image](https://hackmd.io/_uploads/S1bBhCo4xx.png)

提到高性能網路，我們就必須看一下標準的網路轉發路徑，我們在這兩個場景下，就考慮 Kubernetes 的一個節點，然後一個節點就 2 個 pods，左邊的 Pod 就是 Pod A，IP 地址是 `1.1.1.1`，右邊的 Pod B IP 地址就是 `1.1.1.2`。

第一個場景是，在同一個 node 中 Pod A 透過 Service IP 存取 Pod B，第二個場景是 Pod A 直接訪問外部互聯網大概是一個什麼樣的場景，網路封包會怎麼流轉。

從 Pod A 假設要訪問 Service IP 是 `10.96.0.1` 然後網路封包就會從 Pod A 的網卡發送到主機側，主機側會開始進入主機的網路內核站，這個時候它一般會流向有一個表叫 prerouting nat 的表，然後這個地方會有 kubeproxy 生成 Iptable 的規則，把 IP 的目的地址改成 Pod B 的，然後這個封包會繼續流轉，然後在查詢到路油表後，就會發現是去 Pod B 的，然後會轉發到 Pod B 主機側的網卡，主機側的網卡會把封包發給 Pod B，這樣 Pod B 就收到了。

> 主機側網卡指的是 veth pair 中連接在 Host 主機上那一端的網卡，從技術的角度看，veth pair 是指有一對網卡會跨 Linux Network Namespace 互相連接，一端在 Pod 的 Linux Network Namespace，另一端就是在 Host 主機裡面 root 的 Linux network namespace 中的網卡。

第二個場景是 Pod A 直接連線出外部的互聯網時，Pod A 查路油表時，會發現是出去的流量，一般情況下會有 SNAT 的行為發生，Pod A 的 IP 會變成主機的實體網卡。

## 4. Iptables and IPVS

![image](https://hackmd.io/_uploads/Bk9gQ6A4ee.png)


通常提到網路優化，很多時候會提到 IPVS 對 Iptables 的優化，

大家都知道 iptables 的查詢複雜程度是隨著服務數量或後端 Pod 數量的增加，查詢時間會線性增長，IPVS 則是在服務數量或後端 Pod 數量增加後，查詢時間並不會受到影響，也就是說大叢集的網路選 ipvs 的效率更高，但是具體情況發生什麼還是稍微有點複雜的。

## 5. IPVS

下圖就可以看到 IPVS 到底做了哪些事情，其實 IPVS 在這個地方只是替換了 prerouting nat 的表，當叢集很大時 IPVS 確實是有優勢的，問題是它只替換了這一部份，那你的封包還是在主機側的網路內核協議站走了整個內核協議站，這是其一，其二是當叢集沒那麼大時，IPVS 對 Iptables 的優化是未知的，IPVS 在運作上其實也有自己的開銷。

![image](https://hackmd.io/_uploads/rJLiraRVlx.png)


## 6. Kube-proxy replacement

![image](https://hackmd.io/_uploads/SktYB6RNxx.png)


從 cilium 的角度來看，cilium 有提供一個角度是 kube-proxy replacement，其實就是代替了 Kube-proxy，會有一個 eBPF 的程序掛載到 veth-pair 在主機側的網卡上，當 Pod A 到 Pod B 的流量在轉發時，Pod A 發給 Service IP，然後主機側的網卡收到封包後，會直接查詢的動作，然後把 IP 地址改到 Pod B，改到 Pod B 之後就不再通過整個內核協議站去查詢這些了，因為它就已經知道，要發到哪一張網卡上了，就直接透過 eBPF 程序把封包發給 Pod B 主機側的網卡，然後主機側的網卡就會再把封包發給 Pod B。

大家可以看到這已經跳過了很多內核協議站的網路部分，但因為是 Kube-proxy replacement，它只管理 Service 相關的，但這個時候 Pod A 出向的流量還是會查路由表，有的時候還是會通過 iptables 做 SNAT，在這種情況下。

## 7. eBPF host routing

![image](https://hackmd.io/_uploads/BJtsM11Bxx.png)

Cilium 另一個優化的點其實是叫 eBPF host routing，這個地方一般情況下我們會說它有兩個優化 : 
1. Pod A 出向的流量，會直接在 Pod A 主機側的網卡收到封包後，透過 eBPF 程序查詢，根據路由表，就直接發到出向的實體網卡。
2. 如同剛剛的場景，eBPF 程序收到了 Pod A 的封包後，他不解釋發到 Pod B 主機側的網卡，它其實是直接發到 Pod B 裡面，這樣的話又節省了一次從主機側將封包發給 Pod B 網卡的動作，這樣的話又減少了一點傳輸時間。

以上是兩個常見的優化。

## 8. Netkit

第三個是叫 Netkit，這是 Cilium 1.16 引入的，它其實是根據 Linux 核心中新的網路類型叫 Netkit 網路類型，這時候 eBPF 程序就掛載到了 pod 側，這種情況下就非常有意思，當 Pod A 發出一個流量到外部時，eBPF 程序就在 Pod 側就已經抓到了程序，可以直接發到物理網卡側，這樣 Pod A 就不需要把封包傳到主機側，這樣的話是一個非常大的優化，但比較可惜的是 Pod A 到 Pod B 的流量，他沒辦法做到 Pod A 到 Pod B 的直接轉發，雖然他在 Pod A 的容器側收到了，還是要發到 Pod B 主機側，還是沒有特別完美的轉發到 Pod B 這側。

![image](https://hackmd.io/_uploads/SJJiRaRNxx.png)





