K8s 资源监听与 Controller
Higress 控制面本质是一组 K8s Controller。本期把所有 controller 的统一范式与各自差异讲透。
Informer 三件套
Informer = SharedIndexInformer + Lister + EventHandler,K8s 的"List-Watch + 本地缓存"标准范式。Higress 所有 controller 都是这套范式的实例化。
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) { queue.Add(key(obj)) },
UpdateFunc: func(old, new interface{}) { queue.Add(key(new)) },
DeleteFunc: func(obj interface{}) { queue.Add(key(obj)) },
})pkg/kube/client.go
Higress 在 Istio 的 istiokube.Client 之上再包了一层 higresskube.Client,把自定义 CRD 客户端塞进来,对外暴露统一的 multi-typed client。所有 controller 都接收同一个 client 实例。
client/ codegen 产物
client/ 目录由 k8s.io/code-generator 自动生成 typed clientset / lister / informer。Higress 写 CRD types.go + 跑 make gen,剩下都是生成代码。不需要读这些文件,只要会调用即可:
cs, _ := versioned.NewForConfig(cfg)
list, _ := cs.NetworkingV1().McpBridges("ns").List(ctx, ...)make gen 会怎样?common.IngressController 接口
pkg/ingress/kube/common/controller.go 定义了 Higress 自己的 controller 抽象:
type IngressController interface {
Run(stop <-chan struct{})
HasSynced() bool
ListAll() []common.WrapperConfig
GetIngress(ns, name string) *networkingv1.Ingress
AddEventHandler(handler IngressHandler)
...
}
这是 IngressConfig 与各版本 controller 解耦的关键。
ingressv1 控制器
位于 pkg/ingress/kube/ingressv1/。监听 networking.k8s.io/v1 Ingress 资源(K8s 1.19+ 主流形态)。它过滤 spec.ingressClassName 是否匹配 Higress 的 ingress class。
higress,可通过 ConfigMap 配置。ingress (v1beta1)
pkg/ingress/kube/ingress/ 是 Old API 兼容。extensions/v1beta1.Ingress 在 K8s 1.22 已删除,但很多老集群仍在跑。Higress 保留这条线,让升级路径平滑。
kingress Knative
pkg/ingress/kube/kingress/ 监听 Knative 的 networking.internal.knative.dev/v1alpha1.Ingress。这让 Higress 可以替换 Knative 默认的 Kourier/Istio 网关。
gateway (Gateway API)
pkg/ingress/kube/gateway/ 处理 gateway.networking.k8s.io 下的 Gateway / HTTPRoute / TCPRoute / TLSRoute。这是未来主流路径,Ingress 注解的"标准化继任者"。
McpBridgeController
pkg/ingress/kube/mcpbridge/controller.go 只有 49 行——它就是个薄壳:监听 McpBridge CRD,把事件回调给 IngressConfig 的 AddOrUpdateMcpBridge / DeleteMcpBridge。真正的"协调多注册中心"逻辑在 registry/reconcile。
WasmPluginController
pkg/ingress/kube/wasmplugin/controller.go 同样很薄:监听 Higress 自定义的 extensions.higress.io/v1alpha1.WasmPlugin,把事件回给 IngressConfig 的 AddOrUpdateWasmPlugin。最终由 IngressConfig 把它合并到 Istio extensions.WasmPlugin 与 EnvoyFilter。
Http2RpcController
Http2Rpc 是 Higress 的"HTTP→Dubbo 转换"CRD,配合 http2rpc 注解和 EnvoyFilter 可以让前端 HTTP 直接调 Dubbo 接口。Controller 同样薄壳,关键转换在 IngressConfig 的 constructHttp2RpcEnvoyFilter。
McpServerController
负责监听 McpServer CRD —— 描述外部 MCP Server 的接入信息。事件转发到 IngressConfig 与 pkg/ingress/mcp(注意:这里 "mcp" 是 Mesh Config Protocol,不是 Model Context Protocol,名字撞车)。
Secret Controller
pkg/ingress/config/secret_config_mgr.go 实现 Secret 监听:TLS 证书变了要触发对应 Gateway/Listener 的 push。Higress 还监听特殊 Secret(例如 ai-proxy 用的 API key Secret)。
ConfigMap 全局配置
pkg/ingress/kube/configmap/ 监听全局 ConfigMap(默认 higress-config),里面塞 gzip / tracing / global mcpServer 等设置。Controller 把变化广播给依赖它的子模块。
workqueue 与重试
所有 controller 都用 workqueue.NewRateLimitingQueue:失败 requeue 时按指数退避。这是 K8s controller 写法的事实标准,Higress 没有偏离。
if err := c.reconcile(key); err != nil {
c.queue.AddRateLimited(key); return
}
c.queue.Forget(key)EventHandler 注册
IngressConfig 提供 RegisterEventHandler(kind, fn):让 Pilot 注册回调,当 controller 检测变更时 Higress 调 fn 通知 Pilot 重推。这是控制面与 controller 的"反向调用"通道。
AggregateController
Higress 支持多集群:每个集群一个 IngressController 实例,外层用 common.AggregateController 聚合,对 IngressConfig 暴露统一接口。多集群下 WrapperConfig 里会带 clusterId 区分。
多集群 clusterId
clusterId 是 Istio MultiCluster 抽象的关键。Higress 沿用此设计:每个 client 携带 clusterId,Service / Endpoint / Config 命名时都带 clusterId 前缀避免冲突。
Kubernetes 或环境变量指定。资源版本与 ResyncPeriod
Higress informer 配置 ResyncPeriod=0(不周期 resync),完全靠事件驱动。这避免 large cluster 下的 list-watch 风暴。一旦丢事件会通过 K8s watch reconnect 自动追回。
写一个最小 controller
以 McpBridge 为模板,新增一个 controller 的最小步骤:
- 在
api/networking/v1/定义 CRD types。 make gen生成 client/lister/informer。- 新建
pkg/ingress/kube/myfeat/controller.go,模仿 mcpbridge controller。 - 在 IngressConfig 的 NewIngressConfig 里启动它,并注册回调。
- 在 List 或 convert* 里把数据消费成 Istio 配置。
ingress_config.go。