このページでは、クラスタへの構成ファイルの同期に関する問題を解決する方法について説明します。
KNV 2009 エラーのトラブルシューティング
KNV2009
エラーは、Config Sync が一部の構成ファイルをクラスタに同期できなかったことを示します。以下の各セクションでは、最も一般的な原因のいくつかとそれらの解決方法について説明します。
特定のリソースへのオペレーションが禁止される
RepoSync
オブジェクトに RBAC を付与する必要があるため、リソースを適用するために必要な権限が欠落している可能性があります。
権限が欠落していることは、RepoSync
リソースのステータスを取得することで確認できます。
kubectl get reposync repo-sync -n NAMESPACE -o yaml
NAMESPACE
は、Namespace リポジトリを作成した Namespace に置き換えます。
また、nomos status
コマンドの使用も可能です。
ステータスに次のメッセージが確認される場合は、NAMESPACE
の調整ツールに、リソースを適用するために必要な権限がないことを意味します。
KNV2009: deployments.apps "nginx-deployment" is forbidden: User "system:serviceaccount:config-management-system:ns-reconciler-default" cannot get resource "deployments" in API group "apps" in the namespace "default"
この問題を解決するには、対象の Namespace でエラーが発生したリソースを管理するための Reconciler 権限をサービス アカウントに付与する RoleBinding 構成を宣言する必要があります。RoleBinding を追加する方法について詳しくは、複数のリポジトリからの同期の構成をご覧ください。
この問題は、spec.override.roleRefs
を使用して RootSync
オブジェクトに付与されたロールを変更した場合、RootSync オブジェクトにも影響する可能性があります。このフィールドを設定していない場合、RootSync
オブジェクトにはデフォルトで cluster-admin
ロールが付与されます。
ResourceGroup オブジェクトが etcd
オブジェクトのサイズ上限を超えている
Reconciler がクラスタに構成を適用しようとしたときに、次のエラーが表示された場合は、ResourceGroup オブジェクトが etcd
オブジェクトのサイズ上限を超えています。
KNV2009: too many declared resources causing ResourceGroup.kpt.dev, config-management-system/root-sync failed to be applied: task failed (action: "Inventory", name: "inventory-add-0"): Request entity too large: limit is 3145728. To fix, split the resources into multiple repositories.
Git リポジトリを複数のリポジトリに分割することをおすすめします。オブジェクトのサイズがすでに過剰に大きく変更が保持されていないため、Git リポジトリを分割できない場合は、RootSync
または RepoSync
を構成することでこれを軽減し、ResourceGroup へのオブジェクト ステータスの書き込みを一時的に無効できます。これを行うには、RootSync
オブジェクトまたは RepoSync オブジェクトの .spec.override.statusMode
フィールドを disabled
に設定します。これにより、Config Sync は ResourceGroup オブジェクトのマネージド リソース ステータスの更新を停止します。この操作を行うと、ResourceGroup オブジェクトのサイズが縮小されます。ただし、マネージド リソースのステータスを nomos status
または gcloud alpha anthos config sync
から見ることはできなくなります。
RootSync
または RepoSync
オブジェクトからのエラーがまったく見られない場合は、信頼できる情報源からのオブジェクトがクラスタに同期されています。ResourceGroup リソースが etcd
オブジェクトのサイズ上限を超えているかどうかを確認するには、ResourceGroup リソースのステータスと ResourceGroup コントローラのログの両方を確認します。
ResourceGroup のステータスを確認します。
RootSync
オブジェクトを確認するには、次のコマンドを実行します。kubectl get resourcegroup root-sync -n config-management-system
RepoSync
オブジェクトを確認するには、次のコマンドを実行します。kubectl get resourcegroup repo-sync -n NAMESPACE
NAMESPACE
は、Namespace リポジトリを作成した Namespace に置き換えます。
出力は次のようになります。
NAME RECONCILING STALLED AGE root-sync True False 35m
RECONCILING
列の値がTrue
の場合は、ResourceGroup リソースが引き続き調整中であることを表しています。ResourceGroup コントローラのログを確認します。
kubectl logs deployment resource-group-controller-manager -c manager -n resource-group-system
出力に次の例のようなエラーが表示される場合は、ResourceGroup リソースのサイズが過剰に大きく、
etcd
オブジェクトのサイズ上限を超えています。"error":"etcdserver: request is too large"
ResourceGroup が大きくなりすぎることを防ぐには、Git リポジトリ内のリソース数を減らします。1 つのルート リポジトリを複数のルート リポジトリに分割できます。
依存関係適用の調整タイムアウト
依存関係を持つオブジェクトを同期している場合は、Reconciler が config.kubernetes.io/depends-on
アノテーションを持つオブジェクトをクラスタに適用しようとすると、次の例のようなエラーが表示される可能性があります。
KNV2009: skipped apply of Pod, bookstore/pod4: dependency apply reconcile timeout: bookstore_pod3__Pod For more information, see https://g.co/cloud/acm-errors#knv2009
このエラーは、依存関係オブジェクトがデフォルトの調整タイムアウト(5 分)内に調整されなかったことを表します。config.kubernetes.io/depends-on
アノテーションを使用すると、Config Sync は必要な順序でのみオブジェクトを適用するため、Config Sync は依存関係のあるオブジェクトを適用できません。デフォルトの調整タイムアウトを長く設定するには、spec.override.reconcileTimeout
を設定します。
最初の同期の試行が完了した後に依存関係が調整される可能性もあります。この場合は、次の同期の再試行で依存関係が調整済みとして検出され、依存関係の適用がブロックされなくなります。この状態になると、エラーが短時間の間報告され、削除される場合があります。調整タイムアウト期間を長くすると、エラーが断続的に報告されるのを回避できる可能性があります。
インベントリ情報が nil
Reconciler がクラスタに構成を適用しようとしたときに次のエラーが発生した場合は、インベントリにリソースがないか、マニフェストに非マネージドのアノテーションがあることが考えられます。
KNV2009: inventory info is nil\n\nFor more information, see https://g.co/cloud/acm-errors#knv2009
この問題を解決するには、次のことを試してください。
- 1 つ以上のリソースが Config Sync によって管理されるようにすることによって、すべてのリソースに
configmanagement.gke.io/managed: disabled
アノテーションが付加されている同期の設定を回避します。 configmanagement.gke.io/managed: disabled
アノテーションなしでリソースの初期同期を完了した後に限り、このアノテーションを追加するようにします。
複数のインベントリ オブジェクト テンプレート
Reconciler がクラスタに構成を適用しようとしたときに次のエラーが表示された場合は、信頼できる情報源(例: Git リポジトリ)に kpt のインベントリ構成が存在する可能性があります。
KNV2009: Package has multiple inventory object templates. The package should have one and only one inventory object template. For more information, see https://g.co/cloud/acm-errors#knv2009
この問題は、Config Sync が独自のインベントリ構成を管理するために発生します。この問題を解決するには、信頼できる情報源にあるインベントリ構成を削除します。
変更不可のフィールドを変更できない
信頼できる情報源の値を変更しても、構成ファイル内の変更不可フィールドを変更することはできません。この種の変更を試みると、次のようなエラーが発生します。
KNV2009: failed to apply RESOURCE: admission webhook "deny-immutable-field-updates.cnrm.cloud.google.com" denied the request: cannot make changes to immutable field(s):
変更不可フィールドを更新する必要がある場合は、クラスタ内のオブジェクトを手動で削除します。Config Sync は、新しいフィールド値を使用してオブジェクトを再作成します。
API の検出に失敗した
次のようなエラー メッセージが表示される場合は、API 検出エラーが発生している可能性があります。
KNV2002: API discovery failed: APIServer error: unable to retrieve the complete list of server APIs: external.metrics.k8s.io/v1beta1: received empty response for: external.metrics.k8s.io/v1beta1
Config Sync は、Kubernetes API ディスカバリを使用して、クラスタでサポートされているリソースを検索します。これにより、Config Sync はソースで指定されたリソースタイプを検証し、クラスタでのそれらのリソースの変更を監視できます。
バージョン 1.28 より前の Kubernetes では、APIService バックエンドが正常でないか、空のリスト結果を返すと、API 検出が失敗し、Config Sync とその他の複数の Kubernetes コンポーネントでエラーが発生していました。多くの一般的な APIService バックエンドは、高可用性ではないため、バックエンドを更新する、または別のノードに再スケジュールするだけで、比較的頻繁にこのような問題が発生する可能性があります。
単一のレプリカを持つ APIService バックエンドの例には、metrics-server
と custom-metrics-stackdriver-adapter
があります。一部の APIService バックエンドは、常に空のリスト結果(custom-metrics-stackdriver-adapter
など)を返します。API 検出に失敗する別の一般的な原因は、異常な状態の Webhook です。
バージョン 1.28 より後の Kubernetes では、集約検出機能を有効にして、異常な APIService バックエンドによって未処理のエラーが発生しなくなりました。対象の APIService によって処理されるリソース グループにはリソースがないことが示されています。これにより、ソースで異常なリソースが指定されていない限り、同期が継続されます。
自己回復の遅延
自己修復は、マネージド リソースを監視して、信頼できる情報源からのドリフトを検出し、検出したドリフトを元に戻します。
同期を試行している間は、自己回復が一時停止されます。この動作により、特に Reconciler の完了を妨げる同期エラーが発生した場合に、自己回復が遅延する可能性があります。自己回復を再度有効にするには、報告された同期エラーをすべて修正します。
Kubernetes API リクエストの数が多い
Config Sync は、マルチ インスタンス化戦略を使用して、テナント ドメインと障害ドメインをスケーリングして分離します。このため、RootSync
と RepoSync
はそれぞれ独自の Reconciler インスタンスを取得します。各 Reconciler インスタンスは、ソースに変更が加えられたたびに同期するだけでなく、自己修復動作の一環として定期的に同期し、アクティブなドリフト修復で検出できなかった変更を元に戻します。RootSync
オブジェクトまたは RepoSync
オブジェクトを追加すると、Kubernetes にリソースを同期する Reconciler によって行われる API リクエストの数が増加します。そのため、RootSync
オブジェクトと RepoSync
オブジェクトが多数あると、Kubernetes API に多大なトラフィック負荷が発生する可能性があります。
Config Sync は、同期を実行するためにサーバーサイドの適用を使用します。これにより、通常の GET リクエストと PATCH リクエストのフローが単一の PATCH リクエストに置き換えられ、API 呼び出しの合計数は減少しますが、PATCH 呼び出しの回数は増加します。これにより、ソースのリソース グループのバージョンがクラスタのデフォルトのリソース グループのバージョンと一致しない場合でも、変更が正しく行われます。ただし、ソースに変更や目的の状態からのドリフトが生じていない場合でも、監査ログに PATCH リクエストが表示される可能性があります。これは正常ですが、驚くべき状態であると思われるかもしれません。
同期でエラーが発生した場合は、成功するまで再試行されます。ただし、この操作に人の介入が必要な場合は、Config Sync でエラーが発生し、しばらく再試行が行われるため、Kubernetes API に対するリクエストの量が増加する可能性があります。再試行は指数関数的にバックオフしますが、多くの RootSync
オブジェクトまたは RepoSync
オブジェクトが同時に同期に失敗すると、Kubernetes API に多大なトラフィック負荷が発生する可能性があります。
これらの問題を軽減するには、次のいずれかの方法をお試しください。
- 構成エラーを速やかに修正して、蓄積しないようにします。
- 複数の
RootSync
オブジェクトまたはRepoSync
オブジェクトを組み合わせて、Kubernetes API リクエストを行う Reconciler の数を削減します。
ファイナライザによって KubeVirt のアンインストールがブロックされる
KubeVirt は複数のファイナライザを使用する Kubernetes パッケージであり、クリーンアップを容易にするために、正確な削除順序が必要です。KubeVirt オブジェクトが間違った順序で削除されると、他の KubeVirt オブジェクトの削除が停止する、または無期限に応答しなくなる可能性があります。
KubeVirt のアンインストールを試みてブロックされた場合は、手動で KubeVirt を削除する手順を行います。
この問題を将来にわたって軽減するには、リソース オブジェクト間の依存関係を宣言して、依存関係の逆の順序で削除されるようにします。
ファイナライザによってオブジェクトの削除がブロックされる
Kubernetes ファイナライザは、特定のコントローラがクリーンアップを実行するまでオブジェクトを削除しないように Kubernetes に指示するメタデータ エントリです。クリーンアップの条件が満たされていない場合、または対象リソースのクリーンアップを実行するコントローラが異常な状態であるか削除されている場合は、同期または調整が失敗する可能性があります。
この問題を軽減するには、引き続き最終処理が行われているリソースと、クリーンアップを行うコントローラを特定します。
コントローラが正常でない場合は、根本原因を修正することでリソースのクリーンアップが完了し、オブジェクトの削除がブロックされなくなります。
コントローラが正常な場合、コントローラは削除されるオブジェクトにステータス条件を適用して、クリーンアップが停止した理由を説明している必要があります。説明していない場合は、コントローラのログで根本原因の兆候を確認します。
多くの場合にオブジェクトの削除が停止していることは、オブジェクトが間違った順序で削除されたことを示します。今後このような問題が発生しないようにするには、リソース オブジェクト間の依存関係を宣言して、依存関係の逆順で削除されるようにします。
ResourceGroup フィールドが変わり続ける
同期が試行されると、インベントリが更新され、リソースのステータスが「保留」に変わります。同期に失敗すると、インベントリが更新され、リソースのステータスが「失敗」に変わります。同期が失敗した後に再試行されると、このパターンが繰り返され、インベントリが定期的に更新されます。これにより、ResourceGroup resourceVersion
は更新のたびに増加し、同期ステータスが前後に切り替わります。これは正常ですが、驚くべき状態であると思われるかもしれません。
同期エラーは、いくつかの問題が原因で発生する可能性があります。最も一般的な原因の一つは、ソースで指定されたリソースを管理するための権限が不足していることです。このエラーを修正するには、適切な RoleBinding または ClusterRoleBinding を追加して、同期に失敗したリソースを管理するための権限を RepoSync
または RootSync
Reconciler に付与します。
サーバーサイドの適用では、ソースで指定されていないフィールドを削除または元に戻すことができない
Config Sync は、サーバーサイドの適用を使用して、ソースから Kubernetes にマニフェストを適用します。これは、他のコントローラが metadata
フィールドと spec
フィールドを管理できるようにするために必要です。これの一例が、Deployment のレプリカ数を更新する HorizontalPodAutoscaler です。そのため、Config Sync はソース マニフェストで指定されたフィールドのみを管理します。これにより、既存のリソース オブジェクトを採用する際に、ソースで指定されていないフィールドが変更されないという副作用が発生します。このため、マージされた構成が無効または不正確になることがあります。
リソースの採用時にこの問題を回避するには、最初に採用するときにソースでまったく同じフィールドを使用し、同期後にソースのフィールドを変更します。これにより、Config Sync は以前に適用したフィールドを正しく削除し、ソースの新しいフィールドに置き換えます。この問題を回避するもう一つの方法は、最初にクラスタからリソースを削除し、Config Sync で新しいバージョンを適用できるようにすることです。
次のステップ
- まだ問題が解決しない場合は、既知の問題かどうかを確認してください。