排查将配置同步到集群的相关问题

本页面介绍如何解决将配置同步到集群的相关问题。

排查 KNV 2009 错误

KNV2009 错误表明 Config Sync 未能将部分配置同步到集群。以下部分介绍了一些最常见的原因以及解决方法。

禁止对某些资源执行操作

由于您需要向 RepoSync 对象授予其 RBAC,因此可能缺少应用资源所需的权限。

您可以通过获取 RepoSync 资源状态来验证是否缺少这些权限:

kubectl get reposync repo-sync -n NAMESPACE -o yaml

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"

如需解决此问题,您需要声明一个 RoleBinding 配置,向协调器的服务账号授予管理该命名空间中失败资源的权限。如需详细了解如何添加 RoleBinding,请参阅配置从多个代码库同步

如果您使用 spec.override.roleRefs 更改了向 RootSync 对象授予的角色,则此问题可能还会影响 RootSync 对象。如果您未设置此字段,则系统在默认情况下会向 RootSync 对象授予 cluster-admin 角色。

ResourceGroup 对象超过 etcd 对象大小限制

如果在协调器尝试将配置应用于集群时收到以下错误,则表示 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 代码库,因为对象已经太大并且更改没有保留,那么可以通过以下方式缓解问题:将 RootSyncRepoSync 配置为暂时停用将对象状态写入 ResourceGroup 的功能。为此,您可以将 RootSync 或 RepoSync 对象的 .spec.override.statusMode 字段设置为 disabled。这样,Config Sync 便会停止更新 ResourceGroup 对象中的代管资源状态;此操作可减小 ResourceGroup 对象的大小。但是,无法从 nomos statusgcloud alpha anthos config sync 查看托管式资源的状态。

如果您没有看到来自 RootSyncRepoSync 对象的任何错误,则表示可靠来源中的对象已同步到集群。如需检查 ResourceGroup 资源是否超过 etcd 对象大小限制,请检查 ResourceGroup 资源状态以及 ResourceGroup 控制器的日志:

  1. 检查 ResourceGroup 状态:

    • 如需检查 RootSync 对象,请运行以下命令:

      kubectl get resourcegroup root-sync -n config-management-system
      
    • 如需检查 RepoSync 对象,请运行以下命令:

      kubectl get resourcegroup repo-sync -n NAMESPACE
      

      NAMESPACE 替换为在其中创建了命名空间代码库的命名空间。

    输出类似于以下示例:

    NAME        RECONCILING   STALLED   AGE
    root-sync   True          False     35m
    

    如果 RECONCILING 列中的值为 True,则意味着 ResourceGroup 资源仍在协调。

  2. 检查 ResourceGroup 控制器的日志:

    kubectl logs deployment resource-group-controller-manager -c manager -n resource-group-system
    

    如果您在输出中看到类似于以下示例的错误,则表示 ResourceGroup 资源太大,超过 etcd 对象大小限制:

    "error":"etcdserver: request is too large"
    

如需防止 ResourceGroup 过大,请减少 Git 代码库中的资源数量。您可以将一个根代码库拆分为多个根代码库

依赖项应用协调超时

如果您将对象与依赖项同步,那么在协调器尝试将具有 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

此错误表示依赖项对象在默认的协调超时(五分钟)内未进行协调。Config Sync 无法应用依赖项对象,因为使用 config.kubernetes.io/depends-on 注解时,Config Sync 只能按所需的顺序应用对象。您可以通过设置 spec.override.reconcileTimeout 将默认协调超时替换为更长的时间。

依赖项也可能在初始同步尝试完成后进行协调。在这种情况下,系统应在下次尝试同步重试时将依赖项检测为已协调,从而取消阻止任何依赖项的应用。发生这种情况时,系统可能会短暂报告错误,然后将其移除。延长协调超时可能有助于避免间歇性报告错误。

库存信息为 nil

如果您在协调器尝试将配置应用于集群时收到以下错误,则说明您的库存可能没有资源,或者清单具有非托管式注解

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 注解的同步。
  2. 请仅在完成不带 configmanagement.gke.io/managed: disabled 注解的资源的初始同步后才添加此注解。

多个清点对象模板

