Kubernetes 網路管理對於分散式應用程式的運作至關重要。本文從 Pod 間通訊、服務與 Pod 的互動等基本網路原則出發,探討 CNI 外掛程式的選擇與網路位址規劃。接著,文章詳述了 Kubernetes 中的服務型別,包含 ClusterIP、NodePort、LoadBalancer 和 ExternalName,並提供 YAML 設定範例。更進一步地,文章介紹了 Ingress API 與 Ingress Controller 的應用,以及如何設定 TLS 終止和路由規則。最後,文章探討了 NetworkPolicy 的設定,以確保叢集的網路安全,並簡要介紹了新一代的 Gateway API 及其優勢。

網路、網路安全與服務網格

Kubernetes有效地管理著跨多個連線系統的分散式系統。這使得連線系統之間的通訊變得至關重要,而網路是實作這一點的關鍵。瞭解Kubernetes如何促進其管理的分散式服務之間的通訊對於有效應用服務間通訊至關重要。

本章重點介紹Kubernetes對網路的基本原則以及在不同情況下應用這些概念的最佳實踐。任何關於網路的討論通常都會涉及到安全問題。在Kubernetes這個分散式系統的新世界中,傳統的網路安全邊界控制模型並未消失,但其實作方式和提供的功能發生了變化。Kubernetes提供了一種原生的網路安全策略API,它與傳統的防火牆規則非常相似。

本章的最後一部分將探討服務網格這個新的領域。服務網格技術在Kubernetes中仍處於初期階段,尚未完全成熟。

Kubernetes網路原則

瞭解Kubernetes如何利用底層網路促進服務之間的通訊對於有效地規劃應用程式架構至關重要。通常,網路話題會讓大多數人感到頭疼。我們將盡量保持簡單,因為這更多的是最佳實踐指導,而不是容器網路的課程。幸運的是,Kubernetes已經為網路制定了一些基本規則,這些規則概述了不同元件之間通訊的預期行為。

同一Pod中的容器間通訊

同一Pod中的所有容器分享相同的網路空間。這使得容器之間可以透過localhost進行通訊。這也意味著同一Pod中的容器需要暴露不同的埠。這是透過Linux名稱空間和Docker網路的力量來實作的,使用每個Pod中的一個暫停容器來託管Pod的網路。圖9-1展示了容器A如何使用localhost和容器正在監聽的埠號直接與容器B進行通訊。

Pod間通訊

所有Pod之間需要無需任何網路位址轉換(NAT)即可進行通訊。這意味著接收Pod所看到的Pod IP位址是傳送者的實際IP位址。根據所使用的網路外掛程式的不同,這一規則的實作方式也有所不同。同一節點上的Pod之間以及不同節點上的Pod之間的通訊都遵循這一規則。這也使得節點可以直接與Pod進行通訊,無需NAT。圖9-2展示了同一節點上的Pod之間以及叢集中不同節點上的Pod之間的通訊過程。

服務與Pod之間的通訊

Kubernetes中的服務代表了一個持久的IP位址和埠,它們在每個節點上都會轉發所有流量到對映到該服務的端點。在Kubernetes的不同版本中,實作這一功能的首選方法已經發生了變化,但主要有兩種方法:使用iptables或更新的IP虛擬伺服器(IPVS)。一些雲端提供商和更先進的實作允許使用根據eBPF的資料平面。目前大多數實作都使用iptables實作來在每個節點上啟用偽第4層負載平衡器。圖9-3展示了服務如何透過標籤選擇器與Pod繫結。

網路外掛程式

早期,特別興趣小組(SIG)將網路標準引導向更具可插拔性的架構,為眾多的第三方網路專案開啟了大門,這些專案在很多情況下為Kubernetes工作負載注入了增值功能。這些網路外掛程式有兩種形式。最基本的是Kubenet,它是Kubernetes原生提供的預設外掛程式。第二種型別的外掛程式遵循容器網路介面(CNI)規範,這是一種用於容器的通用外掛程式網路解決方案。

Kubenet

