為什麼 K8s 網路除錯這麼難?
Kubernetes 的網路設計很優雅——抽象層讓使用者只需要建個 Service 或 Ingress 就能存取應用。但一旦出問題,這些抽象層反而變成了除錯的障礙。底層牽涉的元件太多了:基礎設施的路由與防火牆、CNI 插件、kube-proxy 的 iptables/ipvs 規則、CoreDNS、Network Policy……任何一個環節出差錯,表現出來都是同一句「網路不通」。
這篇文章整理了一套系統化的除錯思路,幫你在遇到網路問題時不再盲目瞎試。
先搞清楚:流量方向是南北向還是東西向?
南北向流量
封包有一端不屬於叢集——也就是有「進出叢集」的行為。常見情境:
| 方向 | 典型機制 |
|---|---|
| 外部 → 叢集內服務 | Ingress Controller、LoadBalancer Service、API Gateway |
| 叢集內服務 → 外部 | NAT Gateway、Internet Gateway、節點的 SNAT |
南北向的底層實作差異極大。舉三種常見架構:
- 外部 LB → NodePort → kube-proxy → Pod:傳統架構,經過的轉換層最多
- 外部 LB → 直通 Pod:雲端 CNI(如 AWS VPC CNI)讓 Pod IP 直接可路由,LB 跳過 NodePort
- L4 LB → Ingress Controller → Pod:在叢集入口用 L7 處理,後端根據路由表選擇走 Internal 或 Public 網路
同一個「外部存取叢集服務」的需求,三種做法的封包路徑完全不同。這就是為什麼除錯的第一步是畫出架構圖。
東西向流量
封包兩端都在叢集內,包含:
- Pod ↔ Pod(同節點或跨節點)
- Pod ↔ Service(經過 iptables/ipvs 轉換)
- Pod ↔ Node
大部分應用會透過 Service 來存取,封包流經 kube-proxy 的規則後才到達目標 Pod。搞懂這個中間層是除錯東西向問題的關鍵。
K8s 網路的四個層面
我把 K8s 網路架構拆成四個層面來理解,每一層都可能是問題的來源:
| 層面 | 包含什麼 | 常見問題 |
|---|---|---|
| 底層基礎設施 | VPC/Subnet/Firewall/Routing/NAT GW(雲端) Switch/VLAN/實體線路/靜態IP(地端) |
安全群組沒開、路由表漏設定、實體線路故障 |
| K8s 內建功能 | Service (kube-proxy)、Ingress、CoreDNS、NetworkPolicy | iptables 規則異常、DNS 解析失敗、Policy 誤擋 |
| CNI | Pod IP 分配 (IPAM)、跨節點封包處理 | IP 耗盡、隧道失效、路由宣告異常 |
| 第三方整合 | Service Mesh、Cluster Federation 等 | sidecar 設定錯誤、跨叢集通訊失效 |
不同的 CNI 使用完全不同的技術來處理跨節點通訊:
- Calico:BGP 或 IPIP 隧道
- Flannel:VXLAN 封裝
- Cilium:eBPF 直接在核心層面處理
- 雲端 CNI:直接使用雲端 VPC 的 IP 分配
系統化除錯流程
遇到網路問題時,我建議按這個順序來處理:
步驟一:畫出架構圖
不是簡單的「A → B」,而是要把中間經過的所有元件都標出來。包括 DNS 查詢、Service 轉換、節點的 iptables 規則、CNI 的隧道等。
如果某個環節你畫不出來,那就代表你對這部分還不夠了解——先補知識再除錯。
步驟二:確認方向與範圍
- 南北向還是東西向?
- 問題出在哪個層面(基礎設施 / K8s 內建 / CNI / 第三方)?
步驟三:逐層排除
以最常見的「Pod 透過 Service 無法存取另一個 Pod」為例:
| 測試 | 排除什麼 |
|---|---|
| 直接用 ClusterIP 而非 DNS 名稱 | 排除 DNS 解析問題 |
| 直接用目標 Pod IP | 排除 Service (kube-proxy) 轉換問題 |
| 從同節點的 Pod 打看看 | 排除跨節點的 CNI 問題 |
| 從節點本身打看看 | 排除發送端 Pod 的問題 |
| 檢查 NetworkPolicy | 排除防火牆規則問題 |
步驟四:抓封包分析
如果以上測試都無法定位問題,就需要抓封包了。但抓封包前要先確認:
- 問題可重現嗎? 如果不能重現,抓不到有用的資訊
- 在哪裡抓? Pod 內(不一定有 tcpdump)還是節點上?
- 怎麼過濾? 茫茫封包中如何定位目標流量
建議優先從節點上抓封包。原因:
- Pod 的映像常常沒有 tcpdump,甚至沒有 shell
- 節點上能看到幾乎所有容器的封包
- 如果知道 veth 與 Pod 的對應關係,可以針對特定 veth 介面抓,效率最高
要注意的是:如果 CNI 使用隧道(如 Calico 的 IPIP),抓到的封包外層是隧道協定,需要理解封裝格式才能正確解讀。
封包抓取後的判斷邏輯
| 觀察結果 | 可能原因 |
|---|---|
| Server 端完全沒收到封包 | 中間路由問題、防火牆阻擋、CNI 隧道故障 |
| Server 收到但沒回應 | 應用本身問題、port 沒開、readinessProbe 失敗 |
| Server 有回但 Client 沒收到 | 回程路由問題、SNAT 錯誤、conntrack 表滿了 |
| 兩端都抓不到封包 | Kernel 層面就丟了(rp_filter、conntrack、iptables DROP) |
實用的 Linux 網路工具
除了 K8s 相關的元件外,這些 Linux 工具在除錯時不可或缺:
| 工具 | 用途 |
|---|---|
ip addr / ip route |
檢查介面設定與路由表 |
tcpdump / tshark |
封包擷取與分析 |
conntrack -L |
查看連線追蹤表 |
iptables -t nat -L |
檢查 NAT 規則(kube-proxy 的轉換) |
ipvsadm -Ln |
IPVS 模式下查看後端列表 |
ethtool |
檢查網路介面的硬體層面狀態 |
sysctl net.ipv4.conf.*.rp_filter |
反向路徑過濾設定,設錯可能導致莫名丟包 |
結語:除錯心態比工具更重要
網路問題千萬不要「用嘴除錯」。每個人對網路的理解程度不同,光用口頭描述很難建立共識。最有效的做法是:
- 畫出封包流經的完整路徑
- 把自己想像成一個封包,逐步走過每個元件
- 在每個可能出問題的點做驗證,逐步縮小範圍
- 詳細記錄做過的測試和結果
這套思路不只適用於 K8s,任何複雜的分散式系統網路問題都可以套用。反覆練習之後,你會越來越快地定位問題——因為你對底層的理解會隨著每次除錯不斷加深。

發佈留言