Istio Pilot Discovery 深入剖析与流程图

Istio Pilot-Discovery 深入剖析与流程图

本文对 Istio 控制面的核心组件 Pilot-Discovery(通常作为 Istiod 的发现服务部分)进行系统性拆解与讲解,并配套 Mermaid 流程图来说明其关键启动路径、ADS 连接与订阅、以及 Push 配置下发流程。全文以仓库中的源码为依据,保证技术细节准确可溯源。

参考源码入口与目录:

  • 启动命令入口:pilot/cmd/pilot-discovery/main.gopilot/cmd/pilot-discovery/app/cmd.go
  • 服务器参数与选项:pilot/pkg/bootstrap/options.go
  • XDS 发现与推送核心:pilot/pkg/xds/discovery.go 及各类型生成器(LDS/RDS/CDS/EDS/ECDS/NDS)

1. 组件职责与定位

Pilot-Discovery 是 Istio 控制面中为数据面(Envoy/Sidecar)提供动态配置的服务。核心职责:

  • 暴露 gRPC 的 XDS/ADS 接口,接收 Sidecar 订阅并推送配置;
  • 维护全局服务与端点缓存(EndpointShards)、PushContext 以及各类生成器;
  • 聚合多个服务注册中心(默认 Kubernetes),监听配置/服务变化并去抖合并事件;
  • 提供监控与调试接口(HTTP/Monitoring、CtrlZ),可选地提供注入与校验的 HTTPS Webhook;
  • 管理连接状态、流控与速率限制,支持增量/全量推送与缓存优化。

2. 启动流程总览

入口位于 pilot/cmd/pilot-discovery/main.go

1
2
3
4
5
6
7
8
func main() {
    log.EnableKlogWithCobra()
    rootCmd := app.NewRootCommand()
    if err := rootCmd.Execute(); err != nil {
        log.Error(err)
        os.Exit(-1)
    }
}

NewRootCommand()app/cmd.go 中定义。其子命令 discoveryRunE 会:

  1. 打印 flags,创建 stop channel;
  2. 调用 bootstrap.NewServer(serverArgs) 构建发现服务实例;
  3. 调用 discoveryServer.Start(stop) 启动所有端口与控制循环;
  4. 监听退出信号并优雅关闭。

关键端口(均由 addFlags 通过 PersistentFlags 配置):

  • httpAddr(默认 :8080):调试/健康检查/部分 HTTP 接口;
  • httpsAddr(默认 :15017):注入与校验 Webhook(可选);
  • grpcAddr(默认 :15010):XDS/ADS 非 TLS gRPC;
  • secureGRPCAddr(默认 :15012):XDS/ADS TLS gRPC;
  • monitoringAddr(默认 :15014):自监控/指标暴露。

PilotArgs 与 DiscoveryServerOptions 定义在 pilot/pkg/bootstrap/options.go,可通过命令行与环境变量(如 POD_NAMESPACEREVISION)定制。

关键代码片段(cmd.go - PreRunE 与 RunE)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
func newDiscoveryCommand() *cobra.Command {
    return &cobra.Command{
        Use:   "discovery",
        Short: "Start Istio proxy discovery service.",
        Args:  cobra.ExactArgs(0),
        PreRunE: func(c *cobra.Command, args []string) error {
            if err := log.Configure(loggingOptions); err != nil { return err }
            if err := validateFlags(serverArgs); err != nil { return err }
            if err := serverArgs.Complete(); err != nil { return err }
            return nil
        },
        RunE: func(c *cobra.Command, args []string) error {
            cmd.PrintFlags(c.Flags())
            stop := make(chan struct{})
            discoveryServer, err := bootstrap.NewServer(serverArgs)
            if err != nil {
                return fmt.Errorf("failed to create discovery service: %v", err)
            }
            if err := discoveryServer.Start(stop); err != nil {
                return fmt.Errorf("failed to start discovery service: %v", err)
            }
            cmd.WaitSignal(stop)
            discoveryServer.WaitUntilCompletion()
            return nil
        },
    }
}

启动流程图(Mermaid)

flowchart TD
    A[main.go 启动] --> B[app.NewRootCommand]
    B --> C{选择子命令}
    C -->|discovery| D[PreRun: 配置日志/校验/Complete]
    D --> E[RunE: 打印flags, 创建stop chan]
    E --> F["bootstrap.NewServer(serverArgs)"]
    F --> G[构建 Model Environment / 注册中心 / XDS DiscoveryServer]
    G --> H["Start(): 启动 HTTP/HTTPS/gRPC/监控端口"]
    H --> I[初始化生成器、缓存、去抖队列]
    I --> J[侦听注册中心与配置变化]
    J --> K[等候退出信号]
    K --> L[WaitUntilCompletion & 优雅关闭]
flowchart TD
    A[main.go 启动] --> B[app.NewRootCommand]
    B --> C{选择子命令}
    C -->|discovery| D[PreRun: 配置日志/校验/Complete]
    D --> E[RunE: 打印flags, 创建stop chan]
    E --> F["bootstrap.NewServer(serverArgs)"]
    F --> G[构建 Model Environment / 注册中心 / XDS DiscoveryServer]
    G --> H["Start(): 启动 HTTP/HTTPS/gRPC/监控端口"]
    H --> I[初始化生成器、缓存、去抖队列]
    I --> J[侦听注册中心与配置变化]
    J --> K[等候退出信号]
    K --> L[WaitUntilCompletion & 优雅关闭]
flowchart TD
    A[main.go 启动] --> B[app.NewRootCommand]
    B --> C{选择子命令}
    C -->|discovery| D[PreRun: 配置日志/校验/Complete]
    D --> E[RunE: 打印flags, 创建stop chan]
    E --> F["bootstrap.NewServer(serverArgs)"]
    F --> G[构建 Model Environment / 注册中心 / XDS DiscoveryServer]
    G --> H["Start(): 启动 HTTP/HTTPS/gRPC/监控端口"]
    H --> I[初始化生成器、缓存、去抖队列]
    I --> J[侦听注册中心与配置变化]
    J --> K[等候退出信号]
    K --> L[WaitUntilCompletion & 优雅关闭]

3. DiscoveryServer 核心数据结构与职责

位于 pilot/pkg/xds/discovery.goDiscoveryServer 是 ADS/XDS 的核心,其关键字段与职责包括:

  • Env *model.Environment:全局环境上下文,含 Mesh 配置、服务注册表等;
  • EndpointShardsByService:按服务/命名空间聚合的端点分片缓存(来自不同注册中心/集群);
  • pushChannelpushQueue:用于去抖(debounce)后的异步推送队列;
  • GeneratorsConfigGenerator:按 TypeURL(LDS/RDS/CDS/EDS/ECDS/NDS)生成对应配置;
  • adsClients:当前活跃的 ADS/EDS gRPC 连接集合,管理连接状态与订阅主题;
  • ProxyNeedsPush:判断某代理是否需要本次 Push 的谓词,避免不必要下发;
  • Cache:XDS 缓存(由特性 EnableXDSCaching 控制);
  • debounceOptions:去抖窗口(DebounceAfter/DebounceMax,含 EDS 专用);
  • 监控与状态:InboundUpdatesCommittedUpdatesStatusReporter 等。

