虛擬 IP 和服務代理

Kubernetes 叢集中的每個 節點都執行一個 kube-proxy(除非您已部署了自定義元件來替代 kube-proxy)。

kube-proxy 元件負責為 type 為除 ExternalName 之外的 Service 實現虛擬 IP 機制。kube-proxy 的每個例項都會監視 Kubernetes 控制平面,以便新增和移除 Service 和 EndpointSlice 物件。對於每個 Service,kube-proxy 會呼叫適當的 API(取決於 kube-proxy 模式)來配置節點,以捕獲到 Service 的 clusterIPport 的流量,並將該流量重定向到 Service 的某個端點(通常是 Pod,也可能是使用者提供的任意 IP 地址)。一個控制迴圈確保每個節點上的規則都與 API 伺服器指示的 Service 和 EndpointSlice 狀態可靠地同步。

使用 iptables 模式的 Service 虛擬 IP 機制

有時會有人問,為什麼 Kubernetes 依賴代理來將入站流量轉發到後端。其他方法呢?例如,是否可以配置具有多個 A 記錄(IPv6 為 AAAA)的 DNS 記錄,並依賴輪詢名稱解析?

使用代理來實現 Service 有幾個原因

  • DNS 實現長期以來都未能遵守記錄 TTL,並且會在名稱查詢應過期後繼續快取結果。
  • 有些應用程式只執行一次 DNS 查詢,並無限期地快取結果。
  • 即使應用程式和庫進行了正確的重新解析,DNS 記錄的低 TTL 或零 TTL 也會給 DNS 帶來很高的負載,從而難以管理。

在本頁稍後,您可以閱讀有關各種 kube-proxy 實現的工作原理。總的來說,您應該注意,當執行 kube-proxy 時,核心級別規則可能會被修改(例如,可能會建立 iptables 規則),這些規則在某些情況下可能不會被清理,直到您重啟。因此,只有理解了在計算機上執行低級別、特權網路代理服務所帶來的後果的管理員才能執行 kube-proxy。儘管 kube-proxy 可執行檔案支援 cleanup 函式,但該函式並非官方功能,因此只能按原樣使用。

此參考中的一些詳細資訊會引用一個示例:一個無狀態影像處理工作負載的後端 Pod,執行三個副本。這些副本是可互換的——前端不關心使用哪個後端。雖然構成後端集合的實際 Pod 可能會發生變化,但前端客戶端不需要知道這一點,也不需要自己跟蹤後端集合。

代理模式

kube-proxy 以不同的模式啟動,這由其配置決定。

在 Linux 節點上,kube-proxy 的可用模式包括

iptables
一種模式,其中 kube-proxy 使用 iptables 配置資料包轉發規則。
ipvs
一種模式,其中 kube-proxy 使用 ipvs 配置資料包轉發規則。
nftables
一種模式,其中 kube-proxy 使用 nftables 配置資料包轉發規則。

Windows 上 kube-proxy 只有一種可用模式

kernelspace
一種模式,其中 kube-proxy 在 Windows 核心中配置資料包轉發規則

iptables 代理模式

此代理模式僅在 Linux 節點上可用。

在此模式下,kube-proxy 使用核心 netfilter 子系統的 iptables API 配置資料包轉發規則。對於每個端點,它會安裝 iptables 規則,這些規則預設會隨機選擇一個後端 Pod。

示例

例如,考慮頁面前面描述的影像處理應用程式。當建立後端 Service 時,Kubernetes 控制平面會分配一個虛擬 IP 地址,例如 10.0.0.1。在此示例中,假設 Service 埠為 1234。叢集中的所有 kube-proxy 例項都會觀察到新 Service 的建立。

當節點上的 kube-proxy 看到新 Service 時,它會安裝一系列 iptables 規則,將流量從虛擬 IP 地址重定向到為每個 Service 定義的更多 iptables 規則。每個 Service 的規則連結到每個後端端點的進一步規則,而每個端點的規則(使用目標 NAT)將流量重定向到後端。

