← 返回信息流
AI 资讯Hacker News·9 天前

你从未声明状态,你只是在手动观察

原标题:You Were Never Declaring State. You Were Observing by Hand

速览

该文章深入分析了在软件工程和系统设计中,显式状态管理与隐式观察之间的差异。它指出许多开发者误以为自己在管理状态,实际上只是在被动地观察系统行为。这种视角的转换对于理解复杂系统的可观测性和调试至关重要。

AI 深度解读

你从未在声明状态,你只是在手动观测

背景

在基础设施即代码(IaC)的早期历史中,无论是 Terraform、Chef、Puppet 还是 CFEngine,其核心范式都建立在一个根本性的局限之上:工具本身是“盲目”的。

传统的 IaC 工作流要求人类架构师充当系统的“眼睛”。架构师首先观察基础设施的实际状态,然后凭借自己的判断决定基础设施“应该”是什么样子,最后将这些决策编写成 HCL、Ruby 或 YAML 等格式的文件。这些文件被提交给一个只能解析文本、却无法自行感知环境的代理程序(Agent)。代理程序读取文件,并试图让系统收敛到文件中描述的状态。

长期以来,这种模式被称为“声明式状态”(Declarative State)。然而,这篇文章指出,这实际上是一种误解。我们并没有在声明状态,而是在进行“手动观测”,并将观测结果硬编码为一种格式,供无法自主观察的代理程序消费。

随着 AI Agent 能力的提升,特别是具备“沼泽模型”(Swamp Model)方法的引入,Agent 现在能够直接对实时系统进行观测。这一技术转折迫使我们需要重新审视基础设施管理的本质,以及架构师角色的边界移动。

核心内容

1. “声明状态”的本质是手动观测

文章引用了 Mark Burgess 在《In Search of Certainty》中提出的“承诺理论”(Promise Theory)。该理论描述了一种自主 Agent 的模型:Agent 观察环境,做出决策,并针对自身行为做出局部承诺。Agent 观察、Agent 决定、Agent 行动。

然而,过去我们构建的工具无法实现第一步——观察。

  • CFEngine Agent 可以解析承诺体并尝试收敛,但它无法观察更广泛的系统,也无法判断应该做出哪些承诺。
  • Chef Agent 可以按顺序执行资源并检查是否需要收敛,但它无法查看节点的整体状态,也无法判断食谱(Recipe)是否仍然相关。

因此,我们不得不替 Agent 完成观察工作。我们将这种观察称为“期望状态”(Desired State),并将其存储在文件中。这些文件本质上是为缺乏观察能力的 Agent 提供的脚手架。

2. 变革:Agent 现在可以观测了

现在的技术范式发生了改变,Agent 具备了观测能力。通过运行“沼泽模型方法”(Swamp Model Method),Agent 可以对实时系统进行探测,捕获发现的结果,并将其存储为经过类型检查、版本控制和模式验证的结构化数据。

在这个过程中,没有人类预先将观测结果计算并写入文件。以 @webframp/aws/adopt 扩展为例,其唯一目的是观测现有的 AWS 资源,并将其作为结构化数据纳入管理。它不声明资源“应该”是什么,而是捕获资源“实际”是什么。每次执行都会产生现实状态的版本化快照。

例如,运行以下命令:

swamp model method my-account discover_all --json

执行后,Agent 便知晓了 VPC、子网、网关、路由表、安全组、RDS 集群和密钥等的存在。随后可以通过查询获取这些数据:

swamp data query 'modelName == "my-account" && isLatest == true' --json

数据随实时系统演化。如果下周再次运行该方法,会得到一个新的版本。通过比较版本,可以看到漂移(Drift)。由于 Agent 直接观测了现实,因此不再需要声明文件。

3. 边界的移动:从语法设计到数据形状

在过去十年中,架构师的工作包括精心制作声明文件。你需要决定如何在 HCL、Ruby 或 YAML 中表示基础设施。声明的形状本身就是一个设计决策,消耗了架构师的判断力。

现在,这一边界发生了移动。架构师的工作重心转变为决定“观测”在哪里结束,“行动”在哪里开始。

  • 哪些数据足以作为决策的上下文?
  • 什么样的工作流条件足以证明写入操作是合理的?
  • 什么样的模型边界将“感知”与“控制”分开?