构造函数 NewDiscoveryServer(env, plugins, instanceID, systemNamespace, clusterAliases) 完成初始化(JWT 解析器、缓存开关、ConfigGenerator 实例化等)。


4. ADS 连接与订阅

Sidecar 与 Pilot-Discovery 建立 gRPC 流(ADS/增量),按需订阅 TypeURL。

  • Pilot 注册 gRPC 服务(Register(rpcs *grpc.Server)),挂载 Discovery/DeltaDiscovery;
  • 首次连接进行认证(Authenticators)与集群别名映射(ClusterAliases);
  • 连接建立后,Connection 跟踪订阅类型、nonce/version 以及上次 ACK/NACK 状态。

ADS 连接与订阅流程图(Mermaid)

flowchart TD
    A[Sidecar 启动] --> B["连接 Pilot gRPC (15010/15012)"]
    B --> C{认证/握手}
    C -->|通过| D[建立 ADS 双向流]
    D --> E["发送初始 DiscoveryRequest(含 TypeURL/token/node)"]
    E --> F[Pilot 记录连接/订阅信息]
    F --> G[生成初始配置并返回 DiscoveryResponse]
    G --> H{Sidecar 校验}
    H -->|ACK| I[更新订阅状态, 继续增量或后续订阅]
    H -->|NACK| J[记录错误, 可重试/修复后再次下发]
flowchart TD
    A[Sidecar 启动] --> B["连接 Pilot gRPC (15010/15012)"]
    B --> C{认证/握手}
    C -->|通过| D[建立 ADS 双向流]
    D --> E["发送初始 DiscoveryRequest(含 TypeURL/token/node)"]
    E --> F[Pilot 记录连接/订阅信息]
    F --> G[生成初始配置并返回 DiscoveryResponse]
    G --> H{Sidecar 校验}
    H -->|ACK| I[更新订阅状态, 继续增量或后续订阅]
    H -->|NACK| J[记录错误, 可重试/修复后再次下发]
flowchart TD
    A[Sidecar 启动] --> B["连接 Pilot gRPC (15010/15012)"]
    B --> C{认证/握手}
    C -->|通过| D[建立 ADS 双向流]
    D --> E["发送初始 DiscoveryRequest(含 TypeURL/token/node)"]
    E --> F[Pilot 记录连接/订阅信息]
    F --> G[生成初始配置并返回 DiscoveryResponse]
    G --> H{Sidecar 校验}
    H -->|ACK| I[更新订阅状态, 继续增量或后续订阅]
    H -->|NACK| J[记录错误, 可重试/修复后再次下发]

5. 推送流程与触发源

当注册中心(服务/端点)或 Istio 配置(VirtualService/Gateway 等)发生变化时,会触发 Push:

  1. 事件入队:ConfigUpdate(req *model.PushRequest) 写入 pushChannel
  2. 去抖与合并:在 debounceAfterdebounceMax 窗口内合并事件;
  3. 构建上下文:initPushContext(req, old, version) 汇总变更为 PushContext
  4. 筛选代理:遍历 adsClients,结合 ProxyNeedsPush 与订阅类型过滤;
  5. 调用生成器:按 TypeURL(LDS/RDS/CDS/EDS/ECDS/NDS)生成资源;
  6. 缓存与版本:命中/回填 XDS 缓存,生成 nonce/version
  7. 通过 gRPC 流发送 DiscoveryResponse,并记录指标。

触发 Push 的典型来源

  • 控制面配置变化(常导致 Full 或按类型的 Push):

    • VirtualService、DestinationRule、Gateway、Sidecar、EnvoyFilter 的新增/更新/删除;
    • ServiceEntry、WorkloadEntry/WorkloadGroup 变更(地址、端口、标签、证书等);
    • 认证与安全策略:RequestAuthentication、AuthorizationPolicy、PeerAuthentication、Telemetry;
    • MeshConfig、Networks 文件变更(如 meshConfigmeshNetworks);
    • 命名空间或选择器影响范围变化(Sidecar 作用域、命名空间标签变化)。
  • 服务注册中心事件(通常为增量 EDS,必要时扩展为 CDS/RDS/LDS):

    • Kubernetes Service/EndpointSlice 的新增/删除/更新(端口、标签、选择器变化);
    • Pod/Workload 的新增/删除/状态变化(Ready/NotReady、IP 变更、注入状态/labels/annotations 变化);
    • 多集群/多注册中心端点变更(分片 ShardKey 更新)。当 EndpointShards.ServiceAccounts 变化时,为更新 SAN 会触发 Full Push。
  • 证书与信任相关触发:

    • JWT 公钥变更:JwtKeyResolver.PushFunc 检测到更新时触发 Full: true
    • Trust bundle/根证书更新:影响双向 TLS 校验,通常触发 CDS/LDS/RDS 的重建。
  • 连接与会话层触发:

    • Sidecar 新连接/重连:首次建立 ADS 流时发送初始配置;重连基于当前 PushContext 重新下发;
    • NACK:Envoy 对某次下发 NACK(资源校验失败)时,Pilot 记录并在修复后重推该类型资源。
  • 手动/运维触发:

    • 通过调试接口或管理命令触发重建上下文或清理缓存(可强制全量下发)。

Push 下发流程图(Mermaid)

flowchart TD
    A[配置/服务事件] --> B[ConfigUpdate: 写入 pushChannel]
    B --> C{Debounce: 等待窗口}
    C -->|窗口结束| D[合并请求 → pushQueue]
    D --> E[initPushContext: 生成全局上下文]
    E --> F["选择需要推送的连接(adsClients)"]
    F --> G[按订阅类型调用生成器: LDS/RDS/CDS/EDS/...]
    G --> H[命中/回填 XDS 缓存]
    H --> I["组装 DiscoveryResponse(nonce/version)"]
    I --> J[通过 gRPC 流发送]
    J --> K{Sidecar ACK/NACK}
    K -->|ACK| L[推进版本, 记录状态]
    K -->|NACK| M[记录错误, 可重试]
