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)中的 EndpointsEndpointSlice 都是用来跟踪 Service 对应后端 Pods 网络地址信息的对象,但 EndpointSlice 是为了解决大规模集群中 Endpoints 对象的扩展性问题而引入的。


🧐 Endpoints 与 EndpointSlice 的核心区别

特性EndpointsEndpointSlice
引入时间早期(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 来配置网络规则的细节吗?