跳到主要内容

你的数据驻留政策中遗漏的推理区域锁定

· 阅读需 10 分钟
Tian Pan
Software Engineer

合规审计总是从同一个问题开始,而你的团队也总是以同样的方式回答:“客户数据在哪里处理?”在欧盟(EU)地区。幻灯片是这么说的,SDK 配置截图证实了这一点,DPA(数据处理协议)也做出了承诺。接着,审计员提取了上个季度的请求日志样本,将其与服务商的每请求区域头信息(per-request region header)进行比对,房间里顿时安静了下来。在大约 40 分钟的容量事件期间,大约 4% 的欧盟企业 Prompt 由美国区域的推理节点提供服务,而团队对此一无所知。保存可重用前缀(prefixes)的缓存位于全球池中。支持团队查询的追踪存储(trace store)位于 us-east。DPA 成了幻灯片。合同成了一个路由提示(routing hint)。

这种事件不会出现在事后分析(postmortem)中,因为没有任何服务降级。模型返回了答案,用户得到了响应,延迟图表保持平稳。出故障的是仪表盘从未监测到的东西:请求穿过服务商基础设施的地理路径。那些绝不会将 us-east-1 的 URL 与“请求实际上在 us-east-1 执行”混为一谈的工程师,在 LLM API 层级却经常犯同样的错误,因为服务商的区域参数看起来像 AWS 的参数,在正常路径(happy path)下表现也像 AWS,但一旦首选区域的 GPU 耗尽,它就会静默降级为“尽力而为(best effort)”模式。

终端区域性不等于数据处理区域性

第一个困惑是语言上的,它是所有下游失败的根源。区域终端(regional endpoint)是一个 URL。数据处理区域性(data processing regionality)是处理特定请求的计算资源的属性。服务商用“区域(region)”一词来描述这两者,而消费者则推断出一种在 API 合同中任一领域都不存在的保证。

如果你仔细阅读部署类型页面,主要超大规模云服务商(hyperscaler)的 AI 界面对这种区别有明确说明,但如果你看营销页面,则含糊不清。Azure OpenAI 提供了一个分层模型:全球(Global)部署在任何 Azure 区域处理推理,数据区(Data Zone)部署在多国边界内处理,而区域(Regional)部署仅在部署区域内处理。大多数团队选择默认的全球层级,因为它拥有最高的最默认配额和最平滑的容量表现。“我们使用 Azure”这个关于数据驻留(residency)问题的回答在技术上是正确的,但在操作上毫无意义。

OpenAI 的直接 API 为符合条件的客户提供欧洲区域项目,并在区域内路由请求且不保留数据。Anthropic 的直接 API 提供“美国(us)”和“全球(global)”推理地理区域,但在 API 层级没有专门的仅限欧盟(EU-only)选项;需要 Claude 欧盟驻留的团队转而通过 AWS Bedrock 欧盟区域或 Google Vertex AI 欧盟区域进行路由。这些都不是错误的设计选择。它们是一个四轴空间中的不同点——终端 URL、处理地理区域、保留态势(retention posture)、故障转移行为(failover behavior)——消费者必须明确地进行工程设计。将“我们配置了欧盟终端”作为完整答案的团队只在其中一个轴上进行了工程设计。

故障转移至全球池的问题

第二种失败模式是审计员抓到的那种。当首选区域容量耗尽时,服务商会怎么做?SDK 文档给出的答案与生产系统实现的答案很少是一致的。

服务商为了维持可用性而实现的行为是合理的:静默回退到更广泛的容量池,以便客户的请求仍然成功。客户在 DPA 中签约的行为则相反:在区域外处理之前拒绝请求。这两者在最糟糕的时刻发生冲突——在负载之下,当首选区域的容量耗尽,且处理不当的请求量达到最大时。

相关的问题不是“服务商是否有欧盟区域”,而是“当欧盟区域现在无法处理我的请求时,服务商会怎么做”。如果答案是“我们路由到任何有容量的地方”,那么驻留态势就是一个路由提示,合同就是虚构的。如果答案是“请求失败并返回 503,由应用层决定是重试、排队还是显现错误”,那么驻留态势就是一份合同,其代价是区域容量事件期间的可用性。在任何版本中,驻留都不是免费的。

这也是 Prompt 缓存层背叛那些未加留意的团队的地方。许多服务商维护一个用于快速重复前缀命中的区域缓存,以及一个作为更高级别优化的全球缓存。除非服务商在每个响应中输出该信息,否则消费者无法分辨是哪个缓存服务了特定请求,而大多数服务商并不这样做。区域缓存未命中可能导致全球缓存命中,从而跨越了 DPA 禁止的边界,而产生的追踪记录看起来与干净的区域未命中并重新计算完全相同。