flowchart TD
    A[配置/服务事件] --> B[ConfigUpdate: 写入 pushChannel]
    B --> C{Debounce: 等待窗口}
    C -->|窗口结束| D[合并请求 → pushQueue]
    D --> E[initPushContext: 生成全局上下文]
    E --> F["选择需要推送的连接(adsClients)"]
    F --> G[按订阅类型调用生成器: LDS/RDS/CDS/EDS/...]
    G --> H[命中/回填 XDS 缓存]
    H --> I["组装 DiscoveryResponse(nonce/version)"]
    I --> J[通过 gRPC 流发送]
    J --> K{Sidecar ACK/NACK}
    K -->|ACK| L[推进版本, 记录状态]
    K -->|NACK| M[记录错误, 可重试]
flowchart TD
    A[配置/服务事件] --> B[ConfigUpdate: 写入 pushChannel]
    B --> C{Debounce: 等待窗口}
    C -->|窗口结束| D[合并请求 → pushQueue]
    D --> E[initPushContext: 生成全局上下文]
    E --> F["选择需要推送的连接(adsClients)"]
    F --> G[按订阅类型调用生成器: LDS/RDS/CDS/EDS/...]
    G --> H[命中/回填 XDS 缓存]
    H --> I["组装 DiscoveryResponse(nonce/version)"]
    I --> J[通过 gRPC 流发送]
    J --> K{Sidecar ACK/NACK}
    K -->|ACK| L[推进版本, 记录状态]
    K -->|NACK| M[记录错误, 可重试]

6. 性能与可靠性机制

  • 去抖(Debounce):通过 debounceAfterdebounceMax 控制推送频率,平衡时延与抖动;
  • 并发与限流:concurrentPushLimit 控制并发推送;requestRateLimit 控制连接请求速率;
  • 缓存(XdsCache):减少重复生成开销,提高大规模环境下的推送效率;
  • 增量更新:按端点分片(EndpointShards)与订阅类型进行增量下发;
  • 状态与监控:pilot_xds_push_timepilot_xds_send_time 等指标便于观测与优化。

7. 端口与子系统

  • gRPC(:15010 / :15012):ADS/XDS(支持 TLS),数据面主要入口;
  • HTTP(:8080):调试与部分公开接口,HTTPS 关闭时可能承载非安全 Webhook;
  • HTTPS(:15017):注入与校验 Webhook(安全);
  • Monitoring(:15014):自监控指标暴露;
  • CtrlZ:交互式诊断(命令行可开启)。

8. 注册中心与多集群

  • 默认注册中心为 Kubernetes(--registries=kubernetes),也可启用 Mock 等;
  • 通过 ClusterAliases 统一多集群 ID,便于筛选与推送;
  • 端点分片(EndpointShards)以 ShardKey 分组(通常为注册中心/集群标识)。

9. 调试与问题定位建议

  • 连接检查:确认 Sidecar 到 Pilot 的 gRPC 连接(查看 ADS 客户端与握手日志);
  • ACK/NACK 观察:通过调试接口或日志查看 NACK 原因(常为过滤器不兼容或资源缺失);
  • Debounce:频繁更新时调大 DebounceAfter 或检查事件来源是否异常;
  • 缓存失效策略:必要时在 ConfigUpdate 中强制 Full 推送,排查缓存一致性问题;
  • 指标与火焰图:关注 pilot_xds_push_time_send_time 的分布,定位生成/发送热点。

9.1 实操:调试命令与手动触发上下文重建/缓存清理

为便于快速定位与验证,下列命令可直接复制使用。建议先将 istiod 的调试端口通过本地转发暴露出来:

  • 端口转发(默认 istiod 调试端口为 8080):

    • kubectl -n istio-system port-forward deploy/istiod- 8080:8080
  • 列出所有调试端点:

    • curl -s http://localhost:8080/debug/list | jq .
  • 查看 ADS 客户端连接与订阅资源:

    • curl -s http://localhost:8080/debug/adsz | jq .
  • 查看各代理的 xDS 同步状态(ACK/NACK):

    • curl -s http://localhost:8080/debug/syncz | jq .
  • 配置分发版本概览:

    • curl -s http://localhost:8080/debug/config_distribution | jq .
  • 查看/清理 Pilot 的 XDS 缓存:

    • 查看缓存条目:curl -s “http://localhost:8080/debug/cachez” | jq .
    • 查看缓存大小:curl -s “http://localhost:8080/debug/cachez?sizes=true” | jq .
    • 清空缓存:curl -s “http://localhost:8080/debug/cachez?clear=true”
  • 当前 PushContext 与最近一次推送状态:

    • 当前 PushContext:curl -s http://localhost:8080/debug/pushcontext | jq .
    • 最近一次推送状态:curl -s http://localhost:8080/debug/push_status | jq .
  • 针对某代理的 Sidecar 可见范围:

    • curl -s “http://localhost:8080/debug/sidecarz?proxyID=.” | jq .
  • 查看指定服务实例:

    • curl -s “http://localhost:8080/debug/instancesz?svc=” | jq .
  • 断开某代理连接(强制重连):

    • curl -s “http://localhost:8080/debug/force_disconnect?proxyID=.
  • 面向单代理的服务端 ConfigDump(Pilot 生成的期望动态配置):

    • curl -s “http://localhost:8080/debug/config_dump?proxyID=.” > pilot-config-dump.json
  • Envoy 侧实际配置(sidecar admin API):

    • kubectl -n exec -it -c istio-proxy – curl -sS http://localhost:15000/config_dump > envoy-config-dump.json

手动触发(说明与示例):

  • 一次性全量下发(不重建 PushContext):

    • curl -s “http://localhost:8080/debug/adsz?push=true”
    • 根据 pilot/pkg/xds/debug.gohandlePushRequest 逻辑,带 push 参数访问 /debug/adsz 会调用 AdsPushAll,使用当前的 PushContext 发起一次全量下发。
  • 清理缓存后全量下发:

    • curl -s “http://localhost:8080/debug/cachez?clear=true” && curl -s “http://localhost:8080/debug/adsz?push=true”
  • “重建” PushContext 的推荐方式(通过轻量配置变更触发 Full Push):

    • 原理:PushContext 的重建发生在服务端处理 ConfigUpdate 并进入 Full Push 时;调试端点不直接提供重建开关,但可以通过对任意被 Pilot 监听的资源进行无侵入的元数据变更来触发。
    • 示例 A(为某 Istio 资源添加/删除临时注解):
      1. 添加注解:kubectl -n annotate destinationrule debug-force-rebuild="$(date +%s)" –overwrite
      2. 删除注解:kubectl -n annotate destinationrule debug-force-rebuild- –overwrite
      3. 观察:Pilot 将产生新的 Push 版本;可通过 /debug/push_status/debug/pushcontext 验证。
    • 示例 B(为 mesh ConfigMap 添加临时注解):
      1. kubectl -n istio-system patch configmap istio -p ‘{“metadata”:{“annotations”:{“debug-force-rebuild”:"’"$(date +%s)"’"}}}’
      2. 注意:避免更改 MeshConfig 的功能性字段;仅做注解增删等元数据变更。
    • 示例 C(JWT 公钥变化触发):更新 RequestAuthentication 的 JWKS 或其 URL 时,Pilot 的 JwtKeyResolver 会清空缓存并触发推送(谨慎使用)。
    • 示例 D(创建后删除一个临时 ServiceEntry,不被现有路由引用):

