这篇文章发布时间已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。

使用 EndpointSlices 扩展 Kubernetes 网络

EndpointSlices 是一种令人兴奋的新 API,它为 Endpoints API 提供了一种可扩展且可扩展的替代方案。EndpointSlices 跟踪为服务提供支持的 Pod 的 IP 地址、端口、就绪情况和拓扑信息。

在 Kubernetes 1.19 中,默认启用此功能,kube-proxy 从 EndpointSlices 读取而不是 Endpoints。虽然这在很大程度上是一个不可见的变化,但它应该会在大型集群中带来明显的可扩展性改进。它还可以在未来的 Kubernetes 版本中启用重要的新功能,例如拓扑感知路由。

Endpoints API 的可扩展性限制

使用 Endpoints API 时,一个 Service 只有一个 Endpoints 资源。这意味着它需要能够存储支持相应 Service 的每个 Pod 的 IP 地址和端口(网络端点)。这导致了巨大的 API 资源。更糟糕的是,kube-proxy 在每个节点上运行,并监视 Endpoints 资源的任何更新。即使一个 Endpoints 资源中只有一个网络端点发生更改,也需要将整个对象发送到 kube-proxy 的每个实例。

Endpoints API 的另一个限制是它限制了可以为 Service 跟踪的网络端点的数量。存储在 etcd 中的对象的默认大小限制为 1.5MB。在某些情况下,这会将一个 Endpoints 资源限制为 5,000 个 Pod IP。对于大多数用户来说,这不是问题,但对于拥有接近此规模的 Service 的用户来说,这将成为一个重大问题。

为了展示这些问题在规模上变得多么严重,一个简单的例子会有所帮助。假设一个 Service 有 5,000 个 Pod,它最终可能会得到一个 1.5MB 的 Endpoints 资源。如果该列表中哪怕只有一个网络端点发生更改,整个 Endpoints 资源都需要分发到集群中的每个节点。这在拥有 3,000 个节点的大型集群中会成为一个相当大的问题。每次更新都需要在集群中发送 4.5GB 的数据(1.5MB Endpoints * 3,000 个节点)。这几乎足以填满一张 DVD,并且每次 Endpoints 更改都会发生这种情况。想象一下,一个滚动更新导致所有 5,000 个 Pod 被替换 - 这意味着传输超过 22TB(或 5,000 张 DVD)的数据。

使用 EndpointSlice API 拆分端点

EndpointSlice API 的设计目的是通过类似于分片的方法来解决这个问题。我们不是使用单个 Endpoints 资源来跟踪 Service 的所有 Pod IP,而是将它们拆分为多个较小的 EndpointSlice。

考虑一个 Service 由 15 个 Pod 支持的示例。我们最终会得到一个跟踪所有这些 Pod 的单个 Endpoints 资源。如果 EndpointSlice 配置为每个存储 5 个端点,我们最终将得到 3 个不同的 EndpointSlice:EndpointSlices

默认情况下,EndpointSlice 每个存储多达 100 个端点,不过可以使用 kube-controller-manager 上的 --max-endpoints-per-slice 标志进行配置。

EndpointSlice 提供 10 倍的扩展性改进

此 API 显著提高了网络的可扩展性。现在,当添加或删除 Pod 时,只需要更新 1 个小的 EndpointSlice。当数百或数千个 Pod 支持单个 Service 时,这种差异变得非常明显。

更重要的是,现在不必将 Service 的所有 Pod IP 存储在单个资源中,因此我们不必担心存储在 etcd 中的对象的大小限制。EndpointSlice 已经被用于将 Service 扩展到超过 100,000 个网络端点。

所有这些都与 kube-proxy 中做出的一些重大性能改进结合在一起。当大规模使用 EndpointSlice 时,端点更新传输的数据将显著减少,并且 kube-proxy 更新 iptables 或 ipvs 规则的速度应该更快。除此之外,Service 现在可以扩展到至少比以前的任何限制高 10 倍。

EndpointSlice 启用新功能

EndpointSlice 作为 Kubernetes v1.16 中的 Alpha 功能引入,旨在在未来的 Kubernetes 版本中启用一些令人兴奋的新功能。这可能包括双栈 Service、拓扑感知路由和端点子集。

双栈 Service 是一项令人兴奋的新功能,与 EndpointSlice 一起开发。它们将为 Service 使用 IPv4 和 IPv6 地址,并依赖 EndpointSlice 上的 addressType 字段来按 IP 系列跟踪这些地址。

拓扑感知路由将更新 kube-proxy,使其优先在同一区域内或区域内路由请求。这利用了存储在 EndpointSlice 中每个端点的拓扑字段。作为进一步的改进,我们正在探索端点子集的潜力。这将允许 kube-proxy 仅监视 EndpointSlice 的子集。例如,这可以与拓扑感知路由结合使用,以便 kube-proxy 只需要监视包含同一区域内端点的 EndpointSlice。这将提供另一个非常显著的可扩展性改进。

这对 Endpoints API 意味着什么?

尽管 EndpointSlice API 为 Endpoints API 提供了一种更新、更具可扩展性的替代方案,但 Endpoints API 将继续被视为通用可用且稳定。针对 Endpoints API 计划的最重要更改将包括开始截断那些可能出现可扩展性问题的 Endpoints。

Endpoints API 不会消失,但许多新功能将依赖于 EndpointSlice API。为了利用 EndpointSlice 提供的新的可扩展性和功能,当前使用 Endpoints 的应用程序将来可能需要考虑支持 EndpointSlice。