技术问题背后的组织失效模式

数据驻留缺口很少只是某个团队的失误。它是组织内部工作划分方式的必然结果。法务团队负责 DPA(数据处理协议)并阅读供应商关于区域端点的营销文案;基础设施团队负责 SDK 配置,看到区域参数并进行设置;采购团队负责合同谈判,将“提供欧盟区域”视为一个勾选项;而产品团队负责对客户的承诺,却对上述情况一无所知。

供应商的条款细则夹在这四个团队之间,却无人问津。关于故障转移行为的条款、关于全局缓存层的脚注、关于哪些响应字段编码了实际处理区域的操作细节——这些内容只有在审计时才会被审计员阅读,在发生事故时才会被事故指挥官阅读。在设计阶段,负责确保设计正确性的人员并不会阅读这些内容,因为设计跨越了团队边界,而每个团队的所有权都在缺口边缘戛然而止。

弥补这一缺口的模式往往令人感到不适:需要一个指定的端到端驻留负责人,他有权在同一次会议中向基础设施团队询问“SDK 在故障转移时会做什么”,并向法务团队询问“DPA 对故障转移有什么要求”。如果没有这个角色,技术现状与法律合规要求就会随着功能迭代速度的加快而渐行渐远。

“工程化的数据驻留”究竟是什么样的

实现贯穿整个技术栈的工程化驻留,意味着将其视为一个需要针对每个请求进行验证的属性,而不是在配置文件中声明的属性。在网关和路由层中正在出现几种模式,用以区分那些真正做到了这一点的团队与那些自以为做到了的团队。

  • 基于请求的区域信息透传 (Per-request region surfacing)。要求供应商(如有必要,需在合同中注明)在每次调用时,在响应头中返回实际的处理区域。如果没有这一点,数据驻留的承诺在原则上就是不可验证的。有了它,路由审计流水线就可以对生产流量进行采样,并将每个请求的实际区域与每个客户的策略进行对比。
  • 失败关闭路由 (Fail-closed routing)。配置 SDK 或网关,使其在首选区域无法提供服务时拒绝请求,而不是重新路由。其代价是在区域容量事件期间牺牲可用性,你必须明确地与客户协商这一权衡。如果不这样做,就会在合同本应监管的条件下发生隐蔽的合规违规。
  • 将缓存区域性作为一等约束。以书面形式询问供应商:哪些缓存层为哪些请求提供服务,以及全局缓存是否可以为首选处理区域为特定区域的请求提供服务。如果得到的回答是“尽力而为 (best effort)”,那么合同漏洞就尚未堵上。
  • 区域本地化的追踪和日志存储。如果一种驻留方案仅止于推理调用,却让追踪信息、输入、输出和推理 Token 流向美国区域的可观测性技术栈,那么它只是将驻留问题在技术栈中向下移动了一层。审计迟早会跟进。
  • 面向客户的驻留仪表板。发布证据,而非承诺。按客户分布的逐请求区域分布情况、按部署类型和故障转移事件细分的数据,才是客户审计员真正会接受的交付物。能够按需生成这些数据的团队才真正实现了工程化驻留,而那些必须从不完整的日志中重建数据的团队则没有。

没人协商过的可用性权衡

区域绑定 (Regional Pinning) 的真实版本是:它会牺牲可用性。当欧盟区域无法处理欧盟客户的请求时,该请求必须失败而不能重新路由,否则就不是真正的区域绑定。大多数团队还没有与客户进行过这种对话,因为大多数团队根本没意识到自己在规避这个问题。

对话通常有两种走向。要么客户说“是的,我们接受在区域容量受限期间 SLA 降低,因为驻留是更硬的约束”,然后诚实地签署合同。或者客户说“我们两者都要,你想办法解决”,这时团队要么必须运行一个能在驻留边界内进行故障转移的多供应商路由层,要么在边界内运行自己的推理服务,或者回过头去重新谈判。这些选项没有一个是快速的。但所有这些都比那种承诺两者兼得、却在审计时才发现冲突的路径要廉价得多。

更深层次的认识是,“数据驻留”不是配置界面上的一个设置。它是团队必须在技术栈的每一层(端点、缓存、日志、回退、重试、可观测性)进行工程化实现的一个属性,并且需要针对每个请求(而非每季度)进行验证。供应商的区域参数只是第一个维度,而不是答案。那些将其视为答案的团队所交付的合规方案,只能维持到第一次真正的审计。而第一次真正的审计何时到来,现在只是一个时间问题,而不是是否会发生的问题。监管机构已经行动起来,审计员已经跟上,而基于请求的区域头 (per-request region header) 将是下一次对话开始的基础。

References:Let's stay in touch and Follow me for more thoughts and updates