Day 02 / 共 20 天 · 第 1 周 全景与控制器
启动流程
Higress Controller 怎么 boot?今天追启动链:cmd/higress/main.go → serve → bootstrap.NewServer → initFuncList。看它怎么把 istiod(复用)和自己的 Core 装配起来。昨天(Day 01)看的是"翻译 → 下发 → 执行"的全景,今天钻进"翻译官(Higress Core)"开机时怎么把各个部件装配好,为 Day 03 拆它的心脏 IngressConfig 铺路。
📍 你在 Higress 源码课的位置(第1周 全景与控制器 · 第2周 服务发现与配置)
D01 全景→
D02 启动→
D03 Ingress控制器→
D04 配置翻译→
D05 xDS-over-MCP→
D06 多注册中心→
D07 McpBridge→
D08 Nacos→
D09 ServiceEntry→
D10 配置+证书
🤔 痛点:一个网关开机,到底要"装配"些什么?
想象你盘下一间门店要开业:得先接通水电(连 K8s)、装好收银台(xDS Server)、招好前台和门卫、贴好营业执照(证书)……漏装一样都开不了张。程序也一样——
NewServer 要按顺序把七八个模块初始化好,任何一个失败都不能对外服务。今天就看这份"开业清单"。💡 本质:initFuncList = 一张有序的"开业清单"
Higress 启动的精髓不是某个魔法,而是一份按顺序执行的初始化函数列表(
initFuncList)。就像开业清单"先通水电、再装收银、最后办执照",每一行对应一个后续要细讲的主题。延续 Day 01 的类比:这一步是"翻译官上班前,先把办公桌、电话线(15051)、和总部的专线都接通"。L01
入口 main
// cmd/higress/main.go:25
func main() {
log.EnableKlogWithCobra()
cmd.GetRootCommand().Execute() // cobra 根命令
}
// pkg/cmd/root.go:21 higress 根命令挂 serve + version 子命令
读法:和 istiod(pilot-discovery,Istio 课 Day 02)一样的极简 cobra main。核心是
serve 子命令。L02
serve 命令
// pkg/cmd/server.go getServerCommand RunE(:68)
server, _ := serverProvider(args) // → bootstrap.NewServer(args)
server.Start(stop)
waitForMonitorSignal(stop) // 阻塞等信号
读法:又是"构造 → Start → 等信号"的启动三段(和 Envoy/Istio 课一致)。
serverProvider 指向 bootstrap.NewServer。L03
关键端口
// pkg/cmd/server.go 默认参数(:89-103):
GrpcAddress: ":15051" // ★ istiod 连接的 MCP/xDS 端口(Day 01)
HttpAddress: ":8888" // debug/ready
CertHttpAddress: ":8889" // 证书 ACME
NativeIstio: true
// flag(:105):ingressClass 默认 higress、gatewayHttpPort=80、gatewayHttpsPort=443…
15051 是 Higress Core 的"对外接口"
回想 Day 01:15051 是 Higress Core 起的 MCP Server 端口,istiod 连它拉配置。就像 istiod 用 15012 对 Envoy 服务(Istio 课 Day 02),Higress Core 用 15051 对 istiod 服务。三个端口串起三层:Higress Core(15051) → istiod(15012) → Envoy。8888 是就绪探针(Day 07)、8889 是证书 ACME 挑战(Day 10)。
ingressClass=higress 决定 Higress 只处理标了这个 class 的 Ingress。图注:15051 是本课主角 Core 的"对外电话";15012/Envoy 是你 Istio/Envoy 课已学的下游。
L04
Server 结构
// pkg/bootstrap/server.go:136 Server
type Server struct {
environment *model.Environment // Istio 的!
configController model.ConfigStoreController // Higress 的 IngressConfig
xdsServer *xds.DiscoveryServer // 直接复用 Istio 的 DiscoveryServer!
certServer *cert.Server
...
}
读法:关键:
Server 内嵌的 environment、xdsServer 都是 Istio 的类型(model.Environment、xds.DiscoveryServer)——Higress 直接复用它们!Higress 自己写的是 configController(IngressConfig,Day 03)和 certServer。这坐实了"寄生":Higress 借用 Istio 的骨架。L05
initFuncList
// pkg/bootstrap/server.go NewServer(:152)核心:初始化函数列表(:169)
initFuncList := []func() error{
s.initKubeClient, s.initXdsServer, s.initHttpServer,
s.initConfigController, s.initRegistryEventHandlers,
s.initAuthenticators, s.initAutomaticHttps,
}
initFuncList = "装配清单"
NewServer 按这个列表顺序初始化各模块——这是理解 Higress 启动的最佳骨架。①initKubeClient(连 K8s)②initXdsServer(复用 istiod 的 DiscoveryServer + 换 Generator,Day 05)③initHttpServer ④initConfigController(建 IngressConfig,Day 03)⑤initRegistryEventHandlers(配置变更触发推送)⑥initAuthenticators(认证 istiod 客户端)⑦initAutomaticHttps(证书,Day 10)。每个 init 函数对应后面某一天的主题。这种"init 函数列表"是 Go 项目常见的清晰装配方式(Istio 课 Day 02 也是)。📝 举个例子:开业清单 → 对应哪天学
所以这份清单其实就是"本周的课程表"——每装一个部件,就预告了后面某一天。
initConfigController → 建起翻译官的心脏 IngressConfig(Day 03);initXdsServer → 复用 istiod 的 DiscoveryServer 并换 6 类 Generator(Day 05);initRegistryEventHandlers → 配置一变就触发推送(Day 05/07);initAutomaticHttps → 自动办 HTTPS 证书(Day 10)。所以这份清单其实就是"本周的课程表"——每装一个部件,就预告了后面某一天。
L06
复用 istiod
// initXdsServer(server.go:342):
s.xdsServer = xds.NewDiscoveryServer(s.environment, ...) // Istio 的 xDS server
// 逐类型注册 Higress 自己的 MCP Generator(:346):
s.xdsServer.Generators[gvk.Gateway.String()] = &mcp.GatewayGenerator{...}
s.xdsServer.Generators[gvk.VirtualService.String()] = &mcp.VirtualServiceGenerator{...}
// … 六类:Gateway/VirtualService/DestinationRule/EnvoyFilter/ServiceEntry/WasmPlugin
s.xdsServer.ProxyNeedsPush = func(...) { return req, true } // 永远推送(下游是 istiod)
读法:Higress 不重写 xDS 协议栈——直接 new 一个 Istio 的
DiscoveryServer,只替换六类资源的 Generator(改成从 Higress 的 ConfigStore 生成 MCP Resource,Day 05)。ProxyNeedsPush 改成"永远推"——因为下游是 istiod(一个客户端)而非成千 Envoy,不需要 proxy 级裁剪。这是"复用框架 + 定制生成逻辑"的极致体现。👶 小白:ProxyNeedsPush 改成"永远推",不会把 istiod 累死吗?
👨🏫 老师:不会。原生 istiod 面对成千上万个 Envoy,得精挑细选"这次配置变化跟你有没有关系",省带宽。但 Higress 的 15051 下游只有一个客户端——istiod 本身。既然只有一个订阅者,判断"要不要推"纯属浪费,干脆一律推给它、让它自己合并。就像群发通知只有一个收件人,就不必再筛收件人名单了。
L07
Start 与就绪
Start()(server.go:273):net.Listen("tcp", ":15051") + grpcServer.Serve(对 istiod 服务)。就绪探针 readyHandler(:454)在 :8888/ready,探测 xDS server ready。HasSynced 要所有子控制器同步才 ready。
读法:和 istiod 的 ready 门禁(Istio 课 Day 02)一个道理——所有配置控制器(Ingress/CRD/注册中心)都同步好了,才对 istiod 提供服务,否则会喂不完整的配置。
L08
今日小结 + 动手
🧠 今天你应该能回答
- 启动链 main → serve → NewServer 的结构?
- 15051/8888/8889 各是什么端口?
- Server 结构里哪些是 Istio 的、哪些是 Higress 的?
- initFuncList 的七个 init 函数各干什么?
- Higress 怎么"复用 istiod 的 DiscoveryServer"?ProxyNeedsPush 为什么改成永远推?
✋ 动手
cd /Users/bitmart/work/codes/github/higress-group/higress
sed -n '25,31p' cmd/higress/main.go
grep -n 'GrpcAddress\|initFuncList\|func.*NewServer' pkg/cmd/server.go pkg/bootstrap/server.go
sed -n '342,367p' pkg/bootstrap/server.go
明天预告 · Day 03:Ingress 控制器核心——Higress 自己的心脏
IngressConfig:它是一个只读的 Istio ConfigStore,聚合了 6 个子控制器(Ingress/Gateway/McpBridge/WasmPlugin/Http2Rpc/ConfigMap)。