读懂 APISIX Translator:多集群 Pod 到统一网关的一条链路
# 读懂 APISIX Translator:多集群 Pod 到统一网关的一条链路
如果只有一个 Kubernetes 集群,这个问题不值得单独写一个控制器。
单集群里,Envoy Gateway、Ingress Controller、APISIX Ingress Controller 都有成熟路径。控制器在集群里 watch 资源,再把流量导到 Service 或后端 Pod。这个模式清楚,也足够标准。
APISIX Translator 处理的是另一个场景:平台同时管理多个 Kubernetes 集群,APISIX Gateway 放在集群外,作为统一入口。业务 Pod 分散在不同集群里,但用户希望用同一种方式暴露端口。
这个场景可以压成一句话:
下面这张图就是 APISIX Translator v0 的主流程。

这篇文章只按图讲结构,不展开实现细节。
# 图里有几类角色
先看参与者。
左边是 Translator。它有多个实例,但只有 leader 干活。其他实例 standby,等 leader lease 出问题时接手。
中间偏左是 多个 Kubernetes API。Translator 不只看一个集群,而是同时面对多个业务集群。每个集群里都有可能出现需要暴露的 Pod。
中间偏右是 APISIX Admin API 和 APISIX etcd。Translator 不直接碰数据面,也不直接写 APISIX etcd。它只通过 Admin API 写入 APISIX 控制面。
右边是 APISIX DP 和 PodIP:Port。APISIX DP 拿到配置后,把请求转发到具体 Pod 的 IP 和端口。
把角色压成一句话:
这就是整张图的骨架。
# 用户只声明 Pod 要暴露
用户侧不需要写 APISIX Route,也不需要知道 upstream 怎么配。
Pod 只需要带两类 metadata:
- 一个 label:表示这个 Pod 要被 Translator 接管。
- 一个 annotation:描述要暴露哪个端口、用什么 route name、必要时指定 host 或 uri。
Translator watch 这些 Pod。看到声明后,它会解析 annotation,生成一个“期望的网关状态”。
这一步很重要,因为它把用户的心智保持在 Pod 上:
多集群信息由平台补上。Translator 生成对象时会带上 cluster、namespace、PodUID 和 routeName。这样 APISIX 里的对象能追溯到来源 Pod。
# Leader 启动后先做一次全量对账
图里第一段是 leader 选举。
Translator 多实例部署,但同一时间只有一个 leader 写 APISIX。leader 启动后先做一次全量 reconcile,再处理后续 Pod 变化。
这个动作可以拆成四步:
- 从多个 Kubernetes API 拉取 enabled Pods。
- 解析 Pod label 和 annotation。
- 算出 APISIX 里应该存在的 route/upstream。
- 查询 APISIX 当前已经存在的 Translator 管理对象。
然后做 diff。
这就是 reconcile 的意义:不要相信进程内 cache,也不要只相信 watch event。Translator 每次都把 Kubernetes 当前状态和 APISIX 当前状态拿出来对账。
# 没有冲突就写 upstream 和 route
图中间有一个分支:host + uri 冲突。
如果发现冲突,Translator 不覆盖旧 route。它记录状态或事件,让用户知道这条声明不能生效。
如果没有冲突,Translator 通过 APISIX Admin API 写入两个对象:
APISIX Admin API 写入后,配置进入 APISIX etcd。APISIX DP watch 到新配置,就可以开始接流量。
请求链路变成:
这里 Translator 不在请求链路上。它只负责把配置写正确。
# Pod 变化后走增量 watch
图的第二段是 watch 增量变化。
Pod add、update、delete,或者 label/annotation 变化,都会触发 Translator 重新计算对应对象。
这里不用把每个事件都理解成“马上改 APISIX”。更准确的理解是:
如果 Pod 新增或更新,Translator upsert route/upstream。
如果 Pod 删除,或者不再带 enabled label,Translator 删除自己创建的 route/upstream。
删除时只删自己创建的对象。APISIX 对象上会带来源身份,Translator 不能按 host 或 uri 模糊删除。这个原则比具体实现更重要。
# 某个集群断联时,不删除旧配置
多集群系统最容易出问题的地方,是某个 Kubernetes API 突然不可用。
图里这一步写得很清楚:K8s API 断联时,Translator 标记 cluster degraded,但不删除任何 route/upstream。
原因很简单:看不见就不能乱删。
如果 Translator 根据旧 cache 清理 APISIX,可能会误删仍然存活的业务入口。更稳的做法是保留旧配置,继续重连。等 Kubernetes API 恢复后,再做 full reconcile,把状态对齐。
这也是这张图里最关键的控制器取舍之一。
# Leader 异常后,新 leader 重新全量对账
图底部还有一段 leader lease。
standby 实例会持续观察 leader lease。如果 leader 异常,standby 变成新的 leader。
新 leader 不继承旧 leader 的内存状态。它重新 List 全量 Pods,再查询 APISIX 当前对象,然后重新 reconcile。
这让故障恢复变简单:不需要相信上一个进程留下的 cache,只需要重新对账。
# SDK 只是帮业务生成声明
另一张图讲的是 SDK。
SDK 的边界也很简单:它只帮业务生成 Pod metadata。
它不连接 Kubernetes,不调用 APISIX,也不判断路由是否生效。业务用它少写一些 annotation JSON。真正的 watch、reconcile、冲突处理和 APISIX 写入,仍然由 Translator 完成。
# 小结
APISIX Translator 不是单集群网关控制器的替代品。
它的结构可以用一条线概括:
读这张图时,抓住三件事就够了。
第一,Translator 面向的是多个 Kubernetes API,不是单个集群。
第二,Translator 不处理真实请求,只把 Pod 暴露声明翻译成 APISIX 配置。
第三,系统靠 reconcile 对账,而不是靠某一次 watch event 直接决定最终状态。
理解这三点,APISIX Translator 的整体结构就清楚了。
