在 Kubernetes 中,Service、Endpoint(或 EndpointSlice)和 kube-proxy 是协同实现服务发现与负载均衡的核心组件。它们的关系可以简单理解为:Service 定义了访问规则,Endpoint 维护了实际后端 Pod 的地址列表,而 kube-proxy 负责将规则落地到每个节点,实现流量转发。下面从概念到实例逐一说明。
1. 核心概念
Service
- 作用:为一组功能相同的 Pod 提供稳定的网络访问入口(IP 和 DNS),屏蔽后端 Pod 的动态变化(如扩缩容、故障迁移)。
- 类型:ClusterIP(集群内访问)、NodePort(通过节点端口访问)、LoadBalancer(云负载均衡器)等。
- 关键属性:标签选择器(selector)决定了哪些 Pod 属于该 Service。
Endpoint(及 EndpointSlice)
- 作用:记录 Service 背后实际 Pod 的 IP 地址和端口列表。每个 Service 通常对应一个同名的 Endpoint 对象(旧版)或一组 EndpointSlice(新版,用于大规模集群)。
- 自动维护:当 Service 的标签选择器匹配到 Pod 时,Kubernetes 控制平面会自动创建并更新 Endpoint/EndpointSlice,将匹配的 Pod IP:Port 加入列表;若 Pod 变化,Endpoint 也随之更新。
kube-proxy
- 作用:运行在每个工作节点上的代理组件,负责将访问 Service 的流量转发到后端的 Pod。
- 工作模式:常见的有 iptables(默认)、IPVS(高性能)、userspace(旧版)。kube-proxy 通过监听 API Server 中 Service 和 Endpoint 的变化,动态更新节点上的网络规则(如 iptables 规则),实现流量的负载均衡。
2. 三者的关系与协同流程
| |
- 控制平面:
- 用户创建 Service,指定
selector: app=web。 - Kubernetes 自动创建同名的 Endpoint 对象,并持续监控所有带
app=web标签的 Pod,将其 IP:Port 写入 Endpoint 列表。
- 用户创建 Service,指定
- 数据平面(每个节点):
- kube-proxy 监听 Service 和 Endpoint 的变化。
- 有更新时,kube-proxy 在节点上配置相应的转发规则(例如 iptables 规则):
- 所有目标为 Service ClusterIP 的流量,随机或轮询转发到 Endpoint 列表中的某个 Pod IP。
- 当客户端通过 Service IP 访问时,请求到达节点,被节点上的 iptables 规则拦截,直接转发给某个后端 Pod。
- 流量路径示例:
Pod A(客户端) -> Service 10.96.0.1:80 -> 节点 iptables 规则 -> Pod B(后端)10.244.1.2:8080
3. 举例说明
假设我们有一个简单的 Web 应用,由两个 Pod 组成,它们都带有标签 app=web,容器端口为 80。
步骤 1:创建 Service
| |
步骤 2:Kubernetes 自动创建 Endpoint
执行 kubectl get endpoints web-service,可以看到类似输出:
| |
这里记录了当前两个 Pod 的 IP 和端口。如果某个 Pod 被删除或重建,Endpoint 列表会实时更新,确保只包含健康 Pod。
步骤 3:kube-proxy 配置规则
每个节点上的 kube-proxy 监听到 Service 和 Endpoint 后,会设置 iptables 规则(以 iptables 模式为例):
- 创建一个虚拟 IP(ClusterIP,如 10.96.0.1)作为 Service 的入口。
- 编写规则,将发往 10.96.0.1:80 的包 DNAT(目的地址转换)到 Endpoint 列表中的某个 Pod IP(例如 10.244.1.2:80 或 10.244.2.3:80),并做负载均衡(随机或轮询)。
步骤 4:访问验证
集群内的任意 Pod 可以通过 Service 名称(web-service.default.svc.cluster.local)或 ClusterIP(10.96.0.1)访问 Web 应用:
| |
请求到达节点后,根据 iptables 规则被转发到其中一个实际 Pod,从而实现负载均衡和服务发现。
4. 补充说明:EndpointSlice
在较大规模集群中,单个 Endpoint 对象可能因 Pod 过多而变得庞大,影响性能。Kubernetes 引入了 EndpointSlice,将同一 Service 的后端地址切分成多个 slice,每个 slice 默认最多容纳 100 个地址,从而提升可扩展性。kube-proxy 也支持监听 EndpointSlice,原理与 Endpoint 类似。
总结
- Service 提供稳定访问入口,Endpoint 提供动态后端列表,kube-proxy 负责将二者结合并落地为节点上的转发规则。
- 三者通过 API Server 的监听机制联动,使得 Kubernetes 的服务发现和负载均衡无需手动干预,能够自动适应 Pod 的变化。