服务发现
最常见的说法是 “两种核心机制”,但这指的是服务发现的两种基本模式,而不是具体的实现方式。
维度一:两种核心模式
这是从服务发现的基本原理上划分的。
基于客户端服务发现
- 工作原理:客户端(服务消费者)通过查询一个中心化的服务注册中心(如 Consul、Eureka、Zookeeper)来获取所有可用服务实例的列表(通常是 IP 和端口),然后自己选择一个实例并直接向其发起请求。
- 类比:就像你去餐厅吃饭,先看门口的电子菜单(服务注册中心)了解所有菜品和价格,然后自己决定点什么,再告诉服务员。
- 特点:客户端需要内置服务发现逻辑,与服务注册中心耦合。这种方式更灵活,但增加了客户端的复杂性。
基于服务端服务发现
- 工作原理:客户端不关心具体的服务实例,它只需要向一个固定的访问端点(通常是 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.11和REDIS_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 提供了外部到内部的服务发现和路由能力。