2. Envoy 架构核心:Listener、Cluster、Endpoint、Route、Filter 链

Envoy 作为服务网格的数据面核心,其架构围绕五个关键抽象构建:Listener(监听器)、Cluster(集群)、Endpoint(端点)、Route(路由)和 Filter 链(过滤器链)。理解这五个组件及其协作关系,是进行流量拓扑分析和日志故障排查的基础。

核心原则:Envoy 采用“先监听、再路由、后转发”的流水线模型。流量从 Listener 进入,经过 Filter 链处理,由 Route 匹配规则,最终转发到 Cluster 中的某个 Endpoint。

2.1 五大核心组件概述

组件 职责 故障排查关注点
Listener 定义 Envoy 监听的 IP 地址和端口,接收入站流量。 端口冲突、监听失败、TLS 证书加载错误。
Filter 链 挂载在 Listener 上的处理管道,执行协议解析、流量劫持、日志生成等。 过滤器顺序错误、配置缺失导致连接断开、日志字段丢失。
Route 根据请求属性(Host、Path、Header)匹配虚拟主机,决定流量去向。 路由规则未命中、权重分配异常、重定向循环。
Cluster 定义一组提供相同服务的上游主机集合,包含负载均衡策略和健康检查。 集群为空、健康检查失败、连接池耗尽。
Endpoint Cluster 中的具体上游实例(IP:Port),是流量的最终目的地。 端点不可达、DNS 解析失败、熔断触发。

2.2 组件协作流程

下图展示了 Envoy 处理一次请求的完整路径,从 Listener 接收到 Endpoint 转发,清晰呈现了五个核心组件的协作关系。

Envoy 核心组件协作流程 Envoy 核心组件协作流程 外部流量 Listener (0.0.0.0:80) Filter 链 HTTP 连接管理器 | RBAC | 限流 | 日志 Route 匹配 Cluster (service-v1) Endpoint 列表 10.0.1.2:8080, 10.0.1.3:8080

2.3 Listener 与 Filter 链详解

Listener 是流量的入口。每个 Listener 可以绑定多个 Filter 链,通过 filter_chain_match 条件(如 SNI、ALPN、源 IP)进行区分。最常见的场景是:一个 Listener 同时处理 HTTP 和 HTTPS 流量,通过 TLS 检查器过滤器分流。

排查技巧:当客户端连接被拒绝时,优先检查 Listener 的 bind_to_port 和 reuse_port 配置。使用 curl -v 测试端口可达性,结合 Envoy 的 /listeners 管理端点确认监听状态。

2.4 Route 与 Cluster 的映射关系

Route 配置位于 HTTP 连接管理器(HCM) 过滤器内部。一个典型的虚拟主机(VirtualHost)包含多个路由规则,每个规则指向一个 Cluster。Envoy 支持多种路由匹配条件:

  • 前缀匹配:prefix: /api/v1 → 匹配以该路径开头的请求。
  • 精确匹配:path: /healthz → 仅匹配完全相同的路径。
  • 正则匹配:safe_regex: /users/\d+ → 匹配用户 ID 为数字的请求。
  • Header 匹配:headers: [name: :method, value: POST] → 仅匹配 POST 方法。

2.5 Cluster 与 Endpoint 的负载均衡

Cluster 管理一组 Endpoint,Envoy 支持多种负载均衡策略:

策略 说明 适用场景
轮询(ROUND_ROBIN) 依次将请求分发到每个 Endpoint。 通用场景,各实例性能相近。
最少请求(LEAST_REQUEST) 选择当前活跃请求数最少的 Endpoint。 请求处理时间差异大的场景。
一致性哈希(RING_HASH) 根据请求属性(如源 IP、Cookie)哈希到固定 Endpoint。 需要会话保持的场景。
随机(RANDOM) 随机选择一个 Endpoint。 测试或低负载场景。
常见故障:当 Cluster 的 type 设置为 STRICT_DNS 时,如果 DNS 解析失败或返回空结果,Envoy 会标记该集群为“未就绪”,导致 503 响应。排查时检查 /clusters 管理端点,观察 membership_total 和 host_status 字段。

2.6 配置示例:核心组件联动

以下是一个简化的 Envoy 配置片段,展示了 Listener、Filter 链、Route、Cluster 和 Endpoint 的完整定义:

static_resources:
  listeners:
  - name: ingress_listener
    address:
      socket_address: { address: 0.0.0.0, port_value: 80 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains: ["*"]
              routes:
              - match: { prefix: "/api" }
                route: { cluster: service_cluster }
          http_filters:
          - name: envoy.filters.http.router

  clusters:
  - name: service_cluster
    type: STRICT_DNS
    lb_policy: LEAST_REQUEST
    load_assignment:
      cluster_name: service_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address: { address: service.default.svc.cluster.local, port_value: 8080 }

该配置中,Envoy 在 80 端口监听,所有进入的 HTTP 请求经过 HTTP 连接管理器过滤器,匹配 /api 前缀的请求被路由到 service_cluster,该集群通过 DNS 解析获取 Endpoint 列表,并使用最少请求策略进行负载均衡。