3. 服务发现与DNS代理:多集群服务发现原理、DNS代理配置、跨集群服务路由

3.1 多集群服务发现的核心挑战

在单集群 Service Mesh 中,服务发现依赖控制面(如 Istiod)从 API Server 获取 Service/Endpoint 变更,并通过 xDS 协议推送给数据面 Sidecar。当扩展到多集群时,服务发现面临以下根本性变化:

维度 单集群 多集群
命名空间 全局唯一 集群间可能重叠
网络平面 扁平互通 需跨集群隧道或网关
端点可见性 本地 API Server 实时推送 需跨集群同步或联邦
DNS 解析 CoreDNS 集群内解析 需全局 DNS 或代理
负载均衡 本地端点权重 需感知地域/集群优先级
关键结论:多集群服务发现不能简单复用单集群模型,必须引入全局服务注册表和智能 DNS 代理来统一端点视图与路由策略。

3.2 多集群服务发现原理

主流 Service Mesh(Istio、Consul Connect、Kuma)均采用控制面聚合 + 数据面按需拉取的架构。以 Istio 多集群 Primary-Remote 模型为例,其服务发现流程如下:

  1. 端点采集:每个集群的 Istiod 监听本地 Service/Endpoint 变更。
  2. 跨集群同步:Primary 集群 Istiod 通过 Remote Secret 访问 Remote 集群 API Server,拉取远程端点信息;或通过 Mesh Federation 协议交换。
  3. 全局端点合并:Primary Istiod 将本地与远程端点合并为统一 ServiceEntry,附加集群标签(cluster_name)和地域标签(region/zone)。
  4. xDS 推送:Primary Istiod 将合并后的端点列表通过 EDS(Endpoint Discovery Service)推送给所有数据面 Sidecar。
  5. 本地 DNS 代理:Sidecar 内置的 DNS 代理拦截应用 DNS 查询,返回虚拟 IP(VIP)或直接返回端点 IP 列表。
多集群服务发现原理(Istio Primary-Remote 模型) 集群 A(Primary) Istiod(控制面) API Server Service A (v1) Sidecar Proxy DNS 代理 集群 B(Remote) Istiod(远程) API Server Service A (v2) Sidecar Proxy DNS 代理 Remote Secret / Federation 全局服务注册表(ServiceEntry)
实践要点:Remote 集群的 Istiod 不需要直接暴露 xDS 端口,所有数据面配置均由 Primary 集群统一推送。这降低了 Remote 集群的控制面暴露面,但要求 Primary 集群必须稳定且网络延迟可控。

3.3 DNS 代理配置

Service Mesh 的 DNS 代理位于 Sidecar 内部,拦截容器内所有 DNS 查询(默认监听 127.0.0.1:15053 或 :15053)。其核心配置项如下:

配置项 作用 推荐值
dns.port DNS 代理监听端口 15053
dns.capture 是否劫持容器 DNS 流量 true
dns.rateLimit 每秒最大 DNS 查询数 100
dns.ttl DNS 缓存 TTL(秒) 30
dns.searchNamespaces 搜索域列表,用于短名称解析 ["global", "svc.cluster.local"]

在 Istio 中,DNS 代理通过 MeshConfig 或 ProxyConfig 启用:

apiVersion: v1
kind: ConfigMap
metadata:
  name: istio-mesh-config
  namespace: istio-system
data:
  mesh: |-
    defaultConfig:
      proxyMetadata:
        ISTIO_META_DNS_CAPTURE: "true"
        ISTIO_META_DNS_PORT: "15053"
    dns:
      capture: true
      rateLimit: 100
      ttl: 30s
      searchNamespaces:
        - global
        - svc.cluster.local
避坑提醒:如果应用使用 nslookup 或 dig 直接查询上游 DNS(如 8.8.8.8),Sidecar DNS 代理不会拦截。必须确保容器 DNS 配置指向 127.0.0.1,或通过 iptables 规则强制重定向 UDP 53 端口。

3.4 跨集群服务路由

跨集群路由依赖全局服务条目(ServiceEntry)和地域感知负载均衡(Locality-Aware LB)。典型配置流程如下:

  1. 定义 ServiceEntry:将远程集群的服务端点注册为 Mesh 内部服务。
  2. 附加集群标签:在端点元数据中标记 cluster_name、region、zone。
  3. 配置 DestinationRule:设置负载均衡策略(如 ROUND_ROBIN)和地域权重。
  4. 启用 DNS 代理:确保 Sidecar 能解析跨集群服务名。

以下是一个跨集群路由的 DestinationRule 示例:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: service-a-dr
  namespace: default
spec:
  host: service-a.global
  trafficPolicy:
    loadBalancer:
      localityLbSetting:
        enabled: true
        distribute:
          - from: region-a/zone-1/*
            to:
              "region-a/zone-1/*": 80
              "region-b/zone-1/*": 20
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2
跨集群服务路由流程 客户端 Pod DNS 查询 Sidecar DNS 代理 全局服务注册表 查询 VIP 返回 VIP 路由决策 集群 A(本地) Service A v1 (权重 80%) 集群 B(远程) Service A v2 (权重 20%) 80% 流量 20% 流量 地域感知负载均衡:优先本地,按权重分发远程

3.5 多集群 DNS 代理最佳实践

  • 统一搜索域:所有集群使用 global 作为跨集群服务后缀(如 service-a.global),避免命名冲突。
  • 缓存与 TTL 平衡:跨集群链路延迟较高,建议 TTL 设为 30-60 秒,减少 DNS 查询频率;但不要超过 120 秒,否则端点变更收敛慢。
  • 健康检查联动:DNS 代理应配合 Outlier Detection,当远程集群端点异常时,自动从 DNS 响应中移除,避免客户端重试。
  • 故障域隔离:在 DestinationRule 中设置 failoverPriority,优先路由到同 region 端点,region 故障时再跨 region 切换。
移植适配要点:当从单集群迁移到多集群时,原有应用代码中的 service-a.namespace.svc.cluster.local 需要改为 service-a.global。如果应用硬编码了 DNS 后缀,必须通过 dns.searchNamespaces 或环境变量 DNS_DOMAIN 进行适配,否则跨集群解析会失败。