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 | 骨架掃描

“這篇文章在說什麼”

章節骨架

  1. 基礎原理: Pod IP 獨立且跨節點無 NAT
  2. CNI 插件: 負責實際網路路由與 IP 分配
  3. ClusterIP: 叢集內部穩定的虛擬 IP
  4. NodePort: 開啟所有節點對外公開的 Port
  5. LoadBalancer: 整合雲端實體負載平衡器
  6. 常見雷區: 服務無法連通時的除錯指南

ROUND 2: DISSECTION | 血肉解剖

“憑什麼這麼說”

論證鏈

Pod 生命周期短暫且 IP 動態變化 --> 單靠 Pod IP 無法建立可靠的微服務通訊 --> 引入 Service 作為穩定的中介層 --> 根據存取範圍需求 (內部/外部/雲端),將 Service 劃分為 ClusterIP、NodePort 與 LoadBalancer。

關鍵證據

  1. Kubernetes 要求「所有 Pod 跨節點可直接互相通訊 (無 NAT)」,此需求由 Calico、Flannel 或 Cilium 等 CNI 實作。
  2. ClusterIP 是所有 Service 的基礎,透過內部 DNS (<svc>.<namespace>.svc.cluster.local) 讓內部微服務互連,隱藏了背後 Pod 的變化。
  3. LoadBalancer 與 NodePort 本質上是建立在 ClusterIP 之上的外包裝, LoadBalancer 會自動配置外部雲端服務,避免單點故障與手動開啟對外 Port 的麻煩。

隱形假設與邊界

ROUND 3: SOUL | 靈魂提取

“還能怎麼用”

跨域映射


Kubernetes Networking Explained (Architectural Deep Dive)

前言/背景

這篇文章旨在解決初學者與開發者在 Kubernetes (K8s) 環境中最常遇到的網路障礙(如 connection refusedtimeout)。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 本身不處理網路路由,而是制定了嚴格的網路規範:

  1. 所有 Pod 必須能在不透過 NAT 的情況下與其他 Pod 通訊。
  2. 所有 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 抽象層,它具有以下特性:

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:

  1. port: Service 內部的 Port。
  2. targetPort: Pod 實際接收流量的 Port。
  3. 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)

總結與結論