Day 10 / 共 20 天 · 第 2 周收官

配置模型 + 证书管理

收官第 2 周:先看 Higress 的 config 模型(复用 Istio),再看它的自动 HTTPS——用 certmagic + ACME Let's Encrypt,还有一个"用自身网关完成 HTTP-01 挑战"的巧妙设计。前 9 天我们看透了"配置怎么翻译下发""服务怎么发现",今天补上产品化的最后一块拼图——让网关自动办好并续期 HTTPS 证书,收官第 2 周,第 3 周将转向插件生态。

📍 你在 Higress 源码课的位置(第1周 全景与控制器 · 第2周 服务发现与配置)
D01 全景 D02 启动 D03 Ingress控制器 D04 配置翻译 D05 xDS-over-MCP D06 多注册中心 D07 McpBridge D08 Nacos D09 ServiceEntry D10 配置+证书
💡 本质:自动 HTTPS = 门卫帮你自动办证并续期,还自己接待核验员 HTTPS 证书就像门店的营业执照——顾客(浏览器)进门要先验它是不是真店。传统做法要你亲自跑一趟工商局申请、到期还得记得续。Higress 的自动 HTTPS:你只说一句"给 example.com 办证",门卫(网关)就自动去发证机关(Let's Encrypt)申请、到期前自动续。最妙的是核验环节——发证机关要派人上门核实"你真的是这家店"(HTTP-01 挑战),门卫干脆临时开一个专用接待窗口(临时 Ingress)接待核验员,验完就撤。用自己的网关能力解决自己的发证需求,自举、优雅。
L01

配置模型

// pkg/config/envs.go:环境变量配置
//   PodNamespace 默认 higress-system、GatewayName 默认 higress-gateway
//   McpServerWasmImageUrl 默认阿里云 OCI 镜像
// pkg/config/constants/constants.go:
//   DefaultIngressClass/DefaultGatewayClass = "higress"
//   ManagedGatewayController = "higress.io/gateway-controller"
//   RegistryTypeLabelKey/RegistryNameLabelKey(Day 09 打给 ServiceEntry 的标签)
读法:config 包放全局常量和环境变量——命名空间、网关名、ingress class、各种标签 key。DefaultIngressClass=higress 决定 Higress 只处理标了这个 class 的 Ingress(避免和其他 Ingress 控制器冲突)。
L02

复用 Istio config

Higress 的 config 模型 = 复用 Istio + 自建聚合 Higress 不重新发明配置类型——直接复用 Istio 的 config.Configconfig.Metaconfig.GroupVersionKind(Istio 课 Day 03)。它自己写的是 IngressConfig(Day 03)这个聚合 ConfigStore——把三类来源(Ingress、Gateway API、McpBridge 注册中心)统一转换成 Istio 的 config.Config,用 GVK 区分资源类型。McpBridge 的注册结果最终以 Namespace:"mcp" 的 ServiceEntry 形式融入 Istio 配置体系(Day 09)。Higress 自有 CRD(McpBridge/WasmPlugin/Http2Rpc)的 proto/client 在 api/client/pkg/"复用成熟抽象 + 自建聚合层"是 Higress 的一贯策略。
L03

自动 HTTPS 概览

Higress 用 certmagic(caddy 的证书库)+ acmez 实现自动 HTTPS。配置在 higress-https ConfigMap,Issuer 支持 aliyunsslletsencryptpkg/cert/config.go:41)。默认续期提前 30 天。