當客戶端連線到 Service 的虛擬 IP 地址時,iptables 規則會生效。選擇一個後端(基於會話親和性或隨機選擇),並將資料包重定向到後端,而無需重寫客戶端 IP 地址。

當流量透過 type: NodePort Service 或負載均衡器進入時,會執行相同的基本流程,儘管在這些情況下客戶端 IP 地址確實會被更改。

最佳化 iptables 模式的效能

在 iptables 模式下,kube-proxy 為每個 Service 建立少量 iptables 規則,為每個端點 IP 地址建立少量 iptables 規則。在擁有數萬個 Pod 和 Service 的叢集中,這意味著數萬條 iptables 規則,並且當 Service(或其 EndpointSlices)發生更改時,kube-proxy 可能需要很長時間才能更新核心中的規則。您可以透過 kube-proxy 配置檔案iptables 部分的選項來調整 kube-proxy 的同步行為(透過 kube-proxy --config <path> 指定)。

...
iptables:
  minSyncPeriod: 1s
  syncPeriod: 30s
...
minSyncPeriod

minSyncPeriod 引數設定在嘗試將 iptables 規則與核心重新同步之間的最小持續時間。如果設定為 0s,則 kube-proxy 每次更改任何 Service 或 EndpointSlice 時都會立即同步規則。這在非常小的叢集中效果很好,但在短時間內發生大量更改時會導致大量重複工作。例如,如果您有一個由 100 個 Pod 的 Deployment 支援的 Service,並且刪除了該 Deployment,那麼在 minSyncPeriod: 0s 的情況下,kube-proxy 將逐個從 iptables 規則中刪除 Service 的端點,總共會進行 100 次更新。透過更大的 minSyncPeriod,多個 Pod 刪除事件將聚合在一起,因此 kube-proxy 可能最終只進行 5 次更新,每次刪除 20 個端點,這在 CPU 使用方面效率更高,並且會更快地同步完整的更改集。

minSyncPeriod 的值越大,可以聚合的工作就越多,但缺點是每次更改最多可能需要等待完整的 minSyncPeriod 才能得到處理,這意味著 iptables 規則花費更長的時間與當前 API 伺服器狀態不同步。

預設值 1s 在大多數叢集中應該效果很好,但在非常大的叢集中,可能需要將其設定為更大的值。特別是,如果 kube-proxysync_proxy_rules_duration_seconds 指標顯示平均時間遠大於 1 秒,那麼提高 minSyncPeriod 可能會使更新更有效。

更新舊版 minSyncPeriod 配置

舊版本的 kube-proxy 在每次同步時都會更新所有 Service 的所有規則;這導致大型叢集出現效能問題(更新延遲),並且推薦的解決方案是設定更大的 minSyncPeriod。自 Kubernetes v1.28 起,kube-proxy 的 iptables 模式使用更精簡的方法,僅在 Service 或 EndpointSlices 實際發生更改時才進行更新。

如果您之前覆蓋了 minSyncPeriod,則應嘗試刪除該覆蓋,讓 kube-proxy 使用預設值(1s)或至少是升級前所用值的一個較小值。

如果您執行的不是 Kubernetes 1.34 的 kube-proxy,請檢查您實際執行的版本相關的行為和建議。

syncPeriod

syncPeriod 引數控制一些與 Service 和 EndpointSlice 的單獨更改不直接相關的同步操作。特別是,它控制 kube-proxy 注意到外部元件何時干擾了 kube-proxy 的 iptables 規則。在大型叢集中,kube-proxy 還每 syncPeriod 執行一次某些清理操作,以避免不必要的工作。

在大多數情況下,增加 syncPeriod 不會明顯影響效能,但在過去,將其設定為非常大的值(例如 1h)有時很有用。現在不推薦這樣做,並且很可能會損害功能而非提高效能。

IPVS 代理模式

此代理模式僅在 Linux 節點上可用。

ipvs 模式下,kube-proxy 使用核心 IPVS 和 iptables API 來建立規則,將流量從 Service IP 重定向到端點 IP。

