Skip to content

API 设计指南

原文:https://gateway-api.sigs.k8s.io/contributing/api-design-guide/

整个 API 中贯穿着一些通用的设计指导原则。

NOTE

注意

在 Gateway API 全部的文档和规范中,"MUST"、"MAY"、"SHOULD" 这类关键字广泛使用。它们应当按照 RFC 2119 中的定义来理解。

Kubernetes API 单个资源层面保证一致性。这对复杂的资源图(与单个资源相对)带来个后果:

  • 跨越多个资源的属性校验异步最终一致的。简单的语法检查可以在单个资源层面完成,但跨资源的依赖必须控制器自行处理。
  • 控制器必须能够处理资源之间链接失效以及/或者配置不匹配的情况。

冲突

相互独立的行为者(例如集群运维和应用开发者)之间责任分离与委派导致配置中的冲突。例如,个应用团队可能不经意地同一个 HTTP 路径提交配置。

大多数情况下,可能发生冲突的字段在文档中给出冲突解决指南。如果某个冲突没有规定的解决方案,以下指导原则来处理:

  • 优先不去破坏正在工作的东西。
  • 尽可能少地丢流量。
  • 在冲突发生时提供一致的体验。
  • 当识别出冲突时,清楚地说明选择了哪条路径。在可能的情况下,通过在相关资源的 status 条件中设置适当的值来告知用户。
  • 更具体的匹配应当不太具体的匹配优先
  • 创建时间最早的资源获胜
  • 如果其它一切都相等(包括创建时间),应当优先级交给字典序靠前的资源(namespace/name)。例如,foo/bar 应当foo/baz 优先

优雅地处理未来的 API 版本

实现本 API 时一个重要的考量是:它在未来会如何变化。与之前的 Ingress API 类似,本 API 设计为同一集群中的多种不同产品实现。这意味着:你的实现开发时所基于的 API 版本可能实际使用时的 API 版本不同

至少必须满足以下要求,才能保证未来版本的 API 不会破坏你的实现:

  • 字段验证被放宽崩溃
  • 字段从必填变为可选崩溃

支持的 API 版本

集群中安装的 Gateway API CRD 版本,可以通过查看个 CRD 上的 gateway.networking.k8s.io/bundle-version 注解来确定。个实现必须把该版本识别和支持的版本列表做比较拥有 GatewayClass 的实现必须在 GatewayClass 上发布 SupportedVersion 条件,用以指出集群中安装的 CRD 是否受支持。

CRD 与 Webhook 校验的局限

CRD 与 webhook 校验并非最终校验——webhook 只是"良好的 UX",是模式强制(schema enforcement)。这种校验意在为用户在提供了无效配置提供即时反馈。防御式的方式编写代码——假设到你的控制器的输入至少会部分无效的输入(Gateway API 资源)。Webhook 和 CRD 校验不是完全可靠的,因为它们:

  • 可能没有正确部署。
  • 可能未来的 API 发布中被放宽(字段可能版本 API 中包含验证更宽松的值)。

:这些限制并非 Gateway API 独有,更普遍地适用于所有 Kubernetes 的 CRD 与 webhook。

实施者应当保证:即使 API 中出现了意料之外的值,他们的实现也仍然尽可能安全、优雅地处理这种输入。最常见的做法把该配置视为格式错误拒绝**,通过 status 块中的 condition 告知用户。为了避免重复劳动,Gateway API 维护者们正在考虑添加一个共享的校验包,实现可以直接使用——这 #926 跟踪

期望

我们预期在这个 API 的早期不同提供方之间的一致性程度参差不齐。用户可以通过一致性测试的结果了解实现行为与规范可能存在差异地方**。

实现特有(Implementation-specific)

在 API 的部分方面,我们用户能够指定该特性的使用方式,但具体行为可能取决于底层实现。例如,正则表达式匹配在所有实现中都存在,但由于底层库的微妙差异(PCRE、ECMA、Re2),指定一个精确的行为是不可能的用户在最大程度上描述该特性仍然有用的,我们承认:部分 API 子集的行为可能仍然会有所不同(这是**可以接受的)。

这些情形标记为 API 的"实现特有"界定部分。

Kind vs. Resource

与其它 Kubernetes API 类似,Gateway API 在整个 API 的对象引用中使用"Kind"而不是"Resource"。这种用法大多数 Kubernetes 用户来说应该不陌生

根据 Kubernetes API 约定这意味着本 API 的所有实现应当在 kind 与 resource 之间一份预定义的映射。依赖动态 resource 映射不安全的。

API 约定

Gateway API 遵循 Kubernetes API 约定。这些约定在简化客户端开发,并保证配置机制能够各种用例中一致地实现。除了 Kubernetes API 约定之外,Gateway API 有下面这些约定:

列表名(List Names)

本项目另一个约定是:CRD 中列表的字段名使用复数。我们使用以下规则:

  • 如果字段名是名词复数。
  • 如果字段名是动词单数。

基于 MIT 协议发布