本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

使用 EndpointSlices 扩展 Kubernetes 网络

EndpointSlices 是一种令人兴奋的新 API,它提供了可扩展、可伸缩的 Endpoints API 替代方案。EndpointSlices 跟踪支持 Service 的 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,而是将它们拆分为多个更小的 EndpointSlices。

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

默认情况下,EndpointSlices 每个存储多达 100 个端点,尽管这可以通过 kube-controller-manager 上的 --max-endpoints-per-slice 标志进行配置。

EndpointSlices 提供了 10 倍的伸缩性改进

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

更重要的是,现在 Service 的所有 Pod IP 不需要存储在单个资源中,我们不再需要担心 etcd 中存储的对象的尺寸限制。EndpointSlices 已经用于将 Service 扩展到超过 100,000 个网络端点。

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

EndpointSlices 启用新功能

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

双栈服务是一个令人兴奋的新功能,它与 EndpointSlices 一起开发。它们将为服务同时使用 IPv4 和 IPv6 地址,并依赖 EndpointSlices 上的 addressType 字段来按 IP 家族跟踪这些地址。

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

这对 Endpoints API 意味着什么?

尽管 EndpointSlice API 提供了 Endpoints API 的更新、更具伸缩性的替代方案,但 Endpoints API 将继续被视为普遍可用和稳定的。Endpoints API 计划的最显著的更改将涉及开始截断那些否则会遇到伸缩性问题的 Endpoints。

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