IPVS 代理模式基於 netfilter 鉤子函式,該函式類似於 iptables 模式,但使用雜湊表作為底層資料結構並在核心空間工作。這意味著 IPVS 模式下的 kube-proxy 相比 iptables 模式下的 kube-proxy 具有更低的延遲來重定向流量,並在同步代理規則時具有更好的效能。與 iptables 代理模式相比,IPVS 模式還支援更高的網路流量吞吐量。

IPVS 為將流量負載均衡到後端 Pod 提供了更多選項,這些選項是

  • rr (Round Robin):流量在後端伺服器之間平均分配。

  • wrr (Weighted Round Robin):流量根據伺服器的權重路由到後端伺服器。權重較高的伺服器接收新連線並獲得比權重較低的伺服器更多的請求。

  • lc (Least Connection):將更多流量分配給連線數較少的伺服器。

  • wlc (Weighted Least Connection):將更多流量路由到連線數相對其權重較少的伺服器,即連線數除以權重。

  • lblc (Locality based Least Connection):發往同一 IP 地址的流量會被髮送到同一後端伺服器,前提是該伺服器未過載且可用;否則,流量會被髮送到連線數較少的伺服器,並保留供將來分配。

  • lblcr (Locality Based Least Connection with Replication):發往同一 IP 地址的流量會被髮送到連線數最少的伺服器。如果所有後端伺服器都過載,它會選擇一個連線數較少的伺服器並將其新增到目標集。如果目標集在指定時間內未更改,則會從集中移除負載最高的伺服器,以避免高度複製。

  • sh (Source Hashing):透過查詢基於源 IP 地址的靜態分配的雜湊表來將流量傳送到後端伺服器。

  • dh (Destination Hashing):透過查詢基於目標地址的靜態分配的雜湊表來將流量傳送到後端伺服器。

  • sed (Shortest Expected Delay):將流量轉發到預期延遲最短的後端伺服器。預期延遲為 (C + 1) / U,其中 C 是伺服器上的連線數,U 是伺服器的固定服務速率(權重)。

  • nq (Never Queue):如果存在空閒伺服器,則將流量傳送到該伺服器,而不是等待快速的伺服器;如果所有伺服器都忙,則該演算法將回退到 sed 行為。

  • mh (Maglev Hashing):根據Google 的 Maglev hashing 演算法分配入站作業。此排程程式有兩個標誌:mh-fallback,它在選定的伺服器不可用時啟用回退到其他伺服器,以及 mh-port,它將源埠號新增到雜湊計算中。使用 mh 時,kube-proxy 始終設定 mh-port 標誌,而不啟用 mh-fallback 標誌。在 proxy-mode=ipvs 中,mh 的工作方式類似於源雜湊(sh),但增加了埠。

這些排程演算法透過 kube-proxy 配置中的 ipvs.scheduler 欄位進行配置。

使用 IPVS 模式的 Service 虛擬 IP 地址機制

nftables 代理模式

特性狀態: Kubernetes v1.33 [stable] (預設啟用:true)

此代理模式僅在 Linux 節點上可用,並且需要核心 5.13 或更高版本。

在此模式下,kube-proxy 使用核心 netfilter 子系統的 nftables API 配置資料包轉發規則。對於每個端點,它會安裝 nftables 規則,這些規則預設會隨機選擇一個後端 Pod。

nftables API 是 iptables API 的後繼者,旨在提供比 iptables 更好的效能和可擴充套件性。nftables 代理模式能夠比 iptables 模式更快、更有效地處理 Service 端點的更改,並且還能更有效地在核心中處理資料包(儘管這僅在擁有數萬個 Service 的叢集中才顯現出來)。

截至 Kubernetes 1.34,nftables 模式仍然相對較新,並且可能與所有網路外掛不相容;請參閱您的網路外掛文件。

iptables 模式遷移到 nftables

