IngressConfig 翻译核心
深入 pkg/ingress/config/ingress_config.go(2085 行)——Higress 控制面最复杂的文件。读完这期你能解释一条 Ingress 是怎么变成 VirtualService + DR + EnvoyFilter 的。
文件定位与全景
pkg/ingress/config/ingress_config.go,2085 行。它的角色是实现 Istio model.ConfigStoreController 接口,把 Pilot 想要的 VirtualService / DR / EnvoyFilter 等资源动态合成出来。
grep '^func ' pkg/ingress/config/ingress_config.go | head -40
# 30+ 个方法,主要分四组:构造、ConfigStore 接口、convert*、apply*IngressConfig 字段速读
type IngressConfig struct {
remoteIngressControllers map[string]common.IngressController
mcpbridgeController mcpbridge.McpBridgeController
wasmPluginController wasmplugin.WasmPluginController
http2rpcController http2rpc.Http2RpcController
annotationHandler annotations.AnnotationHandler
eventHandlers map[config.GroupVersionKind]istiomodel.EventHandler
cachedConfig map[config.GroupVersionKind][]config.Config
...
}
字段两类:① 各 controller 引用(拿原始数据),② 缓存与回调(喂给 Pilot)。
NewIngressConfig 构造
第 187 行的 NewIngressConfig 是入口:
- 创建主集群的 IngressController(v1 / v1beta1 / gateway / kingress);
- 初始化 McpBridge / WasmPlugin / Http2Rpc Controller;
- 构造 AnnotationHandler;
- 把所有 controller 注册回调,事件经 normalize 后调用
refreshAndPushXds。
实现 ConfigStore 伪装
Pilot 看不到 IngressConfig 是合成的,因为它实现了 model.ConfigStoreController:
func (m *IngressConfig) Schemas() collection.Schemas { return m.schemas }
func (m *IngressConfig) Get(gvk, name, ns) *config.Config { ... }
func (m *IngressConfig) List(gvk, ns) []config.Config { ... }
func (m *IngressConfig) Run(stop <-chan struct{}) { ... }
func (m *IngressConfig) HasSynced() bool { ... }
对 Pilot 而言它就是一个普通 store,只是不允许 Create/Update/Delete。
RegisterEventHandler
238 行的 RegisterEventHandler 把 Pilot 注册的回调存到 eventHandlers。当内部 informer 触发变更,IngressConfig 调对应回调通知 Pilot:
if h, ok := m.eventHandlers[gvk.VirtualService]; ok {
h(prev, curr, model.EventUpdate)
}List 主分发(286 行)
func (m *IngressConfig) List(typ config.GroupVersionKind, ns string) []config.Config {
switch typ {
case gvk.VirtualService: return m.virtualServices(ns)
case gvk.DestinationRule: return m.destinationRules(ns)
case gvk.Gateway: return m.gateways(ns)
case gvk.ServiceEntry: return m.serviceEntries(ns)
case gvk.EnvoyFilter: return m.envoyFilters(ns)
case gvk.WasmPlugin: return m.wasmPlugins(ns)
}
return nil
}
这是整个文件的中央枢纽——按资源类型分发到对应 convert* 函数。
listFromIngressControllers
322 行。聚合多集群 IngressController 的原始 Ingress,过滤掉错误的、不属于 Higress 的,按 namespace 切分返回。这是 convert 系列的"数据来源"统一入口。
createWrapperConfigs
385 行。把 Ingress 列表逐条调用 annotationHandler.Parse,得到带注解解析结果的 WrapperConfig。这是"原始 K8s 对象 → 内部 IR"的转换点,下游所有 convert* 操作的是 WrapperConfig 不再是原生 Ingress。
convertGateways
431 行。每条 Ingress 的 spec.tls + 默认 80/443 监听被合并为 Istio Gateway 资源,按 host 分组。这是 LDS 生成的源头:Gateway 字段直接影响 listener。
convertVirtualService(483 行)
整个文件的明星方法。约 150 行:
- 把每条 rule + path 转 HTTPRoute;
- 调用
annotationHandler.ApplyRoute把注解填入 HTTPRoute; - 处理 canary(applyCanaryIngresses);
- 处理 AppRoot / InternalActiveRedirect;
- 同 host 多 VS 合并去重。
RDS 的 99% 路由细节都来自这里。
convertDestinationRule(773 行)
DR 生成关注点:
- 从注解读 lb / timeout / retry / mirror。
- 处理 upstreamtls(mTLS、SNI)。
- 处理 subset(灰度版本切流)。
DR 决定 CDS 与 cluster.transport_socket 的细节。
convertServiceEntry(738 行)
当 backend 指向集群外(如 nacos://my-svc)时,要写一份 ServiceEntry 让 Pilot 知道这个外部服务。registry 拉来的实例最终也会以 ServiceEntry 形式注入。
convertEnvoyFilter(628 行)
这是 Higress 的"逃生通道":注解里 Higress 还没原生支持的能力,全靠合成 EnvoyFilter patch listener / route / cluster 的 typed_config。比如 BasicAuth、Http2Rpc、Header 透传等。
convertWasmPlugin(714 行)
把 Higress WasmPlugin CRD 转成 Istio extensions.WasmPlugin。两者 group 不同但内容兼容:Higress 增加了 matchRules(按 host/path 覆盖配置)、imagePullPolicy 等字段,convertIstioWasmPlugin 负责降级处理。
applyCanaryIngresses(1432 行)
K8s 社区的 Ingress canary 语义(同 host 多 Ingress + canary 注解)在这里实现。流程:
- 找到 canary 候选 Ingress;
- 按 weight / header / cookie 匹配规则合并到主 Ingress 的 HTTPRoute;
- normalizeWeightedCluster 归一化权重。
applyAppRoot / Redirect
位于 912 / 940 行:
- applyAppRoot:注解
app-root指定子路径时,把 / 重定向到 /sub。 - applyInternalActiveRedirect:Higress 扩展的"网关内部重定向",比 302 更高效。
Http2Rpc 合成(1452 行)
constructHttp2RpcEnvoyFilter:把 Http2Rpc CRD 翻译成 EnvoyFilter,注入 Dubbo 协议转换器。constructHttp2RpcMethods 生成方法白名单的 google.protobuf.Struct。
BasicAuth EnvoyFilter(1648 行)
constructBasicAuthEnvoyFilter 把 basic-auth 注解里的用户名密码渲染成 envoy.filters.http.basic_auth typed_config。注意密码不能写明文,需要 Secret 引用 + base64。
ProxyEnvoyFilters(1731 行)
constructProxyEnvoyFilters 处理"全局 proxy 设置":每个上游服务可能有自己的 connection pool / outlier detection / tracing 覆写。Higress 把这些合成成一组 EnvoyFilter 一次性推下去。
缓存与 HasSynced(1877+ 行)
Run/HasSynced/GetIngressRoutes/GetIngressDomains 等方法是给 Pilot 与控制面其它组件用的辅助 API。HasSynced 返回所有底层 controller 都 HasSynced 的 AND 结果——只有都准备好了 Pilot 才开始 push。