3. 网格拓扑基础:服务注册、服务发现、流量路由规则、VirtualService 与 DestinationRule

在 Istio 网格中,服务间的通信并非直接由 Pod IP 或 Service ClusterIP 驱动,而是通过一套抽象的控制平面组件与数据平面代理协同完成。理解网格拓扑,首先需要掌握服务如何被注册、发现,以及流量如何被规则引导。本章将拆解这四个核心概念,并重点分析 VirtualService 与 DestinationRule 的协作关系。

3.1 服务注册与发现:网格的“通讯录”

传统 Kubernetes 中,服务发现依赖 kube-proxy 和 ClusterIP。在 Istio 网格中,Pilot 组件接管了这一职责,构建出更精细的“服务注册中心”。

组件/概念 角色说明 数据来源
Pilot 网格控制平面核心,负责服务发现与配置下发 Kubernetes API Server + Service/Endpoint
Service Registry Pilot 内部维护的服务与实例映射表 自动同步自 K8s Service & Pod
Envoy (Sidecar) 数据平面代理,通过 xDS 协议从 Pilot 拉取发现结果 Pilot 下发的 LDS/CDS/EDS
ServiceEntry 手动注册外部服务到网格的 CRD 用户 YAML 定义
关键理解: 网格内的服务发现粒度是 Pod 级别 的。Envoy 拿到的是后端 Pod 的 IP:Port 列表,而非 Service ClusterIP。这使得 L7 路由和灰度发布成为可能。

3.2 流量路由规则:VirtualService 与 DestinationRule

流量路由是 Istio 最核心的运维能力。它通过两个 CRD 解耦了“路由逻辑”与“后端策略”:

  • VirtualService:定义“流量怎么走”。匹配来源、路径、Header,然后转发到指定 Host。
  • DestinationRule:定义“后端怎么处理”。配置负载均衡、连接池、熔断、TLS 以及子集(Subset)划分。
常见误区: VirtualService 中 host 字段指向的是 K8s Service 的 DNS 名称,而非 Pod IP。DestinationRule 中的 host 必须与 VirtualService 中 host 或 destination.host 完全匹配,否则规则不生效。

3.3 VirtualService 深度解析

VirtualService 是网格流量的“交通指挥员”。它支持丰富的匹配条件和流量操作。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: reviews-vs
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 80
    - destination:
        host: reviews
        subset: v3
      weight: 20

上述配置的关键点:

  • hosts:监听 reviews 服务的流量。
  • match:如果 Header end-user 等于 jason,则路由到 subset: v2。
  • weight:其余流量按 80/20 比例分发到 v1 和 v3。

3.4 DestinationRule 与 Subset 定义

DestinationRule 负责定义后端实例的分组(Subset)以及流量策略。Subset 通常基于 Pod 的标签(如 version: v1)进行选择。

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: reviews-dr
spec:
  host: reviews
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
    connectionPool:
      tcp:
        maxConnections: 100
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3
协作关系: VirtualService 中的 subset: v2 必须对应 DestinationRule 中定义的 subsets[0].name: v2。如果 DestinationRule 未定义 v2,VirtualService 引用 v2 会导致路由失败。

3.5 网格拓扑与路由规则的关系图

下图展示了从客户端请求到后端 Pod 的完整拓扑路径,以及 VirtualService 和 DestinationRule 在其中的作用位置。

网格拓扑与路由规则协作流程 客户端 (Pod) Ingress Gateway VirtualService 匹配 → 路由 → 权重 DestinationRule Subset + 策略 Subset 实例池 v1 (80%) v2 (0%) v3 (20%) Pod: reviews-v1 Pod: reviews-v2 Pod: reviews-v3 说明: VirtualService 决定流量去哪个 Subset;DestinationRule 定义 Subset 的标签选择器和负载均衡策略。两者缺一不可。

3.6 服务发现与路由的完整数据流

为了更清晰地理解控制平面与数据平面的交互,下图展示了 Pilot 如何将 Service、VirtualService、DestinationRule 转化为 Envoy 可理解的配置。

控制平面 → 数据平面:配置下发流程 K8s API Server Service / Pod / Endpoint Pilot 聚合 + 转换 Envoy Sidecar xDS 监听 路由表 Cluster + Subset VirtualService CRD DestinationRule CRD 数据流总结: 1. Pilot 从 K8s API 监听 Service/Endpoint,同时监听 VirtualService 和 DestinationRule。 2. Pilot 将三者合并为 Envoy 的 Cluster、Listener、Route 配置,通过 xDS 下发。 3. Envoy 根据路由表直接转发流量到目标 Pod,不再经过 kube-proxy。

3.7 故障排查要点

当网格拓扑出现流量中断或路由异常时,按以下顺序排查:

  1. 检查 Service 是否存在:kubectl get svc reviews,确认 Selector 匹配到 Pod。
  2. 检查 VirtualService 是否生效:istioctl proxy-status 确认 Sidecar 已收到配置。
  3. 检查 DestinationRule Subset 标签:kubectl get pod -l version=v2,确认 Pod 存在且标签正确。
  4. 检查 Envoy 路由表:istioctl proxy-config route <pod-name> 查看实际路由条目。
  5. 检查 Pilot 日志:kubectl logs -n istio-system deployment/istiod 搜索 reviews 相关错误。
核心原则: 网格拓扑的故障 90% 源于 VirtualService 的 host 与 DestinationRule 的 host 不匹配,或者 Subset 标签与 Pod 标签不一致。始终从“两端对齐”的角度入手。