希望從預設的 iptables 模式切換到 nftables 模式的使用者應注意,在 nftables 模式下,某些功能的工作方式略有不同。

  • NodePort 介面:在 iptables 模式下,預設情況下,NodePort Service 在所有本地 IP 地址上都可訪問。這通常不是使用者想要的,因此 nftables 模式預設為 --nodeport-addresses primary,這意味著使用 type: NodePort 的 Service 僅在節點的 IPv4 和/或 IPv6 主要地址上可訪問。您可以透過為該選項指定顯式值來覆蓋此設定:例如,--nodeport-addresses 0.0.0.0/0 監聽所有(本地)IPv4 IP。

  • type: NodePort **Service on 127.0.0.1**:在 iptables 模式下,如果 --nodeport-addresses 範圍包含 127.0.0.1(並且未傳遞選項 --iptables-localhost-nodeports false),則 type: NodePort 的 Service 甚至在“localhost”(127.0.0.1)上也可訪問。在 nftables 模式(和 ipvs 模式)下,這將不起作用。如果您不確定是否依賴此功能,可以檢查 kube-proxyiptables_localhost_nodeports_accepted_packets_total 指標;如果它非零,則意味著某個客戶端已透過 localhost/loopback 連線到 type: NodePort Service。

  • NodePort 與防火牆的互動kube-proxyiptables 模式試圖與過於激進的防火牆相容;對於每個 type: NodePort Service,它會新增規則以接受該埠上的入站流量,以防流量被防火牆阻止。這種方法與基於 nftables 的防火牆不相容,因此 kube-proxynftables 模式在此不做任何處理;如果您有本地防火牆,必須確保它已正確配置以允許 Kubernetes 流量透過(例如,允許 NodePort 範圍上的入站流量)。

  • Conntrack bug 解決方法:Linux 核心 6.1 之前的版本存在一個 bug,可能導致到 Service IP 的長期 TCP 連線以“Connection reset by peer”錯誤關閉。kube-proxyiptables 模式為此 bug 安裝瞭解決方法,但後來發現此解決方法會在某些叢集中導致其他問題。nftables 模式預設不安裝任何解決方法,但您可以檢查 kube-proxyiptables_ct_state_invalid_dropped_packets_total 指標,以檢視您的叢集是否依賴於此解決方法,如果是,您可以使用選項 --conntrack-tcp-be-liberal 執行 kube-proxy 來解決 nftables 模式下的問題。

kernelspace 代理模式

此代理模式僅在 Windows 節點上可用。

kube-proxy 在 Windows虛擬過濾平臺 (VFP) 中配置資料包過濾規則,這是 Windows vSwitch 的一個擴充套件。這些規則處理節點級別虛擬網路中的封裝資料包,並重寫資料包,以使目標 IP 地址(和第 2 層資訊)正確,以便將資料包路由到正確的目標。Windows VFP 類似於 Linux 的 nftablesiptables 等工具。Windows VFP 擴充套件了Hyper-V Switch,最初是為了支援虛擬機器網路而實現的。

當節點上的 Pod 將流量傳送到虛擬 IP 地址,並且 kube-proxy 選擇了一個不同節點上的 Pod 作為負載均衡目標時,kernelspace 代理模式會將該資料包重寫為目標是目標後端 Pod。Windows主機網路服務 (HNS) 確保配置了資料包重寫規則,以便返回流量看起來像是來自虛擬 IP 地址,而不是特定的後端 Pod。

kernelspace 模式的直接伺服器返回

特性狀態: Kubernetes v1.34 [穩定] (預設啟用:true)

作為基本操作的替代方案,託管 Service 後端 Pod 的節點可以直接應用資料包重寫,而不是將此負擔放在執行客戶端 Pod 的節點上。這稱為直接伺服器返回

要使用此功能,您必須執行 kube-proxy 並使用 --enable-dsr 命令列引數**並**啟用 WinDSR 功能門

直接伺服器返回還可以最佳化 Pod 返回流量的情況,即使兩個 Pod 都在同一節點上執行。

會話親和性

在這些代理模型中,發往 Service IP:Port 的流量被代理到適當的後端,而客戶端對此一無所知 Kubernetes 或 Services 或 Pods。

