Endpoints
Endpoints 资源代表了 Service 后端实际运行的 Pod 的网络地址(IP 地址和端口)。当一个 Service 被创建时,Kubernetes 会根据 Service 的选择器(selector)来查找匹配的 Pod,并将这些 Pod 的 IP 和端口信息填充到 Endpoints 对象中。它是 手动管理服务后端 的方式之一,但在大多数情况下,EndpointSlice 资源和 Endpoint 控制器会自动创建和管理它。
apiVersion: v1
kind: Endpoints
metadata:
name: my-service # Endpoints对象的名称通常与它关联的Service名称相同
subsets:
- addresses: # 匹配的后端Pod的IP地址列表
- ip: "10.244.0.4"
- ip: "10.244.0.5"
ports: # 匹配的后端Pod的端口列表
- port: 8080
name: http
protocol: TCP
EndpointSlice
EndpointSlice 是一种更具可扩展性和效率的 Endpoints 替代品。它旨在解决在拥有大量 Pod 后端的 Service 中,单个 Endpoints 对象变得非常大而导致的性能问题。每个 EndpointSlice 对象通常只包含少量的 Endpoint(最多约 100 个),这意味着对于一个大型 Service,可能会有多个 EndpointSlice 对象,每个对象包含一部分后端信息。这使得网络传输和客户端(如 kube-proxy)处理更新时更加高效。
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: my-service-abcxyz # 自动生成的名称,通常包含Service名称
labels:
kubernetes.io/service-name: my-service # 关联的Service名称
addressType: IPv4
ports:
- name: http
protocol: TCP
port: 8080
endpoints: # 包含的具体端点列表
- addresses: # 后端Pod的IP地址
- "10.244.0.6"
conditions: # 端点的状态信息
ready: true
serving: true
hostname: pod-name-a
- addresses:
- "10.244.0.7"
conditions:
ready: false # 示例:这个Pod尚未准备好接收流量
serving: true
hostname: pod-name-b
两者区别
K8s(Kubernetes)中的 Endpoints 和 EndpointSlice 都是用来跟踪 Service 对应后端 Pods 网络地址信息的对象,但 EndpointSlice 是为了解决大规模集群中 Endpoints 对象的扩展性问题而引入的。
🧐 Endpoints 与 EndpointSlice 的核心区别
| 特性 | Endpoints | EndpointSlice |
|---|---|---|
| 引入时间 | 早期(v1 API) | v1.17 引入,v1.21 默认启用 |
| 结构 | 单个对象,包含所有后端 Pod 地址和端口的完整列表。 | 分片 的对象,每个对象只包含一部分后端 Pod 地址和端口。 |
| 可扩展性 | 差:当 Service 后端 Pod 数量巨大时(如数千个),单个 Endpoints 对象会变得非常大,导致: 1. etcd 压力:对象更新、存储和监控(watch)消耗大量资源。 2. 网络延迟:大型对象在网络传输和 API Server 与客户端之间同步时效率低下。 | 好:将大型 Service 的 Endpoint 信息分割成多个较小的 Slice,显著减少单个对象的大小,从而: 1. 降低 etcd 压力:更新只影响必要的 Slice。 2. 提高性能:减少网络开销和处理时间。 |
| 主要用途 | 早期和小型集群。 | 推荐用于大规模集群,是 Kube-proxy、Ingress Controller 等组件获取 Service 后端信息的首选方式。 |
| 控制器 | 由 Endpoint Controller 维护。 | 由 EndpointSlice Controller 维护。 |
详细对比
1. Endpoints (传统方式)
格式举例 (简化):
{ "apiVersion": "v1", "kind": "Endpoints", "metadata": { "name": "my-service" }, "subsets": [ { "addresses": [ {"ip": "10.0.0.1"}, {"ip": "10.0.0.2"}, // ... 几千个 IP ], "ports": [ {"port": 8080} ] } ] }问题所在: 想象一个 Service 有 3000 个 Pod 后端。任何一个 Pod 的状态变化(例如重启、IP 变化)都会导致这个包含 3000 个地址的 巨大 Endpoints 对象被 完全替换,给 API Server、etcd 和所有监视它的组件(如 Kube-proxy)带来巨大的负担。
2. EndpointSlice (现代方式)
设计理念: 分而治之。一个 Service 的后端地址不再存储在一个对象中,而是分散存储在多个 EndpointSlice 对象中。
分片规则: 每个 EndpointSlice 默认最多存储大约 100 个 Endpoints (可以配置)。如果一个 Service 有 3000 个 Pod,它将会有大约 30 个 EndpointSlice 对象。
格式举例 (简化):
// EndpointSlice 1 of 30 for 'my-service' { "apiVersion": "discovery.k8s.io/v1", "kind": "EndpointSlice", "metadata": { "name": "my-service-abcde", "labels": { "kubernetes.io/service-name": "my-service" } }, "addressType": "IPv4", "endpoints": [ {"addresses": ["10.0.0.1"], "targetRef": ...}, {"addresses": ["10.0.0.2"], "targetRef": ...}, // ... 最多约 100 个 endpoints ], "ports": [ {"port": 8080} ] }优势: 当 Pod 状态发生变化时,只需要更新或替换包含该 Pod 的 小型 EndpointSlice 对象,而不是整个 Service 的 Endpoints 列表。这极大地提高了大规模集群的性能和可扩展性。
💡 总结
EndpointSlice 是对 Endpoints 机制的优化升级。
对于集群内需要获取 Service 后端地址信息的组件(如 Kube-proxy),它们现在主要通过监视 EndpointSlice 对象来获取信息,这让 Kubernetes 在处理拥有大量后端 Pod 的 Service 时更高效、更具弹性。
您想了解更多关于 Kube-proxy 如何使用 EndpointSlice 来配置网络规则的细节吗?