安全提示:

  • 调试端点通常要求本地访问或通过与 XDS 相同的认证;使用 kubectl port-forward 到本地是最简单方式。
  • 在生产环境使用 /debug/force_disconnect、清理缓存或触发 Full Push 前,请评估对流量的影响并选择低峰期操作。
  • 通过“元数据注解”触发的上下文重建应确保不被业务逻辑引用,避免产生行为变更。

9.2 故障排查清单(Checklist)

  • 连接与证书(mTLS):

    • 检查 sidecar 到 Pilot 的 gRPC 连接是否稳定:/debug/connections/debug/adsz;查看 istio-proxy 与 Pilot 日志是否出现握手失败/证书错误。
    • 确认证书链与时间同步:SDS 是否正常下发,节点时钟是否偏差过大(> 1 分钟可能导致证书无效)。
    • 检查代理身份(SPIFFE ID)与命名空间是否匹配 Mesh 配置与授权策略。
  • 订阅与资源可见性:

    • 使用 /debug/adsz 查看每个连接的 Watches(订阅的 typeURL 与资源名),确认订阅是否覆盖预期资源。
    • 使用 /debug/sidecarz?proxyID=<pod>.<ns> 检查可见范围与 Sidecar 的入/出站主机;如可见性异常,检查 Sidecar CR 与 workloadSelector。
  • PushContext 与缓存:

    • 查看 /debug/push_status/debug/pushcontext,确认最近一次推送版本与关键视图(授权策略、跨网络网关)是否符合预期。
    • 若怀疑缓存污染,先 /debug/cachez?clear=true 清理缓存,再 /debug/adsz?push=true 发起全量下发观察效果。
    • 关注 Debounce 与并发限制:频繁更新导致推送延迟时,评估 DebounceAfter/DebounceMaxrequestRateLimit 设置;检查 pushQueue 是否积压。
  • 生成器输出差异对比:

    • Pilot 期望配置:/debug/config_dump?proxyID=<pod>.<ns> 导出期望的动态配置(listeners/clusters/routes/endpoints)。
    • Envoy 实际配置:从 sidecar admin API 获取 http://localhost:15000/config_dump
    • 对比两者的动态部分,重点检查:
      • Listener 冲突(端口/地址重复)、TLS 配置(SNI/证书引用)是否一致。
      • Route 规则(VirtualService 匹配、正则/前缀、重试/超时/故障注入)是否按预期展开;目标 cluster 是否存在。
      • Cluster 的 TLS/负载均衡设置与 DestinationRule 子集是否匹配;EDS 是否有健康端点。
      • EnvoyFilter/WasmPlugin 是否改写了关键字段导致结构不合法。
  • 注册中心与端点:

    • 使用 /debug/endpointz/debug/instancesz?svc=<FQDN>/debug/endpointShardz 检查端点分片与实例视图是否完整。
    • 多集群/跨网络场景:/debug/clusterz/debug/networkz/debug/mcsz 检查远端集群/网关/MCS 服务是否可见。
  • 网关/TLS:

    • 检查 Gateway 与 HTTP/TLS 监听器的 SNI、证书 Secret 引用与 SDS 下发状态;必要时比对 Pilot/Envoy 两侧的 listener 与 secret 状态。
  • 常用操作序列:

    • 清缓存 → 全量推送:/debug/cachez?clear=true/debug/adsz?push=true
    • 断开重连单代理:/debug/force_disconnect?proxyID=<pod>.<ns> → 观察其重新订阅与下发。
    • 通过元数据注解触发上下文重建(见 9.1 手动触发)。

9.3 常见 NACK 原因速查

  • EnvoyFilter/插件导致无效配置:

    • JSONPatch/mergePatch 改写错误路径或类型,生成非法 listener/route/cluster;Wasm 插件 ABI 或配置不兼容。
    • 处置:暂时禁用相关 EnvoyFilter/WasmPlugin 验证;在 Pilot 期望配置与 Envoy 实际配置中定位差异点。
  • 监听器冲突与非法组合:

    • 同地址/端口重复监听;过滤器链匹配条件重复或冲突;TLS Inspector 缺失但需要基于 SNI 的匹配。
    • 处置:检查 VirtualService/Gateway 下的端口/SNI 与 filter chain 组装顺序;必要时限缩可见性以避免重叠。
  • 路由配置错误:

    • 无效的 header/URI 匹配(正则不合法);引用的 subset/cluster 不存在;权重求和不为 100;非法重试/超时配置。
    • 处置:在 /debug/config_dump 的 routeConfiguration 中逐条核对匹配与目标 cluster;修正 DestinationRule 与 VirtualService。
  • 集群/TLS 配置异常:

    • DestinationRule 的 TLS 设置与服务端证书不匹配;引用的 Secret 不存在或 SDS 未就绪;
    • 处置:核对 TLS 模式(ISTIO_MUTUAL/SIMPLE/PASSTHROUGH)与证书链;检查 SDS 与 cert/key 路径。
  • 端点与网络可达性问题:

    • EDS 下发空或不健康;跨网络网关不可达;多集群远端未同步。
    • 处置:/debug/endpointz/debug/networkz/debug/clusterz 验证可达性与健康状态。
  • 版本/特性不匹配:

    • 使用了不被当前 Envoy 版本支持的过滤器或 API;typed_config 类型或版本不匹配。
    • 处置:检查代理与控制面的版本兼容矩阵;回退或升级相应扩展。
  • 识别 NACK 的方法:

    • kubectl logs -n <ns> <pod> -c istio-proxy 关键字过滤:NACK[xds]envoy config
    • /debug/syncz 中可见最近下发的版本与 ACK/NACK 状态,配合 /debug/adsz 的订阅资源定位类型。

