Skip to content

第6章 后端发现机制:Endpoints 与 EndpointSlice

Service 只是声明了“我想要把流量发给哪些 Pod”,真正记录“具体发给谁”的是 Endpoints 和 EndpointSlice。本章深入讲解这个发现机制。


6.1 为什么需要 Endpoints

Service 的 selector 定义了选择条件,但 Kubernetes 需要有一个地方记录当前匹配了哪些 Pod、IP 和端口是什么。这就是 Endpoints/EndpointSlice 的作用。

text
Service (意图)


Endpoints/EndpointSlice (当前状态)


Pod IP:targetPort (真实后端)

6.2 Endpoints(旧机制)

当 Service 定义了 selector,Kubernetes 控制平面会自动创建同名的 Endpoints 对象,记录所有匹配 Pod 的 IP:targetPort

YAML 示例

yaml
apiVersion: v1
kind: Endpoints
metadata:
  name: web-service
subsets:
  - addresses:
      - ip: 10.244.1.10
      - ip: 10.244.1.11
    ports:
      - port: 8080

查看命令

bash
kubectl get endpoints <svc-name>

6.3 EndpointSlice(推荐)

Endpoints 在大规模集群中存在性能和可扩展性问题(单个对象过大)。Kubernetes 1.21+ 默认使用 EndpointSlice

  • 将后端端点拆分为多个 Slice,每个最多 100 个端点。
  • 支持更丰富的元数据(拓扑信息、条件状态等)。
  • 更高效的增量更新,降低网络和控制平面压力。

YAML 示例

yaml
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
  name: web-service-abc12
  labels:
    kubernetes.io/service-name: web-service
addressType: IPv4
ports:
  - name: http
    protocol: TCP
    port: 8080
endpoints:
  - addresses:
      - 10.244.1.10
    conditions:
      ready: true
    nodeName: node-1
    zone: cn-north-1a

关键字段

字段含义
addressTypeIPv4 / IPv6 / FQDN
ports[].port后端端口,即 targetPort
endpoints[].addressesPod IP 列表
endpoints[].conditions.ready是否就绪
endpoints[].nodeNamePod 所在节点
endpoints[].zone可用区信息

查看命令

bash
kubectl get endpointslices -l kubernetes.io/service-name=<svc-name>

6.4 Endpoints 与 EndpointSlice 的关系

text
Service

   ├── Endpoints (v1,旧版,单个对象)

   └── EndpointSlice (discovery.k8s.io/v1,新版,分片)
        ├── web-service-abc12
        ├── web-service-def34
        └── ...

在 Kubernetes 1.21+ 中,EndpointSlice 是默认机制,Endpoints 仍然保留以兼容旧系统。


6.5 无 Selector 的 Service 如何手动关联后端

如果 Service 没有 selector,需要手动创建 Endpoints/EndpointSlice,用于指向集群外部服务或自定义后端。

场景:访问集群外部的 MySQL

yaml
apiVersion: v1
kind: Service
metadata:
  name: external-mysql
spec:
  type: ClusterIP
  ports:
    - port: 3306
---
apiVersion: v1
kind: Endpoints
metadata:
  name: external-mysql
subsets:
  - addresses:
      - ip: 192.168.1.100
    ports:
      - port: 3306

集群内应用就可以像访问内部服务一样访问外部 MySQL:

bash
mysql -h external-mysql -P 3306

6.6 readinessProbe 决定端点是否加入

只有满足以下条件的 Pod 才会被加入 Endpoints/EndpointSlice:

  • Pod 的 IP 可达。
  • Pod 的标签匹配 Service selector。
  • Readiness Probe 通过(如果配置了)。
  • Pod 不处于 Terminating 状态。

因此,生产服务务必配置 readinessProbe,否则未就绪的 Pod 会收到流量。

yaml
spec:
  containers:
    - name: app
      image: my-app:1.0
      readinessProbe:
        httpGet:
          path: /health
          port: 8080
        initialDelaySeconds: 5
        periodSeconds: 5

6.7 本章小结

  • Endpoints/EndpointSlice 是 Service 与 Pod 之间的“桥梁”。
  • EndpointSlice 是推荐机制,支持分片和更丰富的拓扑信息。
  • 无 Selector 的 Service 需要手动创建 Endpoints/EndpointSlice。
  • readinessProbe 决定了 Pod 是否能接收流量。

本章练习

  1. 创建一个 Service 和 Deployment,观察自动生成的 Endpoints 和 EndpointSlice。
  2. 为一个 Pod 配置失败的 readinessProbe,观察它是否从 Endpoints 中移除。
  3. 创建一个无 Selector 的 Service,手动创建 Endpoints 指向一个外部 IP,验证集群内能否访问。