網路總覽

本頁面提供 Google Kubernetes Engine 網路各主要部分的總覽。這些資訊適用於剛開始使用 Kubernetes 的人、經驗豐富的叢集操作者或應用程式開發人員,提供更多 Kubernetes 網路相關知識,讓他們能夠設計出更完善的應用程式或設定 Kubernetes 工作負載。

Kubernetes 可讓您以陳述式定義應用程式的部署方式、應用程式彼此之間的通訊方式、應用程式與 Kubernetes 控制層的通訊方式,以及用戶端連線到應用程式的方式。本頁面也提供 GKE 如何透過網路設定 Google Cloud Platform 服務的資訊。

如要使用 Kubernetes 自動化調度管理應用程式,您在思考應用程式及其主機的網路設計時,必須思考 Pod、服務和外部用戶端該如何進行通訊,而不是主機或 VM 要如何連線。

Kubernetes 和 GCP 會根據 Kubernetes 部署的陳述式模型以及 GCP 上的叢集設定,在每個節點上動態設定 IP 篩選規則、路由表和防火牆規則。請勿在節點上進行手動變更,因為 GKE 會覆寫這些變更,使叢集無法正常運作。只有在設定發生問題而需要除錯時,才可直接存取節點。

必備條件

本頁面使用的術語與網際網路通訊協定套件的傳輸網際網路應用程式層有關,包括 HTTPDNS,但您並不需要是這些主題的專家。

此外,如果您對 Linux 網路管理概念及 iptables 規則和轉送等公用程式有基本的瞭解,可能會比較容易理解本頁面的內容。

Kubernetes 網路模型極度仰賴 IP 位址。服務、Pod、容器和節點會透過 IP 位址和通訊埠進行通訊。Kubernetes 提供不同類型的負載平衡,以將要求導向到正確的 Pod。本主題稍後會提供這些機制的詳細說明。請牢記以下術語,在閱讀時將有所幫助:

  • ClusterIP:指派給服務的 IP 位址。在其他文件中,ClusterIP 可能稱為「叢集 IP」。這個位址在服務的生命週期內會維持不變,詳見本主題的服務一節。
  • Pod IP:指派給特定 Pod 的 IP 位址。這是一個臨時的位址,詳見本主題 Pod 一節。
  • 節點 IP:指派給特定節點的 IP 位址。

叢集內的網路

本節探討 Kubernetes 叢集內的網路,因為它與 IP 分配Pod服務有關。

IP 分配

Kubernetes 使用多種 IP 範圍,將 IP 位址指派給節點、Pod 和服務。

  • 每個節點都有一個 IP 位址,是從叢集的虛擬私人雲端 (VPC) 網路指派而來。這個節點 IP 能讓 kube-proxykubelet 等控制元件連線到 Kubernetes API 伺服器。
  • 每個 Pod 都有一個 IP 位址,是從 256 個 IP 位址範圍 (即 /24 CIDR 區塊) 中指派而來。建立叢集時,您可以選擇指定這個範圍。
  • 每個服務都有一個 IP 位址 (稱為 ClusterIP),由叢集的 VPC 網路指派。建立叢集時,您可以選擇自訂虛擬私人雲端網路。

詳情請造訪使用別名 IP 建立虛擬私人雲端原生叢集

Pod

在 Kubernetes 中,Pod 是 Kubernetes 叢集內最基本的可部署單位。一個 Pod 可執行一或多個容器。一個節點可執行零或多個 Pod。叢集中的每個節點都是節點集區的一部分。在 GKE 中,這些節點是虛擬機器,做為 Compute Engine 中的執行個體執行。

Pod 也能連結至外部儲存磁碟區及其他自訂資源。本圖表顯示執行兩個 Pod 的單一節點,這兩個 Pod 又各自連結至兩個磁碟區。

圖表顯示上方段落所述,執行兩個 Pod 的單一節點

當 Kubernetes 排程要在節點上執行某個 Pod 時,會在節點的 Linux 核心中為這個 Pod 建立網路命名空間。這個網路命名空間會連接節點的實體網路介面 (例如 eth0),而 Pod 則使用虛擬網路介面,讓封包傳入或傳出 Pod。在節點的根網路命名空間中,關聯的虛擬網路介面會連接到 Linux 橋接介面,允許在同一個節點上的 Pod 互相通訊。Pod 也能使用相同的虛擬介面,將封包傳送到節點外。

Kubernetes 會從節點上專為 Pod 預留的位址範圍,將 IP 位址 (Pod IP) 指派給 Pod 的網路命名空間中的虛擬網路介面。這個位址範圍是指派給 Pod 叢集的 IP 位址範圍中的一部分,您可以在建立叢集時進行相關設定。

