忽略未指定的字段


本文档介绍了如何使用 cnrm.cloud.google.com/state-into-spec 注解更改用于填充行为的默认规范字段,以及何时需要更改该字段。

在外部管理字段中所述,当 Config Connector 在 Google Cloud 上创建资源时,规范中未指定的字段将采用 API 中的值,除非这些值不可读取(例如,无法通过 GET HTTP 请求获取)。

这意味着默认情况下,原始 YAML 中未指定的字段始终显示在 Kubernetes 资源的规范中。这意味着,当您执行 kubectl get <resource kind> <resource name> -oyaml 时,资源规范中的许多字段不在应用的 YAML 中。

例如,假设 CRD 架构允许您在规范中指定两个名为 foobar 的字段,而应用的 YAML 文件仅指定了 foo

spec:
  foo: "foo"

如果成功应用 YAML 且资源为 UpToDate,您会看到 Kubernetes 资源中显示了另一个名为 bar 的字段:

spec:
  foo: "foo"
  bar: "bar"

由于 Config Connector 与 Google Cloud API 之间交互的复杂性,您可能需要更改此默认行为,并跳过使用未指定的字段填充资源规范。

跳过将未指定的字段填充到规范中

创建 YAML 文件时,您可以将 cnrm.cloud.google.com/state-into-spec 注解的值指定为 absent。这样无需将未指定的字段填充到 Kubernetes 资源规范中:

metadata:
  annotations:
    cnrm.cloud.google.com/state-into-spec: absent

如果未指定该注解,则其默认值为 merge,这意味着 Config Connector 会将所有未指定的字段填充到规范中。此注解是不可变的,这意味着您无法更新现有 Config Connector 资源的注解值。

如果您已创建资源,但想要更改此注解的值以适应不同的填充行为,则必须按照以下步骤操作:

  1. 修改现有 Kubernetes 资源并向其添加注解 cnrm.cloud.google.com/deletion-policy: abandon,以确保下一步删除操作不会删除底层 Google Cloud 资源。

  2. 从 Kubernetes 集群中删除资源。

  3. 将注解 cnrm.cloud.google.com/state-into-spec: absent 添加到资源的 YAML 中。

  4. (可选)从 YAML 中移除 cnrm.cloud.google.com/deletion-policy: abandon

  5. 应用更新后的 YAML。

为了进一步解释此注解带来的区别,假设存在具有以下架构的规范:

foo1: string
foo2: string
bars:
- bar:
    br1: string
    br2: string
barz:
  bz1: string
  bz2: string

另外,假设您已在 YAML 中按如下方式指定规范:

spec:
  foo1: "foo1"
  bars:
  - br1: "1_br1"
  - br1: "2_br1"
  barz:
    bz1: "bz1"

那么默认情况下,所创建的 Kubernetes 资源中填充的规范可能是:

spec:
  foo1: "foo1"
  foo2: "foo2"
  bars:
  - br1: "1_br1"
    br2: "1_br2"
  - br1: "2_br1"
    br2: "2_br2"
  barz:
    bz1: "bz1"
    bz2: "bz2"

虽然如果您设置了 cnrm.cloud.google.com/state-into-spec: absent,则所创建的 Kubernetes 资源中的最终规范将是:

spec:
  foo1: "foo1"
  bars:
  - br1: "1_br1"
  - br1: "2_br1"
  barz:
    bz1: "bz1"

何时使用 cnrm.cloud.google.com/state-into-spec: absent

在一些常见的情况下,您可能需要设置 cnrm.cloud.google.com/state-into-spec: absent

在外部管理列表中的未指定字段

Config Connector 将资源规范中的所有列表字段视为原子字段。因此,默认情况下,Config Connector 会还原您在 Config Connector 之外对列表中的子字段所做的更改。但是,您可以使用该注解让 Config Connector 取消管理列表中的子字段。如需了解详情,请参阅资源规范中列表字段的行为

解决配置管理工具和 Config Connector 之间的冲突问题

如果您使用的是 Config SyncArgo CD 等配置管理工具,您可能会发现配置管理工具和 Config Connector 之间存在冲突。例如,问题排查指南中阐述的 KNV2005 错误。这类问题的根本原因在于:

  1. Config Connector 将在规范的列表中填充并默认未指定值,spec.bars[0].br2 就是一个示例。
  2. 配置管理工具和 Config Connector 都将列表字段视为原子字段,因此添加的 spec.bars[0].br2 会被配置管理工具视为偏移,并将被移除以更正 drift

如需解决这些问题,您可以设置 cnrm.cloud.google.com/state-into-spec: absent,这样 Config Connector 就不会将未指定的字段 spec.bars[0].br2 添加到规范中。

解决 GET/PUT 对称性问题

GET/PUT 对称是指 REST API 中的一项设计原则。具体来说,这意味着当 GET 响应以 PUT 请求的形式发送到同一网址时,预期结果是 HTTP 200 OK 响应,而底层 REST 资源的状态不会发生变化。

资源规范中由 Config Connector 填充的未指定字段是 GET 请求的结果。这意味着在将来的协调中,Config Connector 可能会向底层 Google Cloud API 发送 PUT/PATCH 请求,并使用从 GET 请求获知的这些未指定字段值。这通常不是问题,但某些 Google Cloud API 可能会由于这些未指定的字段值而拒绝 PUT/PATCH 请求。在同一示例中,如果 API 实现违反 GET/PUT 对称原则,则使用值“bz2”填充的 spec.barz.bz2 可能会导致 HTTP 400 客户端错误或其他意外响应。

为避免出现此类问题,您可以对设置 cnrm.cloud.google.com/state-into-spec: absent 进行实验,并检查协调期间的错误是否会消失。

何时应避开cnrm.cloud.google.com/state-into-spec: absent

如果您的解决方案依赖于来自未指定字段的填充值,则应避免设置 cnrm.cloud.google.com/state-into-spec: absent。例如,如果您使用的是 ComputeAddress 资源,并且需要服务器生成的 spec.address 值(该值可能是原始 YAML 中的未指定字段),则您不应使用此注解,因为它会跳过将 spec.address 的值填充到 Kubernetes 资源规范中。

观察到的状态

如果您需要设置 cnrm.cloud.google.com/state-into-spec: absent,但您的解决方案依赖于来自未指定字段的填充值,请检查这些字段是否存在于 CRD 架构中的 status.observedState 下。如果它们显示在 status.observedState 下,您可以设置 cnrm.cloud.google.com/state-into-spec: absent,并且在成功协调后,仍然可以访问未指定字段的值。

status.observedState 字段包含 Config Connector 在上次成功协调中观察到的选定资源字段的实时状态。如果观察字段是常见用例的依赖项,并且是计算的 spec 字段,则系统会选择这些字段。您可以在 CRD 架构中找到观测到的字段。

如果您找不到所需的观察字段,请检查是否存在现有问题,或在公开的问题跟踪器中创建新问题。