未指定のフィールドを無視する


このドキュメントでは、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 という名前の 2 つのフィールドを仕様に指定できて、適用された YAML ファイルに foo のみが指定されているとします。

spec:
  foo: "foo"

YAML が正常に適用され、リソースが UpToDate になっている場合は、bar という名前の別のフィールドが Kubernetes リソースに表示されます。

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

Config Connector と Google Cloud APIs 間のやり取りは複雑であるため、デフォルトの動作を変更して、リソース仕様に未指定のフィールドを入力しないようにすることをおすすめします。

未指定のフィールドの仕様への入力をスキップする

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. アノテーション cnrm.cloud.google.com/deletion-policy: abandon を編集して既存の Kubernetes リソースに追加し、次の手順で削除しても、基盤となる Google Cloud リソースが削除されないようにします。

  2. Kubernetes クラスタからリソースを削除します。

  3. リソースの YAML にアノテーション cnrm.cloud.google.com/state-into-spec: absent を追加します。

  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 を修正するために削除されます。

これらの問題を解決するには、Config Connector が未指定のフィールド spec.bars[0].br2 を仕様に追加しないように、cnrm.cloud.google.com/state-into-spec: absent を設定します。

GET / PUT の対称性の問題を解決する

GET / PUT の対称性は、REST API の設計原則を示します。つまり、GET レスポンスが同じ URL の PUT リクエストとして送信された場合、HTTP 200 OK レスポンスが返されます。基盤となる REST リソースの状態は変更されません。

リソース仕様で Config Connector によって入力される未指定のフィールドは、GET リクエストの結果として発生します。つまり、今後の調整では、Config Connector が、GET リクエストから学習した未指定のフィールド値を使用して、PUT / PATCH リクエストを基盤となる Google Cloud API に送信するということです。通常、これは問題になりませんが、未指定のフィールド値が原因で、一部の Google Cloud APIs で 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 リソース仕様に入力しないので、このアノテーションは使用しないでください。