在 Pod 中執行的容器會使用 Pod 的網路命名空間。從容器的角度來看,Pod 像是一個具有網路介面的實體機器。Pod 中的所有容器都會看到同一個網路介面。 每個容器的 localhost 都會透過 Pod 連線至節點的實體網路介面,例如 eth0

請注意:此連接性差別很大,具體取決於您使用 GKE 的原生 CNI 或選擇使用 Calico 的實作方式 (在建立叢集時啟用網路政策)。

  • 如果您使用 GKE 的 CNI,veth pair 的一端會連結到在其命名空間的 Pod,另一端則連接到 Linux 橋接裝置 cbr0。在這種情況下,下列指令會顯示連結到 cbr0 的各種 Pod 的 MAC 位址︰

    arp -n
    

    此外,叫用工具箱容器中的下列各項會顯示連結到 cbr0 的每一個 veth pair 的根命名空間端︰

    brctl show cbr0
    
  • 如果啟用了網路政策,veth pair 的一端會連結到 Pod,另一端則連結到 eth0。在這種情況下,下列指令會顯示連結到不同 veth 裝置的各種 Pod MAC 位址。

    arp -n
    

    此外,叫用工具箱容器中的下列項目會顯示並沒有稱為 cbr0 的 Linux 橋接裝置︰

    brctl show
    

促成叢集內部轉寄的 iptables 規則隨情況而異。進行連線問題的疑難排解時,必須牢記這些區別。

根據預設,每個 Pod 都可以存取同一個叢集中,在所有節點上執行的所有 Pod,但您可以限制 Pod 之間的互相存取。Kubernetes 會定期拆散 Pod 再重新建立。這會在變更 Pod 的陳述式設定或變更容器的映像檔,或是節點無法使用時,在升級節點集區時發生。因此,Pod 的 IP 位址算是一個實作細節,請勿仰賴這個設定。Kubernetes 會透過服務提供穩定的 IP 位址。

服務

在 Kubernetes 中,您可以將任意鍵/值組合 (稱為標籤) 指派給任何 Kubernetes 資源。Kubernetes 使用標籤將多個相關的 Pod 組合成一個邏輯單元,這個邏輯單元即稱為「服務」。服務有一個穩定的 IP 位址和數個通訊埠,並會在這組 Pod 之間提供負載平衡,前提是這些 Pod 的標籤符合您在建立服務時,在標籤選取器中定義的所有標籤。

以下圖表顯示兩個不同的服務,各自由多個 Pod 構成。圖表中的每個 Pod 都有 app=demo 標籤,但其他的標籤卻都不同。「前端」服務配對具有 app=democomponent=frontend 的所有 Pod,「使用者」服務則配對具有 app=democomponent=users 的所有 Pod。用戶端 Pod 不完全符合這兩個服務選取器,因此,它不屬於任何一個服務的一部分。不過,用戶端 Pod 可以與服務進行通訊,因為它們在同一個叢集中執行。

圖表顯示之前段落所述,兩個獨立的服務

Kubernetes 會為每個新建立的服務指派一個穩定可靠的 IP 位址 (ClusterIP),這個 IP 位址來自叢集的可用服務 IP 位址集區。Kubernetes 也會新增 DNS 項目,以將主機名稱指派給 ClusterIP。叢集內的 ClusterIP 與主機名稱不能重複,且在服務的整個生命週期中都不會變更,只有在從叢集的設定中刪除服務時,Kubernetes 才會釋出 ClusterIP 和主機名稱。您可以透過 ClusterIP 或服務的主機名稱,連至執行應用程式、健康狀態良好的 Pod。

乍看之下,服務似乎會造成應用程式單點故障。不過,Kubernetes 會盡可能地使流量均勻分散在整組 Pod 中,而這些 Pod 又是在眾多節點上執行,這樣叢集就能承受影響一或多個 (但非全部) 節點的服務中斷。

Kubernetes 使用 kube-proxy 元件管理 Pod 與服務之間的互相連線,該元件會在每個節點上執行。kube-proxy 不是 內置 Proxy,而是輸出型負載平衡控制器,其會在節點的 iptables 子系統新增及移除目的地 NAT (DNAT) 規則,以監控 Kubernetes API 伺服器,並持續將 ClusterIP 對應至健康狀態良好的 Pod。在 Pod 中執行的容器將流量傳送至服務的 ClusterIP 時,節點會隨機選取一個 Pod,並將流量轉送至該 Pod。

設定服務時,您可以選擇透過定義 porttargetPort 的值,重新對應其接聽埠。

  • port 是用戶端連至應用程式的位置。
  • targetPort 是應用程式實際聆聽 Pod 內流量的通訊埠。