9.4 推荐观测指标与阈值(15014/Prometheus)

  • 推送耗时相关:

    • pilot_xds_push_time_seconds(推送生成阶段的耗时分布)
    • pilot_xds_send_time_seconds(发送阶段耗时分布)
    • 建议:在中小规模集群中,P95 < 1s、P99 < 2s;超出需检查生成器热点与缓存/并发设置。
  • 推送频率与队列: - inbound_updates_total / committed_updates_total(进入/提交的更新次数) - push_queue_depth(如有暴露,关注队列长度是否长期>0)

    • 建议:队列深度长期为 0 或极低;若持续升高,检查 debounce 与事件风暴。
  • 连接与同步:

    • pilot_total_ads_clients(连接的 ADS 客户端数)
    • xds_acked_total / xds_nacked_total(如有对应指标,关注 NACK 比例)
    • 建议:NACK 比例应接近 0;若 > 1% 持续存在,应按“9.3 常见 NACK 原因速查”逐项排查。
  • 生成器与资源规模:

    • listeners/routes/clusters/endpoints 数量与大小(可从 config_dump 或 Prom 指标侧观测)
    • 建议:规模快速增长时,关注内存使用与生成/发送耗时的同步增长是否线性;必要时分域/分片。
  • 进程与性能:

    • Go runtime 指标(goroutines、GC、CPU):当推送高峰时是否出现过度 GC 或 goroutine 激增。
    • pprof(/debug/pprof)采样:定位生成器热路径与 JSON/Proto 序列化热点。

说明:以上指标名与阈值为通用参考,具体名称可能因版本/部署方式略有差异;建议结合你的监控栈(Prometheus/Grafana)实际看板校准阈值,并按集群规模调整期望值。

9.5 多集群状态调试方法

  • 基本拓扑确认:

    • 明确部署架构(primary-remote、多 primary、跨网络)与各集群的 clusterID、network 名称;
    • 确认东西向网关(eastwest gateway)与远端集群的 API 访问是否通畅。
  • Pilot 控制面视图验证(15014):

    • /debug/networkz:查看跨网络网关与网络拓扑是否识别正确。
      • 端口转发:kubectl -n istio-system port-forward deploy/istiod- 15014:15014
      • 查看:curl -s http://localhost:15014/debug/networkz
    • /debug/clusterz:查看服务注册源(本地/远端)是否被 Pilot 发现。
      • curl -s http://localhost:15014/debug/clusterz
    • /debug/mcsz:查看多集群服务(MCS)的发现与同步状态(如开启)。
      • curl -s http://localhost:15014/debug/mcsz
    • /debug/endpointShardz:按 cluster 维度查看端点分片(远端集群的 endpoints 是否到位)。
      • curl -s http://localhost:15014/debug/endpointShardz
    • /debug/endpointz 与 /debug/instancesz?svc=:核对某服务在不同 cluster 的实例/端点视图。
  • 代理侧视图验证(Envoy admin 15000):

    • 端口转发:kubectl -n port-forward pod/ 15000:15000
    • 导出实际配置:curl -s http://localhost:15000/config_dump > envoy-config.json
    • 核对要点:
      • listeners/clusters/routes/endpoints 的数量与关键条目名称是否与 Pilot 的 /debug/config_dump?proxyID=<pod>.<ns> 一致;
      • EDS 中是否包含来自远端集群的端点(可通过 locality 或标签识别,或在 /debug/endpointShardz 中确认分片来源);
      • gateway/sidecar 的 TLS 与 SNI 配置是否合理,避免跨网络路由失败。
  • 同步与 ACK 状态:

    • /debug/adsz:查看每个连接的订阅类型与资源名,确认跨集群服务已被订阅。
    • /debug/syncz:查看最近一次下发的版本与 ACK/NACK;如出现 NACK,按 9.3 排查。
    • 建议配合 istioctl proxy-status 查看 SYNCED/STALENESS 快速定位。
  • 常见问题快速排查:

    • 远端集群访问授权:
      • 检查 istio-system 命名空间的远端 secret(名称通常包含 remote/clusterId):kubectl -n istio-system get secret | grep -i remote
      • 如需重建远端 secret,请使用 istioctl x create-remote-secret(参考官方文档)。
    • 东西向网关与网络定义:
      • kubectl -n istio-system get svc istio-eastwestgateway
      • /debug/networkz 中是否识别到正确的网关地址与网络映射。
    • 端点聚合:
      • /debug/endpointShardz 是否显示来自远端集群的分片;如缺失,检查远端集群与主控面的连接与 RBAC。
    • 资源可见性:
      • /debug/sidecarz?proxyID=. 验证该工作负载的可见服务集合是否涵盖远端服务;必要时调整 Sidecar CR 的 egress/ingress hosts。
  • 快速操作流程(控制面):

    • 清缓存 → 全量推送:curl -s “http://localhost:15014/debug/cachez?clear=true”;curl -s “http://localhost:15014/debug/adsz?push=true”
    • 断开重连单代理:curl -s “http://localhost:15014/debug/force_disconnect?proxyID=.
    • 观察推送状态:curl -s http://localhost:15014/debug/push_status;curl -s http://localhost:15014/debug/pushcontext

10. 典型时序

典型时序图

flowchart TD
    A[Sidecar 启动] --> B["连接 Pilot ADS (15010/15012)"]
    B --> C[首次订阅资源: LDS/CDS]
    C --> D[Pilot 返回 DiscoveryResponse]
    D --> E{Sidecar 校验}
    E -->|ACK| F[继续订阅 RDS/EDS]
    E -->|NACK| G[记录错误, 等待修复后重试]
    F --> H[进入稳定运行]
    H --> I[服务/配置发生变化]
    I --> J[ConfigUpdate → Debounce → pushQueue]
    J --> K[initPushContext 构建全局上下文]
    K --> L["筛选需要下发的连接(adsClients)"]
    L --> M[按订阅类型生成资源: LDS/RDS/CDS/EDS/...]
    M --> N[命中/回填 XDS 缓存]
    N --> O["下发 DiscoveryResponse (version/nonce)"]
    O --> P{Sidecar ACK/NACK}
    P -->|ACK| Q[推进版本/状态, 持续运行]
    P -->|NACK| R[记录错误, 修复后重推]
flowchart TD
    A[Sidecar 启动] --> B["连接 Pilot ADS (15010/15012)"]
    B --> C[首次订阅资源: LDS/CDS]
    C --> D[Pilot 返回 DiscoveryResponse]
    D --> E{Sidecar 校验}
    E -->|ACK| F[继续订阅 RDS/EDS]
    E -->|NACK| G[记录错误, 等待修复后重试]
    F --> H[进入稳定运行]
    H --> I[服务/配置发生变化]
    I --> J[ConfigUpdate → Debounce → pushQueue]
    J --> K[initPushContext 构建全局上下文]
    K --> L["筛选需要下发的连接(adsClients)"]
    L --> M[按订阅类型生成资源: LDS/RDS/CDS/EDS/...]
    M --> N[命中/回填 XDS 缓存]
    N --> O["下发 DiscoveryResponse (version/nonce)"]
    O --> P{Sidecar ACK/NACK}
    P -->|ACK| Q[推进版本/状态, 持续运行]
    P -->|NACK| R[记录错误, 修复后重推]
