網路總覽

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

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

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

Kubernetes 先進的軟體定義網路 (SDN) 技術能夠在同一個地區叢集中的不同區域,為 Pod、Service 和節點轉送送封包。此外,Kubernetes 和 GCP 也會根據 Kubernetes 部署的陳述式模型以及 GCP 上的叢集設定,在每個節點上動態設定 IP 篩選規則、路由表和防火牆規則。

必備條件

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

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

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

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

叢集內的網路

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

IP 分配

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

  • 每個節點都有一個 IP 位址,是從叢集的虛擬私人雲端 (VPC) 網路指派而來。這個節點 IP 能讓 kube-proxykubelet 等控制元件連線到 Kubernetes API 伺服器。這個 IP 是節點與叢集其他部分的連接點。
  • 每個節點都有一個 IP 位址集區,GKE 會指派在該節點上執行的 Pod (預設為 /24 CIDR 區塊)。建立叢集時,您可以選擇指定 IP 的範圍。您可以利用 Pod CIDR 範圍的彈性調整功能,針對指定節點集區中的節點縮小 Pod IP 範圍。

  • 每個 Pod 都有一個 IP 位址,是從其節點的 Pod CIDR 範圍指派而來。這個 IP 位址會由所有在 Pod 內執行的容器共用,並將它們連接至在叢集中執行的其他 Pod。

  • 每個 Service 都有一個 IP 位址 (稱為 ClusterIP),是由叢集的虛擬私人雲端 (VPC) 網路指派而來。建立叢集時,您可以選擇自訂虛擬私人雲端網路。

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

Pod

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

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

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

當 Kubernetes 排程要在節點上執行某個 Pod 時,會在節點的 Linux kernel 中為這個 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 會透過 Service 提供穩定的 IP 位址。

Service

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

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

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

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

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

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

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

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

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

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

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

叢集外的網路

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

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

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

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

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

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

圖表顯示流量從節點轉送到另一節點上某個 Pod (如先前段落所述)

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

如要指定流量必須前往相同節點上的 Pod,請在 Service 資訊清單中將 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 時,負載平衡器只會將流量傳送到具有屬於該 Service 且健康狀態良好的 Pod 的節點。 負載平衡器會透過健康狀態檢查決定哪一個節點擁有合適的 Pod。

外部負載平衡器

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

技術詳細資料

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

內部負載平衡器

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

技術詳細資料

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

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

HTTP(S) 負載平衡器

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

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

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

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 與 Service 的連線

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

限制 Pod 之間的互相存取

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

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

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

限制對外部負載平衡器的存取

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

限制對 HTTP(S) 負載平衡器的存取

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

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

後續步驟

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

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

這個網頁
Kubernetes Engine 說明文件