kube-proxy 透過在節點上新增及移除 iptables 規則,來管理這個通訊埠的重新對應。

這個圖表說明在不同節點上從用戶端 Pod 到伺服器 Pod 的流量。用戶端可在 172.16.12.100:80 連線到服務。Kubernetes API 伺服器會維護執行應用程式的 Pod 清單。每個節點上的 kube-proxy 程序都會使用這個清單來建立 iptables 規則,將流量導向適當的 Pod (例如 10.255.255.202:8080)。用戶端 Pod 不需要知道叢集的拓撲,或其中個別 Pod 或容器的任何詳細資料。

圖表說明之前段落所述,連線至服務並轉送至 Pod 的用戶端

叢集外的網路

本節說明來自叢集外的流量如何到達在 Kubernetes 叢集內執行的應用程式。在設計叢集的應用程式和工作負載時,這資訊非常重要。

您已瞭解 Kubernetes 如何使用服務,為 Pod 內執行的應用程式提供穩定的 IP 位址。根據預設,Pod 不會公開發佈外部 IP 位址,因為 kube-proxy 會管理每個節點上的所有流量。Pod 及其容器可以自由地通訊,但叢集外的連線無法存取服務。舉例來說,在上一個插圖中,叢集外的用戶端無法透過其 ClusterIP 存取前端服務。

GKE 提供三種不同類型的負載平衡器來控制存取權,並使連入流量盡可能地在叢集中均勻分散。您可以將一個服務設定為同時使用多種負載平衡器。

  • 外部負載平衡器管理來自叢集外以及 GCP 虛擬私人雲端 (VPC) 網路外的流量。外部負載平衡器使用與 GCP 網路關聯的轉送規則,將流量轉送至 Kubernetes 節點。
  • 內部負載平衡器則管理來自同一個 VPC 網路內的流量。如同外部負載平衡器,內部負載平衡器使用與 GCP 網路關聯的轉送規則,將流量轉送至 Kubernetes 節點。
  • HTTP(S) 負載平衡器是 HTTP(S) 流量專用的特殊外部負載平衡器。HTTP(S) 負載平衡器不使用轉送規則,而是使用輸入資源將流量轉送至 Kubernetes 節點。

當流量抵達 Kubernetes 節點時,無論使用哪種負載平衡器,都會以同樣的方式處理流量。負載平衡器不知道叢集中的哪些節點正在執行 Pod 以提供服務。負載平衡器會將叢集中所有節點的流量進行平衡,包含未執行相關 Pod 的節點。在地區叢集上,負載會分散在叢集所在地區中,所有區域的所有節點間。流量轉送至節點時,節點會將流量轉送到在同一個或不同節點上執行的 Pod。節點使用 kube-proxy 在節點上管理的 iptables 規則,將流量轉寄到隨機選擇的 Pod。

在下圖中,網路負載平衡器將流量傳送到中間節點,該流量會被轉送到第一個節點上的某個 Pod。

顯示流量從節點轉送到另一節點上某個 Pod 的圖形,如前一段所述

負載平衡器將流量傳送到一個節點時,流量可能會被轉送到不同節點上的 Pod。這樣會需要額外的網路躍點。如果您希望避免使用額外的躍點,可以指定流量必須前往最初收到該流量的同一個節點上的 Pod。

如要指定流量必須前往相同節點上的 Pod,請在服務資訊清單中將 externalTrafficPolicy 設定為 Local

apiVersion: v1
kind: Service
metadata:
  name: my-lb-service
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  selector:
    app: demo
    component: users
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

externalTrafficPolicy 設定為 Local時,負載平衡器只會將流量傳送到具有屬於該服務、健康狀態良好的 Pod 的節點。負載平衡器使用健康狀態檢查決定哪一個節點擁有合適的 Pod。

外部負載平衡器

若要讓服務可從叢集外及虛擬私人雲端網路外進行存取,您可以在定義服務時,將服務的 type 欄位設定為 LoadBalancer,而將服務設定為 LoadBalancer。接著,GKE 會在服務的前面佈建網路負載平衡器。網路負載平衡器知道叢集中的所有節點,並會設定 VPC 網路的防火牆規則,允許使用服務的外部 IP 位址從 VPC 外連線至服務。您可以為服務指派一個靜態外部 IP 位址。詳情請造訪使用靜態 IP 位址設定網域名稱

技術詳細資料

使用外部負載平衡器時,抵達的流量一開始會透過與 GCP 網路關聯的轉送規則轉送至節點。流量抵達節點後,節點會使用其 iptables NAT 資料表來選擇 Pod。kube-proxy 會管理節點上的 iptables 規則。

內部負載平衡器