flowchart TD
    A[Sidecar 启动] --> B["连接 Pilot ADS (15010/15012)"]
    B --> C[首次订阅资源: LDS/CDS]
    C --> D[Pilot 返回 DiscoveryResponse]
    D --> E{Sidecar 校验}
    E -->|ACK| F[继续订阅 RDS/EDS]
    E -->|NACK| G[记录错误, 等待修复后重试]
    F --> H[进入稳定运行]
    H --> I[服务/配置发生变化]
    I --> J[ConfigUpdate → Debounce → pushQueue]
    J --> K[initPushContext 构建全局上下文]
    K --> L["筛选需要下发的连接(adsClients)"]
    L --> M[按订阅类型生成资源: LDS/RDS/CDS/EDS/...]
    M --> N[命中/回填 XDS 缓存]
    N --> O["下发 DiscoveryResponse (version/nonce)"]
    O --> P{Sidecar ACK/NACK}
    P -->|ACK| Q[推进版本/状态, 持续运行]
    P -->|NACK| R[记录错误, 修复后重推]

11. PushContext 构建逻辑解析

PushContext 的职责是在一次 Push 周期内,将控制面与服务注册表的最新视图整合为“可生成 xDS”的统一上下文,包括索引、策略、可见性、网关与网络分区信息等。

生成时机:在 DiscoveryServer 的 Push 流程中,Full Push 重建上下文;增量则按 Config 更新做选择性重建。

关键入口 InitContext

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// pilot/pkg/model/push_context.go
func (ps *PushContext) InitContext(env *Environment, oldPushContext *PushContext, pushReq *PushRequest) error {
    ps.initializeMutex.Lock()
    defer ps.initializeMutex.Unlock()
    if ps.InitDone.Load() {
        return nil
    }

    ps.Mesh = env.Mesh()
    ps.LedgerVersion = env.Version()
    ps.initDefaultExportMaps()

    // create new or incremental update
    if pushReq == nil || oldPushContext == nil || !oldPushContext.InitDone.Load() || len(pushReq.ConfigsUpdated) == 0 {
        if err := ps.createNewContext(env); err != nil { return err }
    } else {
        if err := ps.updateContext(env, oldPushContext, pushReq); err != nil { return err }
    }

    ps.networkMgr = env.NetworkManager
    ps.clusterLocalHosts = env.ClusterLocal().GetClusterLocalHosts()
    ps.InitDone.Store(true)
    return nil
}

全量重建 createNewContext 的阶段顺序:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func (ps *PushContext) createNewContext(env *Environment) error {
    if err := ps.initServiceRegistry(env); err != nil { return err }
    if err := ps.initKubernetesGateways(env); err != nil { return err }
    if err := ps.initVirtualServices(env); err != nil { return err }
    if err := ps.initDestinationRules(env); err != nil { return err }
    if err := ps.initAuthnPolicies(env); err != nil { return err }
    if err := ps.initAuthorizationPolicies(env); err != nil { return err }
    if err := ps.initTelemetry(env); err != nil { return err }
    if err := ps.initProxyConfigs(env); err != nil { return err }
    if err := ps.initWasmPlugins(env); err != nil { return err }
    if err := ps.initEnvoyFilters(env); err != nil { return err }
    if err := ps.initGateways(env); err != nil { return err }
    // Must be initialized in the end
    if err := ps.initSidecarScopes(env); err != nil { return err }
    return nil
}

增量选择性重建 updateContext(按变更点触发):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
func (ps *PushContext) updateContext(env *Environment, oldPushContext *PushContext, pushReq *PushRequest) error {
    var servicesChanged, virtualServicesChanged, destinationRulesChanged, gatewayChanged,
        authnChanged, authzChanged, envoyFiltersChanged, sidecarsChanged, telemetryChanged, gatewayAPIChanged,
        wasmPluginsChanged, proxyConfigsChanged bool

    for conf := range pushReq.ConfigsUpdated {
        switch conf.Kind {
        case gvk.ServiceEntry:
            servicesChanged = true
        case gvk.DestinationRule:
            destinationRulesChanged = true
        case gvk.VirtualService:
            virtualServicesChanged = true
        case gvk.Gateway:
            gatewayChanged = true
        case gvk.Sidecar:
            sidecarsChanged = true
        case gvk.WasmPlugin:
            wasmPluginsChanged = true
        case gvk.EnvoyFilter:
            envoyFiltersChanged = true
        case gvk.AuthorizationPolicy:
            authzChanged = true
        case gvk.RequestAuthentication, gvk.PeerAuthentication:
            authnChanged = true
        case gvk.HTTPRoute, gvk.TCPRoute, gvk.GatewayClass, gvk.KubernetesGateway, gvk.TLSRoute, gvk.ReferencePolicy:
            gatewayAPIChanged = true
            virtualServicesChanged = true
            gatewayChanged = true
        case gvk.Telemetry:
            telemetryChanged = true
        case gvk.ProxyConfig:
            proxyConfigsChanged = true
        }
    }
    // 按变更点选择性重建各子视图(服务、VS、DR、Authn/Authz、Telemetry、EnvoyFilter、Sidecar、K8s Gateway 等)
    // ...(省略后续赋值与回收逻辑)
    return nil
}

11.1 服务与端点索引(ServiceIndex/ServiceInstances)

  • 来源:initServiceRegistry 遍历服务,建立 Hostname+Namespace 查找表,并为每个端口预缓存实例集合;
  • 作用:为后续 CDS/EDS/RDS/LDS 生成提供基础数据(例如 EDS 的端点来源、CDS 的服务维度聚合)。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func (ps *PushContext) initServiceRegistry(env *Environment) error {
    services, err := env.Services(); if err != nil { return err }
    allServices := SortServicesByCreationTime(services)
    for _, s := range allServices {
        svcKey := s.Key()
        // Precache instances
        for _, port := range s.Ports {
            if _, ok := ps.ServiceIndex.instancesByPort[svcKey]; !ok {
                ps.ServiceIndex.instancesByPort[svcKey] = make(map[int][]*ServiceInstance)
            }
            // ...填充每个端口的实例列表(省略细节)
        }
        // ...维护 HostnameAndNamespace、public/private/exportedTo 等视图
    }
    // ...同步 ServiceAccounts 与 Inbound/Outbound 可见性
    return nil
}

11.2 路由视图(VirtualServiceIndex)

  • 来源:initVirtualServices 收集并索引 VS,按网关、命名空间与 ExportTo 分组;支持委托(delegates)与多网关派生;
  • 作用:为 RDS 的 routeConfiguration 生成提供匹配条件、目标权重、重试/故障注入等策略输入。

提示:push_context.go 中包含 getGatewayNamesDelegateVirtualServicesConfigKey 等辅助函数用于 VS 的派生与关联。

