Kubernetes Networking Explained
原始來源與檔名:2026-06-12T093117+0800-Kubernetes Networking Explained.md
NAPKIN | 餐巾纸
餐巾紙公式
Kubernetes 網路 = (Pod IP + CNI 跨節點路由) × (Service 分流抽象化)
Kubernetes 網路透過 CNI 提供底層連通性,再透過 Service 提供穩定的存取入口與負載平衡。
一句話
Kubernetes 網路本質上就是透過 CNI 讓動態的 Pod 互相連通,並透過三種 Service (ClusterIP, NodePort, LoadBalancer) 將這些動態 IP 封裝成穩定的存取介面。
餐巾紙草圖
[ 外部請求 ]
|
v
[ LoadBalancer ] ---> 雲端負載平衡器 (Public IP)
|
v
[ NodePort ] -------> 每個節點上的固定 Port (30000-32767)
|
v
[ ClusterIP ] ------> 叢集內部的虛擬 IP (穩定入口)
|
+--> [ Pod A (動態 IP) ] \
+--> [ Pod B (動態 IP) ] -- (由 CNI 處理跨節點網路與分配IP)
ROUND 1: SKELETON | 骨架掃描
“這篇文章在說什麼”
- 核心問題: 如何理解 Kubernetes 中複雜的網路架構,包含 Pod 通訊、CNI 角色以及各種 Service 的差異?
- 核心答案: Kubernetes 網路分層運作,底層由 CNI 確保跨節點無 NAT 通訊,上層利用 ClusterIP、NodePort 與 LoadBalancer 三種 Service 為隨時生滅的 Pod 提供穩定且自動負載平衡的網路入口。
- 論證結構: 歸納型與案例型結合(先談網路基礎原理,再逐一介紹三種 Service,最後給出使用場景與常見問題)。
章節骨架
- 基礎原理: Pod IP 獨立且跨節點無 NAT
- CNI 插件: 負責實際網路路由與 IP 分配
- ClusterIP: 叢集內部穩定的虛擬 IP
- NodePort: 開啟所有節點對外公開的 Port
- LoadBalancer: 整合雲端實體負載平衡器
- 常見雷區: 服務無法連通時的除錯指南
ROUND 2: DISSECTION | 血肉解剖
“憑什麼這麼說”
論證鏈
Pod 生命周期短暫且 IP 動態變化 --> 單靠 Pod IP 無法建立可靠的微服務通訊 --> 引入 Service 作為穩定的中介層 --> 根據存取範圍需求 (內部/外部/雲端),將 Service 劃分為 ClusterIP、NodePort 與 LoadBalancer。
關鍵證據
- Kubernetes 要求「所有 Pod 跨節點可直接互相通訊 (無 NAT)」,此需求由 Calico、Flannel 或 Cilium 等 CNI 實作。
- ClusterIP 是所有 Service 的基礎,透過內部 DNS (
<svc>.<namespace>.svc.cluster.local) 讓內部微服務互連,隱藏了背後 Pod 的變化。 - LoadBalancer 與 NodePort 本質上是建立在 ClusterIP 之上的外包裝, LoadBalancer 會自動配置外部雲端服務,避免單點故障與手動開啟對外 Port 的麻煩。
隱形假設與邊界
- 隱形假設:
- 叢集中已正確安裝並設定好可運作的 CNI Plugin。
- Service 的 Selector 標籤能正確匹配到狀態為
Ready的 Pod。
- 邊界條件:
- 在裸機 (Bare-metal) 或自建環境中,未配置 MetalLB 等工具時,LoadBalancer 會無限期停留在
<pending>狀態。 - 在多個命名空間時,短網址 DNS (
<service-name>) 只能解析同命名空間的目標,跨命名空間需完整 FQDN。
- 在裸機 (Bare-metal) 或自建環境中,未配置 MetalLB 等工具時,LoadBalancer 會無限期停留在
ROUND 3: SOUL | 靈魂提取
“還能怎麼用”
- 作者盲點: 雖然提到了 Ingress,但並未深入探討 Ingress Controller 如何取代大量 LoadBalancer 以節省成本與統一管理憑證 (TLS)。
- 知識連接: 與傳統的「反向代理 (Reverse Proxy)」與「服務發現 (Service Discovery)」概念對應。Service 相當於內建的分散式反向代理 (kube-proxy 實作)。
- 行動觸發: 停止在設定檔中寫死任何 Pod 的 IP;對於本地端開發或測試叢集遭遇 External-IP
<pending>時,改用 NodePort 或安裝 MetalLB。
跨域映射
- 在 微服務架構,這叫 服務註冊與發現 (Service Registry & Discovery)
- 在 傳統基礎建設,這叫 負載平衡器 (F5 / Nginx)
Kubernetes Networking Explained (Architectural Deep Dive)
前言/背景
這篇文章旨在解決初學者與開發者在 Kubernetes (K8s) 環境中最常遇到的網路障礙(如 connection refused 或 timeout)。Kubernetes 的網路架構同時運作於三個抽象層次:Pods(容器實例)、Services(負載平衡入口)以及 Nodes(實體/虛擬節點)。文章透過拆解 CNI (Container Network Interface) 的作用與詳細分析三種核心 Service 類型,提供了一份實戰導向的架構指引。
章節詳細總結
1. Kubernetes 網路基礎:Pod 與 CNI (Container Network Interface)
在傳統 Docker 環境中,IP 通常配發給單一容器;但在 K8s 中,IP 是配發給 Pod(一組緊密耦合的容器)。當 K8s 啟動時,會建立一個內部私有網路(例如 10.244.0.0/16),叢集內的 Pod 在同節點上可直接使用此 IP 互通。
然而,Pod 是高度動態的(Ephemeral),當 Pod 重啟或被重新部署時,IP 就會改變,因此絕對不能在設定中寫死 Pod IP。
當叢集擴展到多節點時,會產生跨節點 IP 衝突問題。K8s 本身不處理網路路由,而是制定了嚴格的網路規範:
- 所有 Pod 必須能在不透過 NAT 的情況下與其他 Pod 通訊。
- 所有 Node 必須能與所有 Pod 通訊。
CNI 插件的角色:
滿足上述規範的任務交由 CNI (如 Calico, Flannel, Cilium) 負責。CNI 會為每個節點分配獨立的子網路 (例如 Node 1 拿 10.244.0.0/24,Node 2 拿 10.244.1.0/24),並設定好跨節點的路由封裝,確保網路互通。
2. Services:動態 Pod 的穩定前端
由於 Pod IP 隨時會變,K8s 引入了 Service 抽象層,它具有以下特性:
- 使用 Labels (標籤選擇器) 來綁定後端 Pod。
- 提供一組穩定的虛擬 IP (ClusterIP) 與 DNS 名稱。
- 自動在符合標籤的 Pod 之間執行負載平衡。
3. ClusterIP:叢集內部預設服務
ClusterIP 是 K8s 預設且最常見的 Service 類型,僅在叢集內部提供連線。
使用場景:專門用於內部微服務間的通訊,例如 Backend 連接 Redis 或 MySQL。
配置範例與架構細節:
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
type: ClusterIP # 這是預設值,可省略
ports:
- port: 80 # Service 在叢集內部暴露的 Port
targetPort: 8080 # 後端 Pod 容器實際 Listen 的 Port
selector:
app: backend # 尋找帶有 app=backend 標籤的 Pods
部署後,叢集內的其他元件可直接透過內部 DNS http://backend 或 <service-name>.<namespace>.svc.cluster.local 來存取,kube-proxy 會自動將流量導向健康的 Pod。
4. NodePort:在每個節點開啟通道
NodePort 會在叢集的每一個節點上,開啟一個範圍在 30000–32767 的特定 Port,並將打到該 Port 的流量轉發至對應的 Pod。
架構細節:
NodePort 涉及三個層級的 Port:
port: Service 內部的 Port。targetPort: Pod 實際接收流量的 Port。nodePort: 對外部實體網路開放的 Port (30000-32767)。
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30008 # 若省略,K8s 會自動隨機分配
selector:
app: myapp
流量機制:即使流量打到「沒有運行該應用程式 Pod」的節點 IP,kube-proxy 依然會在底層進行跳轉 (Hop),將流量導向叢集中其他健康的 Pod。
限制:直接將 NodePort 暴露於網際網路是不安全的,通常僅用於開發、Demo 或是作為實體負載平衡器 (Hardware LB) 的後方對接窗口。
5. LoadBalancer:生產環境的外部存取
LoadBalancer 會向雲端供應商 (AWS, GCP, Azure) 請求建立實體的外部負載平衡器,並自動將其連接至叢集內每個節點的 NodePort 上,最終提供一組穩定的 Public IP。
配置範例:
apiVersion: v1
kind: Service
metadata:
name: voting-app
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: voting-app
架構陷阱 (Fallback Behavior):
在無雲端控制器的環境(如裸機、地端 Kubeadm)使用 LoadBalancer 時,其 EXTERNAL-IP 會永遠顯示 <pending>。此時它只會退化成 NodePort 的行為。解決方案是安裝 MetalLB 來透過 ARP/BGP 提供等效功能。
架構決策 (Cost & Scale):
不建議為每個對外服務都建立一個 LoadBalancer (成本高昂且缺乏路由彈性)。生產環境的最佳實踐是:單一 LoadBalancer + Ingress Controller (如 Nginx, Traefik),透過 L7 Path-based 路由將流量分發給各個內部 ClusterIP。
6. 常見連線雷區 (Gotchas)
- 永遠
<pending>的 External-IP:確認叢集是否支援 Cloud Controller,或改用 NodePort/MetalLB。 - “Connection refused”:執行
kubectl get endpoints <svc>檢查。若 Endpoints 為空,代表 Service 的 Selector 標籤寫錯,找不到對應的 Pod。 - DNS 可解析但連線卡死 (Hang):Pod 存在但未處於
Ready狀態。需檢查 Pod 的readinessProbe設定。
總結與結論
- 網路分工明確:Pod 分配動態 IP,CNI 確保跨節點網路打通 (無 NAT),而 Service 則提供服務發現與穩定的負載平衡入口。
- 嚴禁硬編碼 IP:Pod 生命週期脆弱,應用程式必須依賴 K8s 內部 DNS 與 Service (ClusterIP) 來進行微服務間通訊。
- Service 選擇策略:內部通訊一律使用
ClusterIP;測試與裸機對接使用NodePort;雲端生產環境對外則使用LoadBalancer。 - L7 路由擴展:面對複雜的生產級對外服務,單靠 Service 的 L4 負載平衡是不夠的,應引入
Ingress來處理 TLS 終止、網域與路徑路由,以節省 LoadBalancer 成本並集中化網路管理。