自动 HTTPS = "证书全自动" 传统上给网站配 HTTPS 要:申请证书、配置、到期手动续。Higress 的自动 HTTPS:你只需声明"我要给 example.com 自动签证书",Higress 就通过 ACME 协议(Let's Encrypt)自动申请、自动续期——零手动。底层用 certmagic(Caddy 服务器的证书引擎,久经考验)。这是"网关帮你搞定证书"的产品化能力——又一个"让用户省心"的产品特性。
L04

certmagic 引擎

// pkg/cert/certmgr.go:52 InitCertMgr
//   用 ConfigMap 作 certmagic 的 Storage(:59)
//   RenewalWindowRatio = RenewBeforeDays/90(:60)
//   ACMEIssuer:CA 用 LetsEncryptProductionCA,禁 TLS-ALPN、启用 HTTP-01(:86)
//   注入自定义 ingressSolver(:94)
// Reconcile(:116):配置变化时 manageSync 管理域名证书,触发 XDSUpdater.ConfigUpdate 全量推送
读法:CertMgr 封装 certmagic:配好 CA(Let's Encrypt)、续期比例、challenge 方式(HTTP-01)。Reconcile 是证书的控制循环(和 Day 07 的 Reconcile 同模式)——配置变了就管理对应域名的证书。证书变更触发 xDS 全量推送(让 Envoy 用新证书)。
L05

HTTP-01 挑战(巧妙设计)

// pkg/cert/ingress.go IngressSolver(实现 acmez.Solver)
// Present(:58):挑战时【动态创建一个 Ingress】
//   path /.well-known/acme-challenge/{token},后端指向 higress-controller:8889
// CleanUp(:95):验证完删除该 Ingress
用网关自己完成 ACME 挑战——绝妙 Let's Encrypt 签证书前要验证"你真的拥有这个域名"——HTTP-01 挑战:它访问 你的域名/.well-known/acme-challenge/{token},你能返回正确 token 就证明拥有域名。问题:这个验证请求得能到达 Higress。Higress 的巧妙解法:动态创建一个临时 Ingress,把 /.well-known/acme-challenge/{token} 路由到自己的证书服务(8889 端口)——用自身的网关能力来接 Let's Encrypt 的验证请求!验证完删掉这个临时 Ingress。网关用自己解决自己的证书验证——自举、优雅。这是"用产品自身能力解决产品自身需求"的漂亮设计。
HTTP-01 挑战:门卫自己开临时窗口接待核验员 Higress 门卫 certmagic Let's Encrypt 发证机关 临时 Ingress (窗口) /.well-known/... → :8889 ① 申请 example.com 证书 ② 派核验员访问 域名/.well-known/acme-challenge/{token} ③ Present 建窗口 ④ 返回 token 通过 → ⑤ 发证 → CleanUp 撤窗口
图注:Present 动态建临时 Ingress 接待核验请求,验完 CleanUp 撤掉——网关自举完成证书签发。
📝 举个例子:给 example.com 自动签证的一次全过程 你在 higress-https ConfigMap 声明 example.com 用 letsencrypt →
certmagic 向 Let's Encrypt 申请 → LE 说"证明你拥有 example.com,我去访问 http://example.com/.well-known/acme-challenge/abc123" →
Present 动态建临时 Ingress:把该 path 路由到 higress-controller:8889 → LE 访问,8889 返回正确 token → 验证通过 →
LE 签发证书 → OnEvent(cert_obtained) → 写入 K8s TLS Secret → xDS 推给 Envoy → CleanUp 删临时 Ingress。全程零手动。

👶 小白:为什么不直接固定配一条 challenge 路由,非要"动态建、验完删"?

👨‍🏫 老师:因为 challenge 路由只在申请/续期那几秒有用,平时留着纯属多余、还多一条对外暴露的路径(安全面)。动态建、验完删让这条特殊路由"用时才存在",既不污染常态配置,也把暴露窗口压到最短。这跟 Day 04 的"惰性生成"一个味道——需要时才造,用完即弃。

L06

ConfigMap 存储

pkg/cert/storage.go ConfigmapStorage 实现 certmagic 的 Storage 接口(Exists/Store/Load/Delete/Lock/Unlock),把证书、账户、锁全存进 K8s ConfigMap。

用 ConfigMap 当"证书数据库" certmagic 需要一个地方存证书、ACME 账户、分布式锁。Higress 不引入外部数据库,而是用 K8s ConfigMap 作存储——实现 certmagic 的 Storage 接口,把这些数据全塞进 ConfigMap。好处:零外部依赖——K8s 集群本身就是存储,多个 Higress 副本共享同一个 ConfigMap(含分布式锁,避免多副本同时申请证书)。这是"复用 K8s 原生能力做持久化"的云原生实践(和 Istio 用 Secret 存证书同理)。
L07

证书落地

certmgr.go:203 OnEvent 监听 certmagic 的 cert_obtained 事件——拿到证书后解析有效期,secretMgr.Update 把证书写入 K8s TLS Secret 供网关使用。控制器 pkg/cert/controller.go watch higress-https ConfigMap 触发 Reconcile;pkg/cert/server.goHTTPChallengeHandler 在 8889 处理 ACME 挑战。

读法:证书申请成功 → 写入 K8s TLS Secret → Envoy(通过 istiod SDS)用它做 TLS。整个链路:ConfigMap 配置 → Reconcile → certmagic 申请(HTTP-01 挑战)→ 证书存 ConfigMap + 落地 TLS Secret → xDS 推给 Envoy。全自动、零手动。
L08

第 2 周收官 🎓

🧠 第 2 周(服务发现与配置)你已掌握

  • Day 06 多注册中心:8 种类型、Watcher 统一接口、BaseWatcher 组合
  • Day 07 McpBridge CRD、Reconciler 控制循环、diff 式协调、watcher 工厂
  • Day 08 Nacos 三代、轮询+订阅、generateServiceEntry
  • Day 09 共享内存缓存、生产者-消费者、延迟删除、convertServiceEntry、全链路
  • Day 10 config 模型复用 Istio、自动 HTTPS certmagic、HTTP-01 自举、ConfigMap 存储

你现在理解了 Higress 的两大特色能力:多注册中心服务发现(连接老微服务生态)和自动 HTTPS。第 3 周进入插件生态——Wasm 插件怎么写和加载。

✋ 动手

cd /Users/bitmart/work/codes/github/higress-group/higress
grep -n 'DefaultIngressClass\|RegistryTypeLabelKey' pkg/config/constants/constants.go
grep -n 'func InitCertMgr\|func.*Reconcile' pkg/cert/certmgr.go
grep -n 'func.*Present\|func.*CleanUp' pkg/cert/ingress.go
明天预告 · Day 11(第3周开始)Wasm 插件系统概览——Higress 的插件生态:Wasm 插件 vs golang-filter 两套机制、和 Envoy proxy-wasm 的关系、SDK 已迁到独立 module。
← Day 09 ServiceEntry Day 11 · Wasm 插件系统概览 →