基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Service 和 Endpoints 的关系?

知识点图片

在 Kubernetes (K8s) 中,ServiceEndpoints 是两个紧密相关但职责不同的资源对象。

用一句话概括它们的关系:Service 是“前台”也就是访问入口(定义了访问策略),Endpoints 是“通讯录”也就是后端列表(存储了实际的后端 Pod IP 地址)。

以下是详细的深度解析:

1. 核心概念对比

  • Service (抽象层):

    • 作用: 提供一个稳定的虚拟 IP (ClusterIP) 和 DNS 名称。
    • 目的: 屏蔽后端 Pod 的动态变化(Pod 可能会挂掉、重启、扩缩容,IP 会变)。客户端只需要访问 Service,不需要关心具体是哪个 Pod 在服务。
    • 角色: 它是定义者,定义了“我是谁”以及“我要把流量转发给谁(通过标签选择器)”。
  • Endpoints (具体层):

    • 作用: 维护一个动态的 IP 地址列表。
    • 目的: 告诉 Service,当前时刻,真正活着的、准备好接收流量的 Pod 的 IP 和端口具体是多少。
    • 角色: 它是执行者/数据源,它是 Service 和 Pod 之间的桥梁。

2. 它们是如何关联的?(工作原理)

它们之间的纽带通常是 Label Selector(标签选择器)资源名称

场景 A:带有 Selector 的 Service(最常见)

当你创建一个带有 selector 的 Service 时,Kubernetes 的控制平面(Endpoint Controller)会自动执行以下操作:

  1. 查找: 扫描集群中所有满足 selector 条件(例如 app: nginx)且状态为 Running 的 Pod。
  2. 创建/更新: 自动创建一个与 Service 同名 的 Endpoints 对象。
  3. 填充: 将找到的 Pod IP 地址和端口填入这个 Endpoints 对象中。
  4. 同步: 如果 Pod 挂了或扩容了,Endpoint Controller 会感知到,并实时更新 Endpoints 对象中的 IP 列表。

数据流向:
Client -> Service (VIP) -> iptables/IPVS 规则 (基于 Endpoints 生成) -> Pod IP

场景 B:不带 Selector 的 Service(特殊场景)

如果你创建 Service 时没有指定 selector

  1. K8s 不会自动创建 Endpoints 对象。
  2. 你需要手动创建一个与 Service 同名 的 Endpoints 对象,并手动填入后端的 IP 地址。
  3. 用途: 这种方式通常用于将 Service 映射到集群外部的数据库、遗留系统,或者另一个 Namespace 里的服务。

3. 形象的比喻

  • Service 就像公司的总机号码(永远不变)。
  • Pods 就像客服员工(员工会离职、入职、换工位,分机号会变)。
  • Endpoints 就像前台手里的分机通讯录

当客户打总机号码(访问 Service)时,前台(Kube-proxy)会查阅通讯录(Endpoints),看现在哪位员工(Pod)在位,然后把电话转接过去。如果来了新员工,通讯录会自动更新,但总机号码不需要变。

4. 实际操作中的体现

你可以通过 kubectl 命令验证这种关系:

1. 查看 Service:

bash
kubectl get svc my-service
# 输出: NAME: my-service, CLUSTER-IP: 10.96.0.100

2. 查看对应的 Endpoints:

bash
kubectl get endpoints my-service
# 输出: NAME: my-service, ENDPOINTS: 10.244.1.5:80,10.244.2.3:80

注意:Endpoints 的名字和 Service 是一样的,里面的 IP 就是 Pod 的 IP。

3. 查看 YAML 定义:
Service 的 YAML:

yaml
apiVersion: v1
kind: Service
metadata:
  name: my-app
spec:
  selector:
    app: demo  # 关键点:通过这个标签找 Pod
  ports:
    - port: 80

自动生成的 Endpoints YAML 片段:

yaml
apiVersion: v1
kind: Endpoints
metadata:
  name: my-app # 关键点:名字与 Service 相同
subsets:
  - addresses:
      - ip: 10.244.0.5 # 实际 Pod IP
      - ip: 10.244.0.6
    ports:
      - port: 80

5. 进阶:EndpointSlices (K8s 的演进)

在较新的 Kubernetes 版本(v1.21+)中,为了解决大规模集群中 Endpoints 对象过大导致的性能问题,引入了 EndpointSlices

  • 问题: 如果一个 Service 后面有 5000 个 Pod,那么 Endpoints 对象就会非常巨大。每次有一个 Pod 变动,整个巨大的对象都要在网络中传输给所有的节点,造成网络风暴。
  • 解决: EndpointSlice 将原来的大 Endpoints 切分成多个小片(Slice)。
  • 关系: Service -> EndpointSlices -> Pods。
  • 现状: 虽然现在底层主要使用 EndpointSlices,但为了兼容性,K8s 依然会维护传统的 Endpoints 对象,逻辑关系依然适用。

总结

  • Service 定义访问策略(VIP、端口)。
  • Endpoints 存储目标地址(Pod IP 列表)。
  • 两者通常通过 Selector 自动绑定,且同名
  • kube-proxy 监听 Endpoints 的变化来配置底层的网络转发规则(iptables/IPVS)。
00:00
00:00