Kubenet是Kubernetes自帶的最基本的網路外掛程式。它提供了最簡單的網路堆積疊,使用一個名為cbr0的Linux橋接器,該橋接器是一個虛擬的乙太網對,為連線到它的Pod提供IP位址。Pod從一個跨叢集節點分佈的無類別域間路由(CIDR)範圍內取得IP位址。還有一個IP偽裝標誌應該被設定,以允許目的地在Pod CIDR範圍外的流量被偽裝。這遵循了Pod間通訊的規則,因為只有目的地在Pod CIDR範圍外的流量才會進行網路位址轉換(NAT)。

Kubenet最佳實踐
  • Kubenet允許使用簡單的網路堆積疊,並且不會佔用已經擁擠的網路上的寶貴IP位址。
  • 確保Pod CIDR範圍足夠大,以處理叢集的潛在規模和每個叢集中的Pod數量。
  • 瞭解並相應地規劃路由規則,以正確允許流量到達正確節點上的Pod。

CNI外掛程式

CNI核心專案提供了可以用來編寫外掛程式的函式庫,這些外掛程式提供了基本要求,並且可以呼叫其他外掛程式來執行各種功能。這種適應性導致了許多可以用於容器網路的CNI外掛程式,例如Microsoft Azure原生CNI和Amazon Web Services(AWS)VPC CNI外掛程式,以及來自傳統網路提供商的外掛程式,如Nuage CNI、Juniper Networks Contrail/Tungsten Fabric和VMware NSX。

Kubernetes 網路最佳實踐與服務型別詳解

Kubernetes 環境中的網路設計至關重要,需要謹慎規劃虛擬元件與實體網路之間的互動,以確保應用程式的可靠通訊。首先,選擇適當的 CNI 外掛程式是關鍵,需評估其功能是否滿足整體網路目標,包括高用性、多雲連線和網路政策支援等。

CNI 外掛程式的選擇與考量

  1. 評估功能需求:選擇具備所需功能的外掛程式,如原生高用性、多雲連線和 Kubernetes 網路政策支援。
  2. 雲端供應商相容性:若使用公有雲端服務,須確認所選 CNI 外掛程式是否與雲端供應商的軟體定義網路(SDN)相容。
  3. 網路安全與監控工具相容性:確保所選 CNI 外掛程式與現有的網路安全、監控和管理工具相容,必要時更換工具以維持可觀察性和安全性。
  4. 網路位址空間規劃:若 CNI 外掛程式未提供與 SDN 空間分離的覆寫網路,須確保有足夠的網路位址空間來處理節點 IP、Pod IP、內部負載平衡器等。

內容解密:

  • 選擇 CNI 外掛程式時需要綜合考量多項功能,包括高用性和網路政策支援。
  • 在公有雲環境中,必須確認 CNI 外掛程式與雲端供應商的 SDN 相容,以避免潛在的網路問題。
  • 網路安全和監控工具的相容性是另一個重要考量因素,必要時需更換工具以確保系統的可觀察性和安全性。
  • 正確規劃網路位址空間對於維持系統擴充套件性和升級過程中的穩定性至關重要。

Kubernetes 中的服務

在 Kubernetes 中,Pod 預設只能與同一叢集內的其他 Pod 直接通訊。服務(Service)API 提供了一個持久的 IP 和埠,自動對映到後端 Pod,解決了 Pod 動態變化帶來的存取問題。

服務型別

  1. ClusterIP:預設服務型別,提供叢集內部的持久 IP 和 DNS 名稱,用於服務發現和內部通訊。

    apiVersion: v1
    kind: Service
    metadata:
      name: web1-svc
    spec:
      selector:
        app: web1
      ports:
      - port: 80
        targetPort: 8081
    
    內容解密:
    • ClusterIP 服務提供了一個叢集內部的持久 IP 和埠對映,方便內部服務之間的通訊。
    • 透過 DNS 名稱進行服務發現,使得客戶端可以輕鬆存取服務,無需知道具體的 Pod IP。
    • 若未定義選擇器(selector),可透過端點 API 手動定義伺服器端點,用於存取非叢集內的特定服務。
  2. NodePort:在每個節點上開放一個高埠(預設範圍 30000-32767),用於從叢集外部直接存取服務。

    內容解密:
    • NodePort 服務型別允許透過節點 IP 和指定高埠存取服務,適用於本地叢集或自定義解決方案。
    • 這種方式需要手動處理外部流量的負載平衡和容錯移轉。