針對需要從相同 VPC 網路內連至叢集的流量,您可以設定服務以佈建內部負載平衡器。內部負載平衡器會從叢集的 VPC 子網路選擇 IP 位址,而不是從外部 IP 位址進行選擇。VPC 網路內的應用程式或服務可以使用這個 IP 位址,與叢集內的服務通訊。

技術詳細資料

內部負載平衡功能由 GCP 提供。當流量抵達特定節點時,該節點會使用其 iptables NAT 資料表為要求選擇 Pod,不論 Pod 是否位於不同的節點。 kube-proxy 會管理節點上的 iptables 規則。

如要進一步瞭解內部負載平衡器,請造訪內部負載平衡器說明文件

HTTP(S) 負載平衡器

許多應用程式 (例如符合 REST 樣式的網路服務 API) 都是透過 HTTP(S) 進行通訊。您可以透過 Kubernetes 輸入資源,讓 VPC 網路外的用戶端存取這類應用程式。輸入資源可讓您將主機名稱和 URL 路徑對應至叢集內的服務。使用 HTTP(S) 負載平衡器時,您必須將服務設定為使用 NodePort 以及 ClusterIP。當流量在位於 NodePort 的節點 IP 存取服務時,GKE 會為該服務將流量轉送至健康狀態良好的 Pod。您可以指定 NodePort,或讓 GKE 指派隨機的未使用通訊埠。

建立輸入資源時,GKE 會在 GCP 專案中佈建 HTTP(S) 負載平衡器。負載平衡器會將要求傳送至位於 NodePort 的節點 IP 位址。流量抵達節點後,節點會使用其 iptables NAT 資料表來選擇 Pod。kube-proxy 會管理節點上的 iptables 規則。

這個輸入定義會將 demo.example.com 的流量轉送至通訊埠 80 上名為 frontend 的服務,並將 demo-backend.example.com 轉送至通訊埠 8080 上名為 users 的服務。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: demo
spec:
  rules:
  - host: demo.example.com
    http:
      paths:
      - backend:
          serviceName: frontend
          servicePort: 80
  - host: demo-backend.example.com
    http:
      paths:
      - backend:
          serviceName: users
          servicePort: 8080

詳情請造訪 Google Cloud Platform 上的輸入

技術詳細資料

建立輸入物件時,GKE 輸入控制器會根據輸入資訊清單和關聯服務資訊清單中的規則,設定 GCP HTTP(S) 負載平衡器。用戶端會將要求傳送至 HTTP(S) 負載平衡器。負載平衡器是實際的 Proxy,會選擇節點並將要求轉送至該節點的 NodeIP:NodePort 組合。節點會使用其 iptables NAT 資料表來選擇 Pod。 kube-proxy 會管理節點上的 iptables 規則。

限制連到 Pod 與服務的連線

根據預設,在相同叢集內執行的所有 Pod 皆可自由通訊。不過,您可以依照您的需求,以不同的方式限制叢集內的連線。

限制 Pod 之間的互相存取

您可以使用網路政策,限制 Pod 之間的互相存取。網路政策定義可讓您任意組合標籤、IP 範圍和通訊埠編號,以限制 Pod 的輸入輸出。預設並未設定網路政策,因此允許叢集中 Pod 彼此之間的所有流量。您在命名空間中建立第一個網路政策之後,就會拒絕所有其他流量。

如要進一步瞭解如何指定政策,請造訪網路政策

建立網路政策後,您必須明確地為叢集啟用政策。 詳情請造訪設定應用程式的網路政策

將存取限制在外部負載平衡器

如果服務使用外部負載平衡器,根據預設,來自任何外部 IP 位址的流量都可以存取服務。您可以在設定服務時設定 loadBalancerSourceRanges 選項,以限制哪些 IP 位址範圍可以存取叢集內的端點。您可以指定多個範圍,也可以隨時更新正在執行的服務的設定。在每個節點上執行的 kube-proxy 執行個體會設定該節點的 iptables 規則,拒絕不在指定的 loadBalancerSourceRanges 中的所有流量。服務不會建立任何 VPC 防火牆規則。

將存取限制在 HTTP(S) 負載平衡器

如果服務使用HTTP(S) 負載平衡器,您可以使用 Cloud Armor 安全性政策,限制哪些外部 IP 位址可以存取服務,以及因安全性政策使存取遭拒時要傳回哪些回覆。您可以設定 Stackdriver Logging 來記錄這些互動的資訊。

如果 Cloud Armor 安全性政策不夠精細,您可以在端點上啟用 Cloud Identity-Aware Proxy,為應用程式導入使用者驗證與授權。詳情請造訪設定 Cloud IAP 的詳細教學課程

後續步驟

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Kubernetes Engine 說明文件