这些是边界决策,即选择让一个系统知道另一个系统的什么。你仍然在花费判断力,仍然在定义形状,但现在你思考的重点从“你过去编写的声明语法”转移到了“你想要存储的数据”。你关注的是:观测产生的模式(Schema)是什么?哪些字段可被查询?什么样的版本粒度能让漂移变得可见?设计工作从 HCL 代码块转移到了数据形状上。

4. 诚实的局限:声明并未消失

这种新范式并没有完全消除声明(Intent/Declaration)。在以下三种情况下,仍然需要明确的意图声明:

  1. 配置(Provisioning):你无法观测尚不存在的资源。创建新事物要求你在现实包含它之前指定你想要什么。但这只占基础设施操作工作的一小部分,大部分工作仍是管理已存在的事物。
  2. 合规基线(Compliance Baselines):“所有 S3 存储桶必须启用加密”是一条意图声明,而非对现实的观测。合规基线本质上是声明,但它存在于 Zod 模式或工作流条件中,而不是每个资源的 YAML 块中。
  3. 回滚目标(Rollback Targets):“回滚到周二的状态”需要知道周二时状态是什么。版本化数据提供了这一点(检索版本 N),但必须有人决定哪个版本是回滚目标。这个决定就是意图。

在所有这三种情况下,意图存在于方法逻辑、工作流条件和模式定义中,而不是存在于在两次应用(Apply)之间与现实产生漂移的静态文件中。声明从工具读取的文件,变成了 Agent 推理的约束。声明依然存在,只是介质不同。

5. 幂等性上移

旧工具要求每个资源单独具备幂等性。Chef 资源必须在写入前检查文件是否存在,Terraform 资源必须检测安全组是否已包含该规则。每个原子操作都自带收敛逻辑,因为 Agent 无法推理更广泛的上下文。

当 Agent 可以在执行前查询版本化状态时,幂等性变成了工作流判断的属性,而不是每个子步骤实现的属性。Agent 会问:“这项工作是否已经完成?”它检查最新的快照。如果答案是肯定的,它跳过操作。单个方法不需要具备幂等性,因为工作流决定不调用它。

这连接到了实践中可见的一种模式:检查工作流共享状态并决定“什么都没变,跳过此步骤”。过去的管道假设每个阶段都必须运行,因为没有阶段能推理它是否应该运行。现在,Agent 先进行检查。

6. 实际意义

@webframp/aws/adopt 工作流通过纯观测产生价值,并在用例中产生复利效应:

  • 可查询性:你可以对整个 AWS 账户状态运行 CEL 查询。例如:“显示所有标记为 production 且在过去 30 天内创建的资源。”除非所有资源都已受 Terraform 管理,否则你无法从 Terraform 状态文件中回答这个问题。
  • 组合性:其他 swamp 模型和工作流将采用的资源数据作为输入。例如,安全扫描工作流可以直接读取 adopt 输出来回答“哪些安全组允许来自 0.0.0.0/0 的端口 22 入站流量?”合规工作流读取它来知道要验证哪个基线。
  • 漂移意识:定期运行 adopt。每次运行都会产生新版本。“自上周四以来我的 VPC 配置发生了什么变化?”通过比较版本来回答。你比较的是时间 T 的现实与时间 T-1 的现实,无需与声明进行比较。

7. 原则的延续

承诺理论描述了自主 Agent 观察环境并推理该做什么。我们过去构建的近似值受限于可用的 Agent:那些只能解析文件而无法观察的守护进程。声明是那些受限 Agent 所需的脚手架。

现在,除了配置、合规和回滚外,脚手架对于其他所有事物都是可选的。收敛、自主性和局部推理等原则,比任何一代静态声明都能更好地得到服务。Burgess 关于 Agent 应该做什么的观点是正确的,Agent 只是花了三十年才赶上。

你从未在声明状态。你一直在做你的工具无法为自己完成的观测工作。现在工具赶上了。留给架构师的问题是:我在 Agent 观测什么和 Agent 改变什么之间划定的界限在哪里?

关键要点

  • 范式纠偏:传统的 IaC(如 Terraform、Chef)并非真正的“状态声明”,而是人类手动观测系统并将结果硬编码为文件,供无法自主观察的盲工具使用
查看原文 →webframp.com