ClusterIP 與 NodePort 服務示意圖

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 服務型別

rectangle "selector" as node1
rectangle "iptables/IPVS" as node2
rectangle "DNS 名稱" as node3
rectangle "NodeIP:NodePort" as node4

node1 --> node2
node2 --> node3
node3 --> node4

@enduml

此圖示說明瞭 ClusterIP 和 NodePort 兩種服務型別的運作方式。

Kubernetes 中的服務型別與 Ingress 設定

Kubernetes 提供多種服務型別以滿足不同的網路需求,其中包括 ExternalNameLoadBalancer。此外,Ingress API 提供了一種更進階的流量管理機制,用於處理 HTTP 流量。

ExternalName 服務型別

ExternalName 服務型別用於將叢集內部的 DNS 名稱對應到外部的 DNS 服務。這在需要使用外部資料函式庫服務時特別有用,例如雲端供應商提供的 MongoDB 服務,其 DNS 名稱如 mymongodb.documents.azure.com。透過使用 ExternalName 服務,可以在叢集內部使用一個通用的名稱,如 prod-mongodb,這樣便於在需要時更改實際的資料函式庫服務而無需重新啟動 Pod。

ExternalName 設定範例

kind: Service
apiVersion: v1
metadata:
  name: prod-mongodb
  namespace: prod
spec:
  type: ExternalName
  externalName: mymongodb.documents.azure.com

內容解密:

  1. kindapiVersion:定義了 Kubernetes 資源的型別和版本。
  2. metadata:包含了服務的名稱和名稱空間。
  3. spec:定義了服務的規格,包括服務型別和外部名稱。
  4. type: ExternalName:指定服務型別為 ExternalName
  5. externalName:指定了外部 DNS 名稱。

LoadBalancer 服務型別

LoadBalancer 是一種特殊的服務型別,能夠與雲端供應商的負載平衡機制自動整合。這使得在不同雲端平台(如 AWS、Azure、GCE 和 OpenStack)上佈署負載平衡服務變得更加簡單和統一。透過 LoadBalancer 服務,可以建立一個公開的負載平衡服務,並且可以定義負載平衡器的 IP 地址和允許的來源範圍。

LoadBalancer 設定範例

kind: Service
apiVersion: v1
metadata:
  name: web-svc
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8081
  loadBalancerIP: 13.12.21.31
  loadBalancerSourceRanges:
  - "142.43.0.0/16"

內容解密:

  1. type: LoadBalancer:指定服務型別為 LoadBalancer
  2. selector:定義了選擇 Pod 的標籤選擇器。
  3. ports:定義了服務的連線埠和目標連線埠。
  4. loadBalancerIP:指定了負載平衡器的 IP 地址。
  5. loadBalancerSourceRanges:定義了允許存取負載平衡器的來源 IP 範圍。

Ingress 和 Ingress Controller

Ingress API 提供了一種 HTTP 等級的路由機制,能夠根據主機和路徑將流量導向後端的特定服務。例如,可以定義一個 Ingress 規則,將 www.evillgenius.com/registration 的請求轉發到 reg-svc 服務,並將 www.evillgenius.com/labaccess 的請求轉發到 labaccess-svc 服務。此外,Ingress API 也支援根據主機的路由和 TLS 終止。

Ingress 設定範例

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: labs-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts:
    - www.evillgenius.com
    secretName: secret-tls
  rules:
  - host: www.evillgenius.com
    http:
      paths:
      - path: /registration
        pathType: ImplementationSpecific
        backend:
          service:
            name: reg-svc
            port:
              number: 8088
      - path: /labaccess
        pathType: ImplementationSpecific
        backend:
          service:
            name: labaccess-svc
            port:
              number: 8089

內容解密:

  1. apiVersionkind:定義了 Ingress 資源的 API 版本和型別。
  2. metadata:包含了 Ingress 資源的名稱和註解。
  3. spec:定義了 Ingress 的規格,包括 TLS 組態和路由規則。
  4. tls:定義了 TLS 組態,包括主機名和憑證名稱。
  5. rules:定義了路由規則,包括主機名、路徑和後端服務。

Gateway API

