EndpointSlice
Kubernetes v1.21 [stable]
Kubernetes 的 **EndpointSlice** API 提供了一種在 Kubernetes 叢集中跟蹤網路端點的方法。
EndpointSlice API
在 Kubernetes 中,EndpointSlice 包含對一組網路端點的引用。控制平面會自動為任何具有指定選擇器的 Kubernetes Service 建立 EndpointSlices。這些 EndpointSlices 包含對與 Service 選擇器匹配的所有 Pod 的引用。EndpointSlices 透過 IP 家族、協議、埠號和 Service 名稱的唯一組合對網路端點進行分組。EndpointSlice 物件的名稱必須是有效的DNS 子域名。
例如,這是一個示例 EndpointSlice 物件,由 `example` Kubernetes Service 擁有。
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: example-abc
labels:
kubernetes.io/service-name: example
addressType: IPv4
ports:
- name: http
protocol: TCP
port: 80
endpoints:
- addresses:
- "10.1.2.3"
conditions:
ready: true
hostname: pod-1
nodeName: node-1
zone: us-west2-a
預設情況下,控制平面建立和管理 EndpointSlices,每個 EndpointSlice 最多包含 100 個端點。你可以透過 `kube-controller-manager` 的 `--max-endpoints-per-slice` kube-controller-manager 標誌配置此值,最大為 1000。
EndpointSlices 作為 kube-proxy 路由內部流量的真相來源。
地址型別
EndpointSlices 支援兩種地址型別
- IPv4
- IPv6
每個 `EndpointSlice` 物件代表一個特定的 IP 地址型別。如果你的 Service 同時支援 IPv4 和 IPv6,那麼將至少有兩個 `EndpointSlice` 物件(一個用於 IPv4,一個用於 IPv6)。
狀況
EndpointSlice API 儲存可能對消費者有用的端點狀態。這三個狀態是 `serving`、`terminating` 和 `ready`。
Serving (服務中)
Kubernetes v1.26 [stable]
`serving` 狀態表示端點當前正在提供響應,因此應將其用作 Service 流量的目標。對於由 Pod 支援的端點,這對映到 Pod 的 `Ready` 狀態。
Terminating (正在終止)
Kubernetes v1.26 [stable]
`terminating` 狀態表示端點正在終止。對於由 Pod 支援的端點,當 Pod 首次被刪除時(即當它收到刪除時間戳時,但很可能在 Pod 容器退出之前),此狀態會被設定。
Service 代理通常會忽略 `terminating` 狀態的端點,但如果所有可用端點都處於 `terminating` 狀態,它們可能會將流量路由到同時處於 `serving` 和 `terminating` 狀態的端點。(這有助於確保在底層 Pod 進行滾動更新期間不會丟失 Service 流量。)
Ready (就緒)
`ready` 狀態實際上是“`serving` 且未 `terminating`”的快捷方式(儘管對於 `spec.publishNotReadyAddresses` 設定為 `true` 的 Service,它也總是 `true`)。
拓撲資訊
EndpointSlice 中的每個端點都可以包含相關的拓撲資訊。拓撲資訊包括端點的位置以及有關相應節點和區域的資訊。這些資訊在 EndpointSlices 中以下每個端點欄位中可用:
- `nodeName` - 此端點所在的節點的名稱。
- `zone` - 此端點所在的區域。
管理
最常見的情況是,控制平面(特別是端點切片控制器)建立和管理 EndpointSlice 物件。EndpointSlices 還有其他各種用例,例如服務網格實現,可能導致其他實體或控制器管理額外的 EndpointSlices 集。
為了確保多個實體可以管理 EndpointSlices 而不會相互干擾,Kubernetes 定義了標籤 `endpointslice.kubernetes.io/managed-by`,它指示管理 EndpointSlice 的實體。端點切片控制器將 `endpointslice-controller.k8s.io` 作為其管理的所有 EndpointSlice 的此標籤的值。管理 EndpointSlices 的其他實體也應為此標籤設定一個唯一值。
所有權
在大多數用例中,EndpointSlices 由 EndpointSlice 物件所跟蹤端點的 Service 擁有。這種所有權透過每個 EndpointSlice 上的所有者引用以及 `kubernetes.io/service-name` 標籤來表明,該標籤使得查詢屬於某個 Service 的所有 EndpointSlice 變得簡單。
EndpointSlice 的分發
每個 EndpointSlice 都有一組適用於該資源中所有端點的埠。當服務使用命名埠時,Pod 可能為相同的命名埠分配不同的目標埠號,這需要不同的 EndpointSlice。
控制平面會嘗試儘可能地填充 EndpointSlices,但不會主動重新平衡它們。其邏輯相當簡單:
- 遍歷現有的 EndpointSlices,移除不再需要的端點,並更新已更改的匹配端點。
- 遍歷在第一步中已修改的 EndpointSlices,並用任何所需的新端點填充它們。
- 如果仍有新的端點要新增,嘗試將其放入先前未更改的切片中和/或建立新的切片。
重要的是,第三步優先限制 EndpointSlice 的更新,而不是實現 EndpointSlice 的完美分佈。例如,如果有 10 個新端點要新增,並且有 2 個 EndpointSlice 各有 5 個空閒位置,這種方法會建立一個新的 EndpointSlice,而不是填滿這 2 個現有 EndpointSlice。換句話說,建立一個 EndpointSlice 比多次更新 EndpointSlice 更可取。
由於 kube-proxy 在每個節點上執行並監視 EndpointSlices,對 EndpointSlice 的每次更改都相對昂貴,因為它將被傳輸到叢集中的每個節點。這種方法旨在限制需要傳送到每個節點的更改數量,即使這可能導致多個 EndpointSlice 未完全填充。
在實踐中,這種不理想的分佈應該很少見。EndpointSlice 控制器處理的大多數更改都足夠小,可以放入現有的 EndpointSlice 中,如果不能,無論如何都可能很快需要一個新的 EndpointSlice。Deployment 的滾動更新也提供了一種自然的 EndpointSlice 重打包方式,所有 Pod 及其相應的端點都將被替換。
重複端點
由於 EndpointSlice 變更的性質,端點可能在同一時間出現在多個 EndpointSlice 中。這自然發生在對不同 EndpointSlice 物件的變更可能在不同的時間到達 Kubernetes 客戶端 watch / cache 時。
注意
EndpointSlice API 的客戶端必須遍歷與 Service 相關聯的所有現有 EndpointSlice 並構建一個完整的唯一網路端點列表。值得一提的是,端點可能會在不同的 EndpointSlice 中重複。
你可以在 `kube-proxy` 的 `EndpointSliceCache` 程式碼中找到如何執行此端點聚合和去重操作的參考實現。
EndpointSlice 映象
EndpointSlice API 替代了舊的 Endpoints API。為了保持與期望 kube-proxy 基於 Endpoints 資源路由流量的舊控制器和使用者工作負載的相容性,叢集的控制平面會將大多數使用者建立的 Endpoints 資源映象到相應的 EndpointSlices。
(然而,此功能,與 Endpoints API 的其餘部分一樣,已棄用。手動為無選擇器的 Service 指定端點的使用者應該透過直接建立 EndpointSlice 資源來實現,而不是透過建立 Endpoints 資源並允許它們被映象。)
控制平面會映象 Endpoints 資源,除非:
- Endpoints 資源具有 `endpointslice.kubernetes.io/skip-mirror` 標籤且其值為 `true`。
- Endpoints 資源具有 `control-plane.alpha.kubernetes.io/leader` 註解。
- 相應的 Service 資源不存在。
- 相應的 Service 資源具有非空選擇器。
單個 Endpoints 資源可能會轉換為多個 EndpointSlice。如果 Endpoints 資源有多個子集或包含具有多個 IP 家族(IPv4 和 IPv6)的端點,則會發生這種情況。每個子集最多 1000 個地址將被映象到 EndpointSlices。
下一步
- 請參閱使用 Service 連線應用程式教程
- 閱讀 EndpointSlice API 的API 參考
- 閱讀 Endpoints API 的API 參考