Istio Pilot 复用与 xDS
看清 Higress 与 Istio 的接缝。20 讲覆盖 ConfigStore / ServiceRegistry / PushContext / DiscoveryServer 与 LDS/RDS/CDS/EDS/SDS 的关键代码路径。
Pilot 是什么
Pilot 是 Istio 控制面里负责"生成并下发 Envoy 配置"的组件。其核心抽象:
- ConfigStore:拿到 VirtualService、DestinationRule、Gateway 等 CRD。
- ServiceRegistry:拿到 Service 与 Endpoint。
- PushContext:把以上两者快照成"可推送的视图"。
- DiscoveryServer:ADS gRPC 服务端,对每个 Envoy 连接维护 stream。
vendored Istio 目录
仓库根目录 istio/istio、istio/api、istio/client-go、istio/proxy 分别对应 Istio 的几个仓库。Higress 通过 go.mod replace 把 import 重定向到这里。这意味着:
- 升级 Istio 版本 = git 替换
istio/内容。 - 所有 patch 都"hot",无需 fork。
- Higress 可以保留 Istio 老 API 兼容性。
ConfigStore 模型
type ConfigStore interface {
Schemas() collection.Schemas
Get(typ config.GroupVersionKind, name, ns string) *config.Config
List(typ config.GroupVersionKind, ns string) []config.Config
Create/Update/Delete(config.Config) (string, error)
}
这是 Pilot 的"配置数据库"接口。Higress 不仅有真实 K8s CRD store,还有动态合成的 IngressConfig——后者也实现这个接口,让 Pilot 误以为有真实 VirtualService。
ServiceRegistry 模型
type ServiceDiscovery interface {
Services() []*model.Service
InstancesByPort(svc *model.Service, port int) []*model.ServiceInstance
GetProxyServiceTargets(node *model.Proxy) []model.ServiceTarget
NetworkGateways() []model.NetworkGateway
MCSServices() []model.MCSServiceInfo
}
Pilot 用这个接口拿 endpoint。Higress 通过 registry/memory.ServiceRegistry 把 Nacos/ZK/Consul 来的实例统一注入。
PushContext
PushContext 是"一次推送的不可变快照":从 ConfigStore + ServiceRegistry 拉取当前所有数据,构建好按命名空间/服务的索引,方便 generator 高效查询。每次配置变更后会重建 PushContext,老的快照仍可被进行中的推送使用。
Environment 容器
type Environment struct {
ConfigStore
ServiceDiscovery
Mesh *meshconfig.MeshConfig
PushContext *PushContext
...
}
这是 Higress 跟 Pilot 沟通的"核心对象",bootstrap.NewServer 一旦填好它,剩下全是 Istio 的事。
DiscoveryServer 入口
xdsServer := xds.NewDiscoveryServer(env, plugins, ...)
xdsServer.Register(grpcServer)
DiscoveryServer 内含:
pushChannel:推送任务队列clients:当前连接的 Envoy 列表(按 ADS)generators:按 TypeURL 分发的资源生成器
ADS gRPC stream
每个 Envoy 启动后通过 StreamAggregatedResources 建立一条双向流,发 DiscoveryRequest,接 DiscoveryResponse。Pilot 在 ads.go 维护 stream state:已 ack 的 nonce、订阅的资源列表。
推送队列与 debounce
多个事件短时间内到达时,Pilot 用 debounce 合并:DebounceAfter 默认 100ms,最长 DebounceMax 10s。Higress 通过 XdsOptions.DebounceAfter/Max 透传修改。
合并后形成一次 PushContext 重建 + 多 client 并行推送。
LDS 生成
LDS 把 Gateway / Sidecar 的 listener 渲染成 Envoy Listener。Higress 主要使用 Istio 的 configgen.BuildListeners。Wasm 插件通过 EnvoyFilter 嵌入到 listener 的 HTTP Filter Chain。
RDS 生成
RDS 由 VirtualService 决定。Higress 大量工作就是合成 VirtualService,因此 RDS 是受 Ingress 改动影响最大的资源类型。Pilot 会按 listener route_config_name 分包 RDS 单独推送。
CDS 生成
CDS = Cluster,每个上游服务一份。来源:K8s Service、ServiceEntry、DestinationRule 的 subset。Higress 通过翻译 Ingress + McpBridge 间接控制 CDS。
EDS 生成与增量
EDS 推送 ClusterLoadAssignment(每个 cluster 的 endpoint 列表)。这是最高频的资源类型——Pod IP 一动就 push。Istio 支持增量 xDS(delta),Higress 通过 XdsOptions.EnableEDSDebounce 控制是否对 EDS 也加 debounce。
SDS 与证书
SDS 推送 TLS 证书与私钥。Higress 用 pkg/cert 自动签发证书后存入 Secret,Pilot 通过 Secret → SDS 推到 Envoy。Envoy 不落盘私钥,所有都在内存。
Aggregate 聚合器
configaggregate、aggregate 分别聚合 ConfigStore 与 ServiceRegistry。聚合器对外暴露统一接口,对内按 cluster / source 分发查询。Higress 多集群 / 多注册中心都靠它。
krt 新式 Informer
istio.io/istio/pkg/kube/krt 是 Istio 1.20+ 推出的声明式 collection:用 krt.NewCollection 把多个底层 informer 组合成可派生的视图,类似 RX。Higress 部分 controller 已迁移到 krt,其它仍是老式 Informer + workqueue。
Higress 注入点
Higress 与 Istio 的接缝可总结成 3 处:
- configaggregate 加入 IngressConfig 作为 ConfigStore。
- aggregate.Controller 加入 memory.ServiceRegistry 作为 ServiceDiscovery。
- EnvoyFilter 由 IngressConfig 合成,用来塞 Wasm / Lua / 自定义 filter。
推送一次的全流程
Ingress YAML changed
→ Informer event
→ IngressConfig 缓存重算 + EventHandler 通知
→ DiscoveryServer.ConfigUpdate(PushRequest)
→ debounce 合并
→ PushContext.InitContext (重建快照)
→ 对每个连接的 Envoy
└─ proxy.SidecarScope 更新
└─ generators 按 TypeURL 生成资源
└─ 发送 DiscoveryResponse
→ Envoy ACK / NACK调试 syncz / configz
常用端点:
:15014/debug/syncz:每个 Envoy 当前 ACK 状态。:15014/debug/configz:当前 ConfigStore 内容。:15014/debug/registryz:服务发现内容。:15014/debug/endpointShardz:EDS 切片视图。
与上游 Istio 差异
Higress 主要 patch 点:
- 禁用 sidecar injector / Citadel CA。
- 增强 Gateway label 选择器(GatewaySelectorKey/Value)。
- 支持 KeepConfigLabels / KeepConfigAnnotations 这种透传开关。
- 嵌入了对 Higress 自定义 CRD 的 schema。
这些都可以在 istio/istio 子目录里 diff 上游来确认。