11.3 集群视图(DestinationRuleIndex + Service)

  • 来源:initDestinationRules 构建 processedDestRules(hosts/exports/destRule),并合并命名空间继承与 Mesh Root 的默认策略;支持子集(subset)与流量策略(TrafficPolicy)。
  • 作用:为 CDS 的 cluster 生成与路由子集选择提供依据;并影响 EDS 的 locality、负载均衡、熔断等配置。
1
2
3
4
5
6
7
8
type processedDestRules struct {
    hosts []host.Name
    hostsMap map[host.Name]struct{}
    exportTo map[host.Name]map[visibility.Instance]bool
    destRule map[host.Name]*config.Config
}

func (ps *PushContext) SetDestinationRules(configs []config.Config) { /* 合并并索引 */ }

11.4 过滤器链与可插拔扩展(EnvoyFilter/Wasm/Authn/Authz/Telemetry/ProxyConfig)

  • EnvoyFilter:initEnvoyFilters 读取并按命名空间索引 EnvoyFilterWrapper,生成时对 LDS/RDS/CDS/EDS 做 Patch 与 Match;
  • WasmPlugin:initWasmPlugins 构建各命名空间的插件清单,按 Phase(inbound/outbound、listener/http)分配;
  • 认证鉴权:initAuthnPolicies/initAuthorizationPolicies 为 FilterChain 注入 mTLS、JWT、RBAC 等策略输入;
  • Telemetry/ProxyConfig:影响统计、访问日志与代理行为的默认参数,生成时结合 Sidecar/Workload 特性选择性应用。
1
2
3
4
func (ps *PushContext) initEnvoyFilters(env *Environment) error { /* 加载与索引 */ }
func (ps *PushContext) WasmPlugins(proxy *Proxy) map[extensions.PluginPhase][]*WasmPluginWrapper { /* 选择插件 */ }
func (ps *PushContext) initAuthnPolicies(env *Environment) error { /* JWT/PeerAuth */ }
func (ps *PushContext) initAuthorizationPolicies(env *Environment) error { /* RBAC */ }

11.5 Sidecar 作用域与可见性(SidecarIndex)

  • 来源:initSidecarScopes 在所有子视图完成后执行,计算每命名空间的 SidecarScope,包括默认作用域与 Gateway 场景特例;
  • 作用:限制工作负载可见的服务集合与入/出站 Listener/Route 可见性,直接影响 LDS/RDS 的生成范围与规模。
1
func (ps *PushContext) initSidecarScopes(env *Environment) error { /* 计算默认与命名空间作用域 */ }

11.6 网关与 Gateway API 视图

  • KubernetesGateway/GatewayClass/HTTPRoute/TLSRoute 等资源变更被合并到 VS/Gateway 派生,initKubernetesGatewaysinitGateways 维护对应索引与状态;
  • 生成时,GatewayContext.MergeGateways/ResolveGatewayInstances 用于聚合跨服务的网关实例与端口,最终驱动 LDS/RDS 构建。
1
2
func (ps *PushContext) initKubernetesGateways(env *Environment) error { /* 解析 K8s Gateway */ }
func (ps *PushContext) initGateways(env *Environment) error { /* 解析 Istio Gateway */ }

12. xDS 生成器拆解(CDS/LDS/RDS/EDS)

12.1 CDS(Cluster 生成)实现与关键点

  • 入口与接口定义:

    • 接口声明:pilot/pkg/networking/core/configgen.go
      1
      
      BuildClusters(node *model.Proxy, req *model.PushRequest) ([]*discovery.Resource, model.XdsLogDetails)
    • 入口实现:pilot/pkg/networking/core/v1alpha3/cluster.go
      1
      2
      3
      4
      
      func (configgen *ConfigGeneratorImpl) BuildClusters(proxy *model.Proxy, req *model.PushRequest) ([]*discovery.Resource, model.XdsLogDetails) {
          services := req.Push.Services(proxy)
          return configgen.buildClusters(proxy, req, services)
      }
  • 出站/入站/特殊场景:

    • 出站:buildOutboundClusters 解析 Sidecar 作用域、ServiceEntry、VirtualService 导向的路由目标,并拼装 TLS(mTLS/Passthrough)、LB 策略、熔断等;
    • 入站:buildInboundClusters 为每个入站端口/UDS 构造本地 cluster;
    • SNI+DNAT:buildOutboundSniDnatClusters 用于网关或跨网络场景,按 SNI 名称拆分 cluster 并应用对等 TLS 与网络过滤。
  • 调用链概览(CDS):

    • 入口:ConfigGeneratorImpl.BuildClustersbuildClusters
    • 构建器:NewClusterBuilder 初始化上下文(req、push、locality、labels 等);
    • 出站路径:遍历服务与端口 → 计算发现类型(EDS/STRICT_DNS/LOGICAL_DNS/ORIGINAL_DST) → 生成基础 Cluster → 应用 DestinationRule 与 TrafficPolicy(连接池、负载、熔断、TLS 等) → 子集(subset)派生;
    • 入站路径:按实例/端口构造本地 Cluster;
    • SNI+DNAT:生成 SNI-DNAT 模式的 Cluster;
    • 最终:通过 EnvoyFilter 的 ClusterPatcher 做增删改补丁后输出。

12.2 LDS(Listener 生成)实现与过滤器装配

  • 入口与接口定义:

    • 接口声明:pilot/pkg/networking/core/configgen.go
      1
      
      BuildListeners(node *model.Proxy, push *model.PushContext) []*listener.Listener
    • 入口实现:pilot/pkg/networking/core/v1alpha3/listener.go
      1
      2
      3
      
      func (configgen *ConfigGeneratorImpl) BuildListeners(node *model.Proxy, push *model.PushContext) []*listener.Listener {
          return configgen.buildSidecarListeners(builder).Listeners
      }
  • 侧车 Listener 主流程:

    • 入站:逐端口/UDS 生成 inbound listener 与 filter chains;
    • 出站:生成虚拟出站监听(如 0.0.0.0:15006)与具体目标端口监听,挂载路由过滤器。
  • 关键过滤器拼装:

    • HTTP:buildHTTPConnectionManager 构造 HCM 并按序追加 http_filters:HTTPMx → GrpcWeb → GrpcStats → Alpn → Fault → Cors → Telemetry → Router;
    • TCP:setAccessLogAndBuildTCPFilter 构建 TCP Proxy 并按协议装配 Mongo/Redis/MySQL 等专用网络过滤器;
    • Listener 层:TLSInspector/HTTPInspector/OriginalSource/OriginalDestination 根据场景条件性插入。