如果您想確保來自特定客戶端的連線每次都傳遞到同一 Pod,可以透過將 Service 的 .spec.sessionAffinity 設定為 ClientIP 來基於客戶端 IP 地址選擇會話親和性(預設為 None)。

會話粘性超時

您還可以透過為 Service 適當地設定 .spec.sessionAffinityConfig.clientIP.timeoutSeconds 來設定最大會話粘性時間。(預設值為 10800,相當於 3 小時)。

分配 IP 地址給 Service

與實際路由到固定目標的 Pod IP 地址不同,Service IP 實際上不是由單個主機響應的。相反,kube-proxy 使用資料包處理邏輯(如 Linux iptables)來定義虛擬 IP 地址,這些地址會根據需要進行透明重定向。

當客戶端連線到 VIP 時,它們的流量會自動傳輸到適當的端點。Service 的環境變數和 DNS 實際上是根據 Service 的虛擬 IP 地址(和埠)填充的。

避免衝突

Kubernetes 的主要理念之一是您不應面臨因自身過錯而導致操作失敗的情況。對於 Service 資源的設計,這意味著不讓您選擇自己的 IP 地址,因為該選擇可能與其他人的選擇發生衝突。這是隔離失敗。

為了讓您為 Service 選擇 IP 地址,我們必須確保沒有兩個 Service 會發生衝突。Kubernetes 透過從為 API Server 配置的 service-cluster-ip-range CIDR 範圍中為每個 Service 分配其自己的 IP 地址來做到這一點。

IP 地址分配跟蹤

為了確保每個 Service 獲得唯一的 IP 地址,一個內部分配器在建立每個 Service 之前,會原子地更新 etcd 中的全域性分配對映。對映物件必須存在於登錄檔中,Service 才能獲得 IP 地址分配,否則建立將失敗並顯示一條訊息,表明無法分配 IP 地址。

在控制平面中,一個後臺控制器負責建立該對映(支援從使用記憶體鎖定的舊版本 Kubernetes 遷移)。Kubernetes 還使用控制器來檢查無效分配(例如,由於管理員干預)以及清理不再被任何 Service 使用的已分配 IP 地址。

使用 Kubernetes API 進行 IP 地址分配跟蹤

特性狀態: Kubernetes v1.33 [stable] (預設啟用:true)

控制平面用一個修改後的實現替換現有的 etcd 分配器,該實現使用 IPAddress 和 ServiceCIDR 物件而不是內部全域性分配對映。與 Service 關聯的每個叢集 IP 地址隨後引用一個 IPAddress 物件。

啟用功能門還會用一個替代項替換後臺控制器,該替代項處理 IPAddress 物件並支援從舊分配器模型遷移。Kubernetes 1.34 不支援從 IPAddress 物件遷移到內部分配對映。

修改後分配器的一個主要優點是它消除了可用於 Service 叢集 IP 地址的 IP 地址範圍的大小限制。啟用 MultiCIDRServiceAllocator 後,IPv4 沒有限制,對於 IPv6,您可以使用 /64 或更小的 IP 地址網路掩碼(與舊實現的 /108 相反)。

透過 API 使 IP 地址分配可用意味著您作為叢集管理員可以允許使用者檢查分配給其 Service 的 IP 地址。Kubernetes 擴充套件(如 Gateway API)可以使用 IPAddress API 來擴充套件 Kubernetes 的固有網路功能。

以下是使用者查詢 IP 地址的簡短示例

kubectl get services
NAME         TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   2001:db8:1:2::1   <none>        443/TCP   3d1h
kubectl get ipaddresses
NAME              PARENTREF
2001:db8:1:2::1   services/default/kubernetes
2001:db8:1:2::a   services/kube-system/kube-dns

Kubernetes 還允許使用者使用 ServiceCIDR 物件動態定義 Service 的可用 IP 範圍。在啟動期間,一個名為 kubernetes 的預設 ServiceCIDR 物件會從 kube-apiserver 的 --service-cluster-ip-range 命令列引數值建立。

