← All posts

Scale-to-zero 数不到一

Authagonal·July 6, 2026
authinfrastructurekubernetesaksserverlessazurearchitecture

这条建议总是同一个样子。你的认证流量是突发的。你的 Kubernetes 集群大部分时间都很安静。Azure Container Apps 可以缩放到零,并按实际用量计费。你正在为一个大部分时间都在等待的集群全天候付费。

我们足够认真地核算了迁移成本。然后我们放弃了它。不是因为切换的成本,也不是因为冷启动,虽然仅冷启动一条就应该足够了。我们放弃它,是因为这个平台的词汇表里缺少一个数字,而那是我们的认证核心真正在乎的唯一数字。

Serverless 只会数到零和 N

缩放到零的运行时只认识两个数字。没有人调用时是零。有人调用时是 N,N 随需求浮动。对于无状态的请求处理,这套词汇是完美的,这也是这条建议听起来如此正确的原因。大多数 Web 后端确实是这种形态:每个请求相互独立,每个实例随手可弃,零流量就该零账单。

认证系统对外的那一面看起来也是如此。Token 端点、登录页面、JWKS。无状态、突发、缓存友好。

而在它下面,是一个完全不属于这些形态的层。

这个数字是一

在端点之下,我们的背板(backplane)运行着一个协调层。任何时刻都恰好只有一个副本持有集群领导权租约(如今是 blob 租约,不再是 gossip,那是另一篇文章的故事),并运行各个单例作业:保留期清扫、webhook 投递轮次,这类工作里两个并发执行者意味着副作用被触发两次,零个执行者意味着有些事情悄无声息地永远不会发生。

这个层需要的数字是一。不是安静时的零,也不是高负载下的 N。是一,持续持有,并在持有者死亡时进行可验证的交接。缩放到零没有办法表达"始终为一"。它能说"有流量时至少为一",但那是另一种承诺,而这两种承诺之间的差别,恰恰就是领导者选举要防止的那种故障模式。

这就是利用率图在对我们撒谎的原因。安静的认证集群并非无所事事。它持有着租约,让签名密钥保持热备,随时准备在个位数毫秒内响应下一次 token 验证。安静和空闲是两种不同的状态,而账单仪表板只让你看到其中一种。

你可以硬装出来,但那更糟

你可以把"恰好一个"强加到 serverless 运行时上。把最小副本数固定为一,你就买下了一台常驻服务器,而这个平台的全部本能就是收走安静的实例。每次缩放事件、每次平台发起的重启、每次修订切换,都变成一个你无法控制时机的领导权问题。我们将永远与运行时的核心行为作斗争来保住自己的行为,还要为此付费。

而且故障会落在最糟糕的人身上。为冷启动买单的那个请求,背后是一个正在尝试登录的人。"你登录慢是因为我们的认证服务睡着了"这种话,谁都不应该让它上线。

账单有一个无聊的解法

那引发这一切的钱呢?一个调度器加一个 SKU 就解决了。开发集群现在在无人使用时自动停用,节点池换成了更便宜的 SKU。它只配得上一个段落,而这正是重点:"不再为闲置付费"是一个目标,不是一种架构,而这个目标的大部分靠一次配置变更就能实现,不需要更换平台。

形态测试

我们留下的规则:让运行时匹配工作负载的真实形态,而不是它的流量图。Serverless 奖励无状态、突发式的负载。它惩罚任何必须持有连续、排他角色的东西,而一个保管签名密钥、选举谁来执行破坏性作业的认证核心,是我们所知的第二种形态最纯粹的例子。

我们不反对 serverless。我们大量的无状态表面完全可以在上面愉快运行。但那个必须数到"恰好一"的层,会继续留在无聊、常驻、可检查的基础设施上。

当你把认证交给 Authagonal,而不是自己运营背板时,你不再需要运维的,恰恰就是这一层。