12.3 RDS(Route 生成)实现与路由规则拼装

  • 入口与接口定义:

    • 接口声明:pilot/pkg/networking/core/configgen.go
      1
      
      BuildHTTPRoutes(node *model.Proxy, req *model.PushRequest, routeNames []string) ([]*discovery.Resource, model.XdsLogDetails)
    • 入口实现:pilot/pkg/networking/core/v1alpha3/httproute.go
      1
      
      func (configgen *ConfigGeneratorImpl) BuildHTTPRoutes(node *model.Proxy, req *model.PushRequest, routeNames []string) ([]*discovery.Resource, model.XdsLogDetails)
  • 关键点:

    • VirtualService 中的 HTTP/TCP 路由匹配(主机名、前缀、Header/Query、Method);
    • 目标聚合与 Subset(基于 DestinationRule);
    • 重试、超时、熔断、Fault Injection、Mirror、WASM/ext_proc 扩展;
    • SidecarScope 的 egress 限定与 Gateway 的 server 绑定;
    • gRPC 路由最小化生成(按 routeNames 子集)。

12.4 EDS(Endpoint 生成)实现与过滤策略

  • 入口与生成逻辑:pilot/pkg/xds/eds.go

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    func (eds *EdsGenerator) buildEndpoints(proxy *model.Proxy, push *model.PushContext, req *model.PushRequest, w *model.WatchedResource) {
        // 读取缓存:Server.Cache.Get(builder)
        // 无缓存则调用 Server.generateEndpoints(builder) 生成 CLA
        // 结果写入缓存:Server.Cache.Add(builder, req, resource)
    }
    
    func (s *DiscoveryServer) generateEndpoints(b EndpointBuilder) *endpoint.ClusterLoadAssignment {
        llbOpts := s.llbEndpointAndOptionsForCluster(b)
        llbOpts = b.EndpointsByNetworkFilter(llbOpts)
        llbOpts = b.EndpointsWithMTLSFilter(llbOpts)
        // 应用 locality LB,封装为 CLA 返回
    }
  • 服务分片与增量更新:

    1
    2
    3
    
    func (s *DiscoveryServer) UpdateServiceShards(push *model.PushContext) error { /* 更新 EndpointShardsByService */ }
    func (s *DiscoveryServer) edsCacheUpdate(shard model.ShardKey, hostname, namespace string, istioEndpoints []*model.IstioEndpoint) bool { /* 分片缓存更新/删除 */ }
    func (s *DiscoveryServer) llbEndpointAndOptionsForCluster(b EndpointBuilder) ([]*LocLbEndpointsAndOptions, error) { /* 从 shards 拼 locality 列表 */ }
  • 端点构建器与过滤器:pilot/pkg/xds/endpoint_builder.go

    1
    2
    3
    4
    5
    6
    7
    8
    
    type LocLbEndpointsAndOptions struct {
        istioEndpoints []*model.IstioEndpoint
        llbEndpoints   endpoint.LocalityLbEndpoints
    }
    
    func (e *LocLbEndpointsAndOptions) refreshWeight() { /* 依据 lbEndpoints 数量刷新权重 */ }
    
    // 关键过滤:跨网络视图过滤、mTLS 能力筛选、从分片构造 locality

13. 扩展与过滤器装配注意事项(WASM/ext_proc/RBAC/CORS/Fault 等)

  • HTTP 过滤器:主要挂载在 HCM 的 http_filters 列表。参考 createGatewayHTTPFilterChainOpts(gateway.go)与 buildInboundFilterchains(listener_builder.go)。
  • TCP/网络过滤器:TCP Proxy、Mongo、Redis 等协议专用过滤器在 network_filters 列表;兜底出站链路见 buildOutboundCatchAllNetworkFilterChains
  • WASM 插件:
    • 注入函数:pilot/pkg/networking/core/v1alpha3/extension/wasmplugin.goAddWasmPluginsToMutableObjects
    • 注入算法基于内置过滤器的相对顺序定位:在 JWT/AuthN/RBAC/Stats 等内置过滤器前按 Phase 插入;其余未知过滤器保持原顺序,尾部补齐未插入的扩展;
    • 插件选择来源:PushContext.WasmPlugins(proxy) 按命名空间与 workloadSelector 选择并按 Priority 预排序。
  • Telemetry(Stats/Metadata Exchange):
    • istio.stats 作为 Wasm HTTP 过滤器由 Telemetry/插件管线插入,名称为 xdsfilters.StatsFilterName
    • Metadata Exchange(MX)HTTP 与 TCP 过滤器分别为 xdsfilters.HTTPMxbuildMetadataExchangeNetworkFilters,在开启 features.MetadataExchange 时注入;
    • gRPC 统计:xdsfilters.GrpcStats(envoy.extensions.filters.http.grpc_stats.v3)。
  • CORS 与 Fault:
    • 静态过滤器定义:pilot/pkg/xds/filters/filters.go 中的 xdsfilters.Corsxdsfilters.Fault
    • 配置转换:
      • CORS:translateCORSPolicy(route.go)将 Istio CorsPolicy 转为 Envoy route.CorsPolicy;
      • Fault:translateFault(route.go、virtualservice.go)将 Istio HTTPFaultInjection 转为 Envoy HTTPFault。
  • RBAC 与外部鉴权(ext_authz):
    • RBAC 过滤器由 Authorization 插件在 Listener 构建阶段插入(authorization.go 等);
    • 外部鉴权由 extauthz.go 处理,在启用时插入到 HCM 的 http_filters 中。
  • RateLimit 与 ext_proc:
    • Pilot 默认不主动拼装 HTTP RateLimit 过滤器,可通过外部 Envoy Rate Limit Service 集成(参考 samples/ratelimit);
    • ext_proc 在类型映射(pkg/config/xds/filter_types.gen.go)中可见,但默认 HTTP 过滤器链不包含,需通过 EnvoyFilter 或 WasmPlugin 显式注入。

14. 参考源码路径总览

  • pilot/cmd/pilot-discovery/app/cmd.go:命令与 ServerArgs/Flags;
  • pilot/pkg/bootstrap/options.go:DiscoveryServerOptions、PilotArgs、TLS 与环境变量;
  • pilot/pkg/xds/discovery.go:DiscoveryServer 初始化、去抖/队列、Push/ConfigUpdate、缓存与生成器注册;
  • pilot/pkg/xds/*.go:各 TypeURL 的生成器与处理逻辑(LDS/RDS/CDS/EDS/ECDS/NDS);
  • pilot/pkg/model/push_context.go:PushContext 构建与增量更新;
  • pilot/pkg/networking/core/v1alpha3/*.go:Listener/Route/Cluster 构建与过滤器装配;
  • pilot/pkg/xds/filters/filters.go:常用过滤器静态定义;
  • serviceregistry/kube/...:Kubernetes 源与端点构建逻辑;
  • pilot/pkg/xds/debug.go:调试与状态接口。
0%