kubectl get servicecidrs
NAME         CIDRS         AGE
kubernetes   10.96.0.0/28  17m

使用者可以建立或刪除新的 ServiceCIDR 物件來管理 Service 的可用 IP 範圍。

cat <<'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: ServiceCIDR
metadata:
  name: newservicecidr
spec:
  cidrs:
  - 10.96.0.0/24
EOF
servicecidr.networking.k8s.io/newcidr1 created
kubectl get servicecidrs
NAME             CIDRS         AGE
kubernetes       10.96.0.0/28  17m
newservicecidr   10.96.0.0/24  7m

Kubernetes 叢集的發行版或管理員可能希望控制新增到叢集的新 Service CIDR 不會與其他屬於特定 IP 範圍的網路發生重疊,或者只是簡單地保留每個叢集只有一個 ServiceCIDR 的現有行為。實現此目的的驗證 Admission 策略示例是

---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
  name: "servicecidrs-default"
spec:
  failurePolicy: Fail
  matchConstraints:
    resourceRules:
    - apiGroups:   ["networking.k8s.io"]
      apiVersions: ["v1","v1beta1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["servicecidrs"]
  matchConditions:
  - name: 'exclude-default-servicecidr'
    expression: "object.metadata.name != 'kubernetes'"
  variables:
  - name: allowed
    expression: "['10.96.0.0/16','2001:db8::/64']"
  validations:
  - expression: "object.spec.cidrs.all(i , variables.allowed.exists(j , cidr(j).containsCIDR(i)))"
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
  name: "servicecidrs-binding"
spec:
  policyName: "servicecidrs-default"
  validationActions: [Deny,Audit]
---

Service 虛擬 IP 地址的 IP 地址範圍

功能狀態: Kubernetes v1.26 [stable]

Kubernetes 使用以下公式 min(max(16, cidrSize / 16), 256)ClusterIP 範圍劃分為兩個段,基於配置的 service-cluster-ip-range 的大小。該公式意味著結果永不小於 16 或大於 256,它們之間有一個漸進的步進函式

Kubernetes 傾向於透過從上層選擇來分配動態 IP 地址給 Service,這意味著如果您想為 type: ClusterIP Service 分配特定 IP 地址,則應從較低段手動分配 IP 地址。這種方法減少了分配衝突的風險。

流量策略

您可以設定 .spec.internalTrafficPolicy.spec.externalTrafficPolicy 欄位來控制 Kubernetes 如何將流量路由到健康的(“ready”)後端。

內部流量策略

功能狀態: Kubernetes v1.26 [stable]

您可以設定 .spec.internalTrafficPolicy 欄位來控制從內部源的流量如何路由。有效值為 ClusterLocal。將該欄位設定為 Cluster 以將內部流量路由到所有就緒端點,設定為 Local 以僅路由到就緒的節點本地端點。如果流量策略為 Local 且沒有節點本地端點,則流量將被 kube-proxy 丟棄。

外部流量策略

您可以設定 .spec.externalTrafficPolicy 欄位來控制從外部源的流量如何路由。有效值為 ClusterLocal。將該欄位設定為 Cluster 以將外部流量路由到所有就緒端點,設定為 Local 以僅路由到就緒的節點本地端點。如果流量策略為 Local 且沒有節點本地端點,則 kube-proxy 不會轉發任何相關 Service 的流量。

如果指定了 Cluster,則所有節點都是合格的負載均衡目標,*前提是*節點未被刪除且 kube-proxy 健康。在此模式下:負載均衡器健康檢查配置為將目標指向 Service 代理的就緒埠和路徑。對於 kube-proxy,這評估為:${NODE_IP}:10256/healthzkube-proxy 將返回 HTTP 程式碼 200 或 503。kube-proxy 的負載均衡器健康檢查端點返回 200 如果

  1. kube-proxy 健康,這意味著

    它能夠進行網路程式設計並且在此過程中沒有超時(超時定義為:2 × iptables.syncPeriod);並且

  2. 節點未被刪除(Node 沒有設定刪除時間戳)。

kube-proxy 返回 503 並將節點標記為不合格,因為它支援終止節點的連線排水。從 Kubernetes 管理的負載均衡器的角度來看,當節點正在/刪除時,會發生一些重要的事情。

正在刪除時

  • kube-proxy 將開始使其就緒探測失敗,並有效地將節點標記為不合格接收負載均衡器流量。負載均衡器健康檢查失敗會導致支援連線排水的負載均衡器允許現有連線終止,並阻止新連線建立。

已刪除時

  • Kubernetes 雲控制器管理器中的 Service 控制器會從引用的合格目標集中移除該節點。從負載均衡器的後端目標集中移除任何例項會立即終止所有連線。這也是為什麼 kube-proxy 在節點刪除時首先會使健康檢查失敗的原因。

對於 Kubernetes 供應商來說,重要的是要注意,如果任何供應商將 kube-proxy 的就緒探測配置為活躍探測:那麼 kube-proxy 將在節點刪除時開始不斷重啟,直到節點完全刪除。kube-proxy 暴露了 /livez 路徑,與 /healthz 路徑不同,它考慮節點的刪除狀態,只考慮其網路程式設計的進度。因此,對於任何想要為 kube-proxy 定義活躍探測的人來說,/livez 是推薦的路徑。

部署 kube-proxy 的使用者可以透過評估指標來檢查就緒/活躍狀態:proxy_livez_total / proxy_healthz_total。這兩個指標都發布兩個序列,一個帶有 200 標籤,一個帶有 503 標籤。

對於 Local Service:kube-proxy 將返回 200 如果

  1. kube-proxy 健康/就緒,並且
  2. 在相關節點上有本地端點。

節點刪除影響 kube-proxy 關於負載均衡器健康檢查的返回程式碼。原因如下:刪除節點可能會導致入站中斷,如果所有端點同時在該節點上執行。

Kubernetes 專案建議雲提供商整合程式碼將負載均衡器健康檢查配置為指向 Service 代理的 healthz 埠。如果您正在使用或實現自己的虛擬 IP 實現來替代 kube-proxy,您應該設定一個類似的健康檢查埠,其邏輯與 kube-proxy 實現匹配。

發往終止端點的流量

特性狀態: Kubernetes v1.28 [stable]

如果 ProxyTerminatingEndpoints 功能門kube-proxy 中啟用且流量策略為 Local,則該節點的 kube-proxy 使用更復雜的演算法來選擇 Service 的端點。啟用該功能後,kube-proxy 會檢查節點是否具有本地端點以及所有本地端點是否被標記為終止。如果存在本地端點且所有本地端點都正在終止,則 kube-proxy 會將流量轉發到這些終止的端點。否則,kube-proxy 始終優先將流量轉發到未終止的端點。

這種終止端點的轉發行為是為了允許 NodePortLoadBalancer Service 在使用 externalTrafficPolicy: Local 時優雅地排水連線。

隨著部署進行滾動更新,負載均衡器後面的節點可能會從該部署的 N 個副本轉換到 0 個副本。在某些情況下,外部負載均衡器可以在健康檢查探測之間將流量傳送到具有 0 個副本的節點。路由到終止端點可確保正在縮減 Pod 的節點能夠優雅地接收並排水到這些終止 Pod 的流量。當 Pod 完成終止時,外部負載均衡器應已看到節點的健康檢查失敗,並已將節點完全從後端池中移除。

流量分佈

特性狀態: Kubernetes v1.33 [stable] (預設啟用:true)

Kubernetes Service 中的 spec.trafficDistribution 欄位允許您表達將流量路由到 Service 端點的偏好。

PreferClose
這會優先將流量傳送到與客戶端同一區域的端點。EndpointSlice 控制器會使用 hints 更新 EndpointSlices 來傳達此偏好,kube-proxy 然後會使用這些資訊進行路由決策。如果客戶端所在區域沒有可用的端點,流量將為該客戶端進行叢集範圍路由。
特性狀態: Kubernetes v1.34 [beta] (預設啟用:true)

在 Kubernetes 1.34 中,有兩個附加值可用(除非 PreferSameTrafficDistribution 功能門被停用)

PreferSameZone
這與 PreferClose 含義相同,但更明確。(最初的意圖是 PreferClose 後來可能包含“偏好同一區域”之外的功能,但這已不再計劃。將來,PreferSameZone 將成為此功能的推薦值,而 PreferClose 將被視為其已棄用的別名。)
PreferSameNode
這會優先將流量傳送到與客戶端同一節點的端點。與 PreferClose/PreferSameZone 一樣,EndpointSlice 控制器會使用 hints 更新 EndpointSlices,表明某個切片應用於特定節點。如果客戶端節點沒有可用的端點,則 Service 代理將回退到“同一區域”行為,如果沒有同一區域的端點,則回退到叢集範圍。

trafficDistribution 沒有值的情況下,預設策略是將流量均勻分佈到叢集中的所有端點。

service.kubernetes.io/topology-mode: Auto 的比較

trafficDistribution 欄位(帶 PreferClose/PreferSameZone)以及使用 service.kubernetes.io/topology-mode: Auto 註解的舊版“拓撲感知路由”功能都旨在優先處理同一區域的流量。但是,它們的方法存在關鍵差異

  • service.kubernetes.io/topology-mode: Auto 嘗試根據可分配的 CPU 資源按區域比例分配流量。此啟發式方法包括安全措施(例如,對於少量端點的回退行為),為了可能更好的負載均衡而犧牲了一些可預測性。

  • trafficDistribution: PreferClose 旨在更簡單、更可預測:“如果區域中有端點,它們將接收該區域的所有流量;如果區域中沒有端點,流量將分配到其他區域”。這種方法提供了更高的可預測性,但這意味著您負責避免端點過載

如果設定了 service.kubernetes.io/topology-mode 註解為 Auto,它將優先於 trafficDistribution。將來可能會棄用該註解,以 trafficDistribution 欄位為準。

與流量策略的互動

trafficDistribution 欄位相比,流量策略欄位(externalTrafficPolicyinternalTrafficPolicy)旨在提供更嚴格的流量區域性性要求。trafficDistribution 與它們的互動方式如下:

  • 流量策略的優先順序:對於給定的 Service,如果流量策略(externalTrafficPolicyinternalTrafficPolicy)設定為 Local,它將優先於相應流量型別(外部或內部)的 trafficDistribution

  • trafficDistribution 的影響:對於給定的 Service,如果流量策略(externalTrafficPolicyinternalTrafficPolicy)設定為 Cluster(預設),或者未設定這些欄位,則 trafficDistribution 將指導相應流量型別(外部或內部)的路由行為。這意味著將嘗試將流量路由到與客戶端同一區域的端點。

使用流量分佈控制的注意事項

使用 trafficDistribution 的 Service 將嘗試將流量路由到(健康的)拓撲內的端點,即使這意味著某些端點接收的流量遠多於其他端點。如果您沒有足夠數量的端點與客戶端在同一拓撲(“同一區域”、“同一節點”等)中,則端點可能會過載。如果入站流量未在拓撲中成比例分佈,這種情況尤其可能發生。為緩解此問題,請考慮以下策略:

  • Pod 拓撲擴散約束:使用 Pod 拓撲擴散約束將 Pod 均勻分佈到區域或節點。

  • 區域特定部署:如果您正在使用“同一區域”流量分發,但預計不同區域會看到不同的流量模式,則可以為每個區域建立單獨的 Deployment。這種方法允許獨立的應用程式獨立擴充套件。此外,在 Kubernetes 專案本身之外的生態系統中,也有可用的工作負載管理外掛可以幫助解決此問題。

下一步

要了解更多關於 Service 的資訊,請閱讀使用 Service 連線應用程式

您還可以

最後修改時間 2025 年 7 月 3 日上午 9:29 PST:WinDSR 到穩定更新 (406db73486)