如果您在协调器尝试将配置应用于集群时收到以下错误,则说明在可靠来源(例如 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 便可以验证来源中指定的资源类型,并监控这些资源在集群中的更改。

在 Kubernetes 1.28 版之前,每当任何 APIService 后端健康状况不佳或返回空列表结果时,API 发现都会失败,从而导致 Config Sync 和多个其他 Kubernetes 组件出错。许多常见的 APIService 后端都不具有高可用性,因此只需更新后端或将其重新安排到其他节点上,便可能会比较频繁地发生这种情况。

具有单个副本的 APIService 后端示例包括 metrics-servercustom-metrics-stackdriver-adapter。某些 APIService 后端始终返回空列表结果,例如 custom-metrics-stackdriver-adapter。API 发现失败的另一个常见原因是 webhook 健康状况不佳。

在 Kubernetes 1.28 版之后,如果启用了聚合发现功能,则健康状况不佳的 APIService 后端不会再导致未处理的错误。而是该 APIService 处理的资源组会显示为没有资源。这样,只要来源中未指定健康状况不佳的资源,同步操作便会继续进行。

延迟自我修复

自我修复功能会监控托管式资源,以及检测与可靠来源之间的偏移并还原该偏移。

在尝试同步期间,系统会暂停自我修复。这种行为意味着自我修复可能会延迟,尤其是在存在阻碍协调器完成的同步错误时。如需重新启用自我修复,请修复已报告的所有同步错误。

大量 Kubernetes API 请求

Config Sync 使用多实例策略来扩缩和隔离租户和故障网域。因此,每个 RootSyncRepoSync 都会获得自己的协调器实例。除了在每次对来源进行更改时同步之外,每个协调器实例还会定期同步以作为其自我修复行为的一部分,从而还原主动偏移修复遗漏的任何更改。添加 RootSyncRepoSync 对象时,此操作会导致将资源同步到 Kubernetes 的协调器所发出的 API 请求数量线性增加。因此,如果您有许多 RootSyncRepoSync 对象,这有时可能会导致 Kubernetes API 上产生大量流量负载。

为了执行同步,Config Sync 使用服务器端应用。这会将正常的 GET 和 PATCH 请求流程替换为单个 PATCH 请求,从而减少 API 调用总数,但会增加 PATCH 调用数量。这样可以确保所做的更改正确无误,即使来源中的资源组版本与集群上的默认资源组版本不匹配也是如此。但是,即使未对来源进行任何更改或是与所需状态没有任何偏移,您也可能会在审核日志中看到 PATCH 请求。这是正常现象,但可能让人感到意外。

同步出错时,系统会重试,直到成功为止。但是,如果这需要人工操作,Config Sync 可能会出错并在一段时间内重试,从而增加对 Kubernetes API 发出的请求数量。重试会以指数方式退避,但如果许多 RootSyncRepoSync 对象未能同时同步,这可能会导致 Kubernetes API 上产生大量流量负载。

如需缓解这些问题,请尝试以下方法之一:

  • 快速修复配置错误,避免错误堆积。
  • 组合多个 RootSyncRepoSync 对象,以减少发出 Kubernetes API 请求的协调器的数量。

KubeVirt 卸载被终结器阻止

KubeVirt 是一种使用多个终结器的 Kubernetes 软件包,需要精确的删除顺序来协助清理。如果 KubeVirt 对象以错误顺序删除,则其他 KubeVirt 对象的删除可能会无限期地停滞或停止响应。

如果您尝试卸载 KubeVirt,但操作被阻止,请按照手动删除 KubeVirt 的说明进行操作。

为了防止将来出现此问题,请声明资源对象之间的依赖项,以确保按相反依赖项顺序删除它们。

对象删除被终结器阻止

Kubernetes 终结器是元数据条目,指示 Kubernetes 在特定控制器执行清理之前不允许移除对象。如果未满足清理条件,或者为该资源执行清理的控制器健康状况不佳或已被删除,这可能会导致同步或协调失败。

如需缓解此问题,请确定哪个资源仍在进行终结,以及哪个控制器应执行清理。

如果相应控制器健康状况不佳,则修复根本原因应允许完成资源清理,从而取消阻止对象移除。

如果相应控制器健康状况良好,则控制器应该已向要删除的对象应用了状态条件,以说明清理停滞的原因。否则,请检查控制器日志以了解有关根本原因的指示。

通常,对象在删除时遇到问题表明对象的删除顺序不正确。为了防止将来出现此类问题,请声明资源对象之间的依赖项,以确保按相反依赖项顺序删除它们。

ResourceGroup 字段不断变化

尝试同步时,库存会更新以将资源状态更改为待处理。同步失败时,库存会更新以将资源状态更改为失败。在失败后重试同步时,此模式会重复,从而导致库存定期更新。这会导致 ResourceGroup resourceVersion 随着每次更新而增加,并且同步状态会来回翻转。这是正常现象,但可能让人感到意外。

同步失败可能由多种问题导致。最常见的一种是权限不足,无法管理来源中指定的资源。如需修复此错误,请添加相应的 RoleBinding 或 ClusterRoleBinding,以向 RepoSyncRootSync 协调器授予管理未能同步的资源的权限。

服务器端应用未移除或还原来源中未指定的字段

Config Sync 使用服务器端应用将来源中的清单应用于 Kubernetes。这对于允许其他控制器管理 metadataspec 字段而言是必需的。这方面的一个例子是 Pod 横向自动扩缩器,它会更新 Deployment 中的副本数量。因此,Config Sync 仅管理来源清单中指定的字段。其副作用是,在采用现有资源对象时,来源中未指定的任何字段都不会更改,这有时可能会导致合并配置无效或不正确。

如需避免在采用资源时出现此问题,请在最初采用时使用来源中完全相同的字段,然后在同步后更改来源中的字段,以便 Config Sync 正确移除之前所应用的字段并将其替换为来源中的新字段。 避免此问题的另一种方法是先从集群中删除资源,让 Config Sync 可以应用新版本。

后续步骤

  • 如果您仍然遇到问题,请检查您的问题是否为已知问题