Gateway API 是 Kubernetes SIG Network 小組開發的一個新 API,用於解決 Ingress API 的一些限制。它提供了一個更通用的代理 API,支援多種協定,並且更適合根據角色的管理模型。Gateway API 將基礎設施提供者、平台操作員和開發人員的角色分離,使得管理和組態網路流量更加靈活和可擴充套件。

Gateway API 結構圖示

此圖示展示了 Gateway API 的結構,以及它如何將基礎設施和應用程式的分離。

Gateway API 的優勢

  1. 更具表達力的 API:Gateway API 提供了一個更豐富和靈活的 API,能夠滿足不同的網路需求。
  2. 更好的擴充套件性:透過使用自定義資源定義(CRD)和控制器,Gateway API 能夠支援更多的功能和擴充套件。
  3. 多租戶支援:Gateway API 提供了一種正式的方式來支援多租戶環境,避免了路徑衝突的問題。

總之,Kubernetes 中的服務型別和 Ingress 設定提供了豐富的網路管理功能,能夠滿足不同的應用場景和需求。透過瞭解和使用這些功能,可以更好地管理和最佳化叢集內的網路流量。

Kubernetes 網路安全策略與服務管理最佳實踐

Kubernetes 的網路安全與服務管理是確保應用程式穩定執行的關鍵。本文將探討 Gateway API、Ingress Controller、NetworkPolicy 等核心概念,並提供最佳實踐建議。

Gateway API:新一代網路流量管理

Gateway API 是 Kubernetes 社群推出的新一代網路流量管理標準,目前已進入 Beta 階段。許多領先的代理服務和雲端供應商,如 Google GKE、Contour、Apache APISIX 等,都已開始實作或支援 Gateway API。相較於傳統的 Ingress API,Gateway API 提供了更靈活、更強大的流量管理功能。

服務和 Ingress Controller 最佳實踐

建立複雜的虛擬網路環境需要謹慎規劃。以下是一些最佳實踐建議:

  • 限制需要從叢集外部存取的服務數量,大多數服務應使用 ClusterIP 型別。
  • 若服務主要為 HTTP/HTTPS 服務,建議使用 Ingress API 和 Ingress Controller 進行流量路由,並提供 TLS 終止。
  • 選擇具備所需功能的 Ingress Controller,並在企業內部進行標準化。
  • 評估雲端服務供應商特定的 Ingress Controller 方案,以將基礎設施管理和負載解除安裝至叢集外部。
  • 佈署 Ingress Controller 時,確保設計為高用性和聚合效能吞吐量。

程式碼範例:Ingress 資源定義

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80

內容解密:

  1. apiVersionkind 指定了 Kubernetes 資源的版本和型別。
  2. metadata 包含了資源的中繼資料,如名稱和標籤。
  3. spec 定義了 Ingress 資源的規格,包括規則和後端服務的設定。

網路安全策略(NetworkPolicy)

Kubernetes 的 NetworkPolicy API 允許使用者定義網路層級的輸入和輸出存取控制。NetworkPolicy 物件是一種 namespaced 物件,可以針對特定的 Pod 或 Namespace 設定網路策略。

程式碼範例:預設拒絕所有輸入流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress

內容解密:

  1. podSelector 為空物件,表示選取所有的 Pod。
  2. policyTypes 指定了該 NetworkPolicy 物件適用的網路策略型別,此處為 Ingress。
  3. 由於未定義任何 Ingress 規則,所有輸入流量將被預設拒絕。

三層應用程式網路策略範例

假設有一個三層應用程式,分別為 Web、API 和 DB 層,且都佈署在同一個 Namespace 中。以下是範例的 NetworkPolicy 設定:

Web 層網路策略

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: webaccess
spec:
  podSelector:
    matchLabels:
      tier: "web"
  policyTypes:
  - Ingress
  ingress:
  - {}

API 層網路策略

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-access
spec:
  podSelector:
    matchLabels:
      tier: "api"
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          tier: "web"

DB 層網路策略

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-db-access
spec:
  podSelector:
    matchLabels:
      tier: "db"

內容解密:

  1. 每個 NetworkPolicy 物件都針對特定的 Pod 集合(根據 tier 標籤)。
  2. Web 層允許所有輸入流量。
  3. API 層僅允許來自 Web 層的輸入流量。
  4. DB 層的網路策略未明確定義輸入規則,因此預設拒絕所有輸入流量。