服务发现

最常见的说法是 “两种核心机制”,但这指的是服务发现的两种基本模式,而不是具体的实现方式。


维度一:两种核心模式

这是从服务发现的基本原理上划分的。

  1. 基于客户端服务发现

    • 工作原理:客户端(服务消费者)通过查询一个中心化的服务注册中心(如 Consul、Eureka、Zookeeper)来获取所有可用服务实例的列表(通常是 IP 和端口),然后自己选择一个实例并直接向其发起请求。
    • 类比:就像你去餐厅吃饭,先看门口的电子菜单(服务注册中心)了解所有菜品和价格,然后自己决定点什么,再告诉服务员。
    • 特点:客户端需要内置服务发现逻辑,与服务注册中心耦合。这种方式更灵活,但增加了客户端的复杂性。
  2. 基于服务端服务发现

    • 工作原理:客户端不关心具体的服务实例,它只需要向一个固定的访问端点(通常是 Load Balancer 或 Proxy,如 Kubernetes Service)发起请求。这个端点负责去服务注册中心查询可用实例,并进行负载均衡,将请求转发给其中一个。
    • 类比:就像你去餐厅直接告诉服务员“来份招牌菜”,服务员(负载均衡器)帮你和后厨(服务实例)沟通,最后把菜端给你。
    • 特点:客户端无需知道服务发现的具体细节,简化了客户端。这是 Kubernetes 默认采用的方式

维度二:Kubernetes 中具体的实现方式

在 Kubernetes 内部,我们通常讨论以下几种具体的服务发现实现手段,它们共同构成了 Kubernetes 强大的服务发现能力。

1. 环境变量

当 Pod 被调度到某个节点上时,kubelet 会为当前集群中存在的每个 Service 添加一组环境变量到该 Pod 中。

  • 格式{SVCNAME}_SERVICE_HOST{SVCNAME}_SERVICE_PORT
  • 例子:一个名为 redis-master 的 Service 会生成 REDIS_MASTER_SERVICE_HOST=10.0.0.11REDIS_MASTER_SERVICE_PORT=6379 这样的环境变量。
  • 局限性:环境变量必须在 Pod 创建之前就存在。后创建的 Service 无法将环境变量注入到已运行的 Pod 中。因此,这通常作为辅助手段

2. DNS(最核心、最推荐的方式)

这是 Kubernetes 最主要和最优雅的服务发现方式。

  • 工作原理:Kubernetes 集群内置了一个 DNS 服务器(通常是 CoreDNS)。当你创建一个 Service 时,Kubernetes 会自动为这个 Service 注册一个 DNS 记录。
  • DNS 记录格式
    • 同一命名空间<service-name>.<namespace>.svc.cluster.local -> 指向 Service 的 Cluster IP。
      • 在同一个命名空间内,你可以直接使用 <service-name> 来访问服务。例如,前端 Pod 访问后端服务,只需使用 http://backend-service
    • 不同命名空间:需要使用全限定域名,例如 backend-service.production.svc.cluster.local
  • 优点:行为符合标准,应用无需修改代码,直接使用域名即可访问其他服务。

3. Kubernetes Service

Service 资源对象本身就是服务发现的载体。它提供了一个稳定的访问端点(VIP 或 DNS 名称),背后对应一组动态变化的 Pod。

  • ClusterIP:默认类型,提供一个集群内部的虚拟 IP,只能从集群内部访问。结合 DNS 使用,是服务间通信的基石。
  • NodePort:在 ClusterIP 基础上,在每个节点上暴露一个静态端口。可以从集群外部通过 <NodeIP>:<NodePort> 访问服务。
  • LoadBalancer:在 NodePort 基础上,利用云服务商提供的负载均衡器,将一个外部 IP 地址暴露给 Service。是向公网暴露服务的主要方式。
  • Headless Service:一种特殊的 Service,当你不需要负载均衡和单个 Service IP 时,可以通过设置 clusterIP: None 来创建。DNS 查询会返回该 Service 后端所有 Pod 的 IP 地址列表,而不是一个 VIP。这常用于有状态应用(如 Kafka、MySQL 集群)的自定义负载均衡或状态同步。

4. Ingress

虽然 Ingress 主要被用作 HTTP/HTTPS 路由规则的七层代理,但它也是一种高级的服务发现形式。

  • 它通过规则将外部流量路由到集群内部相应的 Service。
  • 客户端(外部用户)通过访问 Ingress Controller 的地址来发现和访问后端服务。

总结与对比

方式原理适用场景特点
环境变量将 Service 信息注入 Pod 环境变量旧式应用,辅助手段简单,但有局限性(需先于 Pod 创建)
DNS为 Service 自动注册域名服务间通信的标准方式推荐,符合惯例,无需代码改造
Service提供稳定的虚拟 IP 或 DNS 名称服务暴露和负载均衡的核心抽象Kubernetes 服务发现的基石
Ingress七层 HTTP 路由对外暴露 Web 服务,基于域名和路径路由更高级的 API 网关模式

结论:

  • 从模式上讲,Kubernetes 主要采用基于服务端的服务发现模式。
  • 从具体实现上讲,Kubernetes 的服务发现是一个以 DNS 为核心、以 Service 为基石的完整体系,并辅以环境变量和 Ingress 等机制。

所以,当有人问“K8s服务发现有哪些方式”时,最准确的回答是:主要有基于 DNS 和 环境变量这两种内部发现机制,而它们都依赖于 Service 这个核心抽象。同时,Ingress 提供了外部到内部的服务发现和路由能力。