
API网关云原生微服务【免费下载链接】kgatewayThe Cloud-Native API Gateway and AI Gateway项目地址https://gitcode.com/gh_mirrors/kg/kgateway点击查看免费下载kgatewayThe Cloud-Native API Gateway and AI Gateway的策略 CR 基于 Kubernetes Gateway API 的gwv1.PolicyStatus上报状态。但由于策略的挂载attachment机制涉及按优先级应用、合并以及被更高优先级策略覆盖等复杂语义仅仅一个笼统的状态无法区分策略已被接受和策略已实际生效。本文围绕设计文档 design/11741-policy-status-and-merge-reporting.md系统讲解 kgateway 如何通过Accepted与Attached两个自定义 Condition 分离上报策略的接受与挂载状态并在下发的 Envoy 配置中以MergeOrigins元数据记录每个合并字段的来源策略为策略合并结果提供可观测性。读完本文你将掌握 kgateway 策略状态字段的完整语义、三种挂载状态的判定规则与优先级顺序以及如何从 Kubernetes status 与 Envoy 配置中诊断已接受但未生效的策略问题。背景为什么需要区分接受与挂载kgateway 的各类策略 CR如 TrafficPolicy、ListenerPolicy、BackendConfigPolicy、DirectResponse 等都使用gwv1.PolicyStatusAPI 作为状态载体。在 api/v1alpha1/shared/shared_types.go 中可以看到PolicyStatus由Conditions条件列表最多 8 条与Ancestors祖先状态条目最多 16 个组成type PolicyStatus struct { // optional // listTypemap // listMapKeytype // kubebuilder:validation:MaxItems8 Conditions []metav1.Condition json:conditions,omitempty // kubebuilder:validation:MaxItems16 // required Ancestors []PolicyAncestorStatus json:ancestors }PolicyAncestorStatus通过AncestorRef对应 spec 中的 ParentRef、ControllerName写状态的控制器的域名/路径标识与Conditions描述策略相对于某个祖先的状态。设计文档指出旧版状态 API 存在一个根本性局限它无法区分策略被接受与策略被挂载。策略挂载是一个复杂过程多个策略可能以优先级顺序依次应用到同一目标资源支持合并的策略如 TrafficPolicy会与其他策略做合并最终挂载到目标资源上的可能是多个策略合并后的结果优先级较低策略中的部分或全部字段在最终挂载结果中可能被更高优先级策略覆盖。这会导致一个令人困惑的场景策略被接受Accepted了但由于与其他策略冲突而没有被实际挂载。只有Accepted而没有Attached维度的状态会让用户看到策略一切正常实际上配置却完全没有生效。设计目标与非目标目标使用自定义 Condition 分别上报策略的接受状态acceptance与挂载状态attachment。使用AttachedCondition 汇总挂载信息。在下发的 Envoy 配置上增加MergeOrigins元数据作为诊断用途。非目标不在状态 API 中暴露细粒度或高基数high cardinality的数据。不针对策略 CR 上无法解析的targetRefs上报状态。核心实现策略状态条件类型与原因在 api/v1alpha1/shared/policy_types.go 中定义了完整的条件类型与原因常量这是整个状态报告体系的类型基础const ( // PolicyConditionAccepted 表示策略是否被系统接受或被拒绝以及原因。 // 该条件为 True 的可能原因* Valid // 该条件为 False 的可能原因* Pending、* Invalid、* TargetNotFound PolicyConditionAccepted PolicyConditionType Accepted // PolicyConditionAttached 表示策略是否已挂载到目标资源。 // 该条件为 True 的可能原因* Attached、* Merged // 该条件为 False 的可能原因* Pending、* Overridden、* TargetNotFound PolicyConditionAttached PolicyConditionType Attached PolicyReasonValid PolicyConditionReason Valid PolicyReasonInvalid PolicyConditionReason Invalid PolicyReasonAttached PolicyConditionReason Attached PolicyReasonMerged PolicyConditionReason Merged PolicyReasonOverridden PolicyConditionReason Overridden PolicyReasonPending PolicyConditionReason Pending PolicyReasonPartiallyValid PolicyConditionReason PartiallyValid PolicyReasonTargetNotFound PolicyConditionReason TargetNotFound )两类条件的分工如下Accepted策略是否被系统接受。True表示有效ValidFalse表示无效Invalid、待处理Pending或目标不存在TargetNotFound。Attached策略是否真正挂载到目标资源。True的可能原因是Attached完全挂载或Merged合并后挂载False的原因则是Pending、Overridden被更高优先级策略完全覆盖或TargetNotFound。注意TargetNotFound的语义当策略的targetRefs指向不存在的资源时由于缺失的目标没有 Gateway 祖先可供上报条件会被上报到策略的合成StatusSummary祖先条目上见下文状态写入路径。挂载状态的判定Attached / Merged / Overridden设计文档给出了Attached条件的三态语义status: True, reason: Attached策略挂载到了全部目标且未与其他策略合并status: True, reason: Merged策略挂载到了全部目标但在一个或多个目标上与其他策略发生了合并status: False, reason: Overridden策略在一个或多个目标上被更高优先级策略覆盖。由于一个策略可以挂载多个目标且每个目标上的挂载状态可能不同同一个策略可能同时处于多种状态。Attached条件在聚合时遵循严重程度优先级OverriddenMergedAttached即策略同时存在多个关联状态时以最严重者为准。源码实现PolicyAttachmentState 位掩码在 pkg/pluginsdk/reporter/types.go 中挂载状态被建模为一个可按位组合的枚举type PolicyAttachmentState int const ( // PolicyAttachmentStatePending 表示策略挂载处于待处理状态 PolicyAttachmentStatePending PolicyAttachmentState iota // PolicyAttachmentStateAttached 表示整个策略被成功挂载 PolicyAttachmentStateAttached PolicyAttachmentState 1 iota // PolicyAttachmentStateMerged 表示策略与其他策略合并后被挂载 PolicyAttachmentStateMerged // PolicyAttachmentStateOverridden 表示策略与更高优先级策略冲突并被完全覆盖 PolicyAttachmentStateOverridden ) // Has 检查现有状态是否包含给定状态 func (a PolicyAttachmentState) Has(b PolicyAttachmentState) bool { return ab ! 0 }同一文件还定义了各状态对应的用户可见消息常量这些消息会直接出现在 status 条件中PolicyAcceptedMsg Policy accepted PolicyAttachedMsg Attached to all targets PolicyMergedMsg Merged with other policies in target(s) and attached PolicyOverriddenMsg Overridden due to conflict with higher priority policy in target(s) PolicyTargetNotFoundMsg Policy is not attached to targets that could not be resolved在 pkg/reports/policy.go 的addAttachmentCondition函数中实现了最严重状态优先的聚合逻辑依次检查Overridden、Merged、Attached命中即设置对应条件从而保证多个目标上不同状态的并集被收敛为一个最严重的Attached条件switch { case attachmentState.Has(reporter.PolicyAttachmentStateOverridden): // status: False, reason: Overridden meta.SetStatusCondition(existing, metav1.Condition{ Type: string(shared.PolicyConditionAttached), Status: metav1.ConditionFalse, Reason: string(shared.PolicyReasonOverridden), Message: reporter.PolicyOverriddenMsg, }) case attachmentState.Has(reporter.PolicyAttachmentStateMerged): // status: True, reason: Merged ... case attachmentState.Has(reporter.PolicyAttachmentStateAttached): // status: True, reason: Attached ... }状态写入路径从翻译到上报接受状态与挂载状态的报告在 pkg/kgateway/translator/irtranslator/policy.go 中两个核心函数分别负责两类状态reportPolicyAcceptanceStatus对每个关联 CR 的策略若存在Errors则上报AcceptedFalse, reasonInvalid消息为策略的错误格式化文本否则上报AcceptedTrue, reasonValid消息为Policy accepted。reportPolicyAttachmentStatus对无错误的策略根据mergeOrigins判断挂载状态若mergeOrigins.IsSet()为 false说明没有发生合并是直接挂载上报PolicyAttachmentStateAttached否则根据策略引用在MergeOrigins中的出现次数映射到OverriddenNone、MergedPartial、AttachedAll。在 pkg/kgateway/translator/irtranslator/gateway.go 的监听器插件执行路径中可以看到两者的串联调用reportPolicyAcceptanceStatus(reporter, l.PolicyAncestorRef, pols...) policies, mergeOrigins : mergePolicies(pass, pols) // ...应用插件... out.Metadata addMergeOriginsToFilterMetadata(gk, mergeOrigins, out.GetMetadata()) reportPolicyAttachmentStatus(reporter, l.PolicyAncestorRef, mergeOrigins, pols...)即在一次合并处理中先上报接受状态 → 执行策略合并得到mergeOrigins→ 应用插件产出 Envoy 配置 → 把MergeOrigins写入过滤器元数据 → 再上报挂载状态。状态汇总BuildPolicyStatuspkg/reports/policy.go 的BuildPolicyStatus负责把翻译过程中累积的 typed report 转为最终的gwv1.PolicyStatus为每个祖先条目合并Accepted默认值缺失时置为False/Pending、调用addAttachmentCondition追加Attached条件、保留旧条件以维持lastTransitionTime连续性并保留不由本报告器拥有的外来条件。未解析 targetRefs 的补充上报设计文档的非目标声明不报告未解析 targetRefs 的状态而仓库中的实现pkg/kgateway/proxy_syncer/policy_target_status.go将这类情况收敛为TargetNotFound条件正向遍历每个策略的显式targetRefs通过 krtKubernetes 运行时转换驱动的 informer 集合解析目标无法解析的引用上报到策略的合成StatusSummary祖先条目上AcceptedFalse/TargetNotFound而不是直接使用缺失引用本身作为祖先——后者会因引用不存在对象而浪费祖先配额。合成祖先的定义位于 pkg/pluginsdk/reporter/types.gofunc PolicyStatusSummaryAncestorRef() gwv1.ParentReference { return gwv1.ParentReference{ Group: new(gwv1.Group(kgateway.GroupName)), Kind: new(gwv1.Kind(PolicyStatusSummaryAncestorName)), Name: PolicyStatusSummaryAncestorName, } }合并来源追踪MergeOrigins数据结构与操作语义在 pkg/pluginsdk/ir/merge.go 中MergeOrigins被定义为策略字段名 → 贡献该字段的策略引用集合的映射并附带三个计数枚举// MergeOrigins maps policy field names to policy refs that contribute to it // during policy merging type MergeOrigins map[string]sets.Set[string] // MergeOriginsRefCount 用于追踪策略引用在 MergeOrigins 中的状态 type MergeOriginsRefCount int const ( // MergeOriginsRefCountNone 表示该引用未出现在任何字段的 MergeOrigins 中 MergeOriginsRefCountNone MergeOriginsRefCount iota // MergeOriginsRefCountPartial 表示该引用出现在部分非全部字段中 MergeOriginsRefCountPartial // MergeOriginsRefCountAll 表示该引用出现在全部字段中 MergeOriginsRefCountAll )MergeOrigins提供的操作与合并策略一一对应SetOne(field, ref, mergeOrigins)浅合并shallow merge场景使用——字段被覆盖后仅记录新的来源或当 ref 为 nil 时继承来源的MergeOrigins。Append(field, ref, mergeOrigins)深合并deep merge场景使用——字段值是多个策略拼接/并集的结果因此把来源引用追加到已有集合中。GetRefCount(ref)统计某策略引用出现在多少个字段中返回None/Partial/All这正是reportPolicyAttachmentStatus判定Overridden/Merged/Attached的依据。ToProtoStruct()把MergeOrigins转换为 Envoystructpb.Struct供写入过滤器元数据使用。策略引用的唯一 ID 由AttachedPolicyRef.ID()生成见 pkg/pluginsdk/ir/gw.go其格式为Group delimiter Kind delimiter Namespace delimiter Name并通过 intern 共享底层字符串以减少内存占用。各字段的实际合并调用以 pkg/kgateway/extensions2/plugins/trafficpolicy/merge.go 为例TrafficPolicy 的合并函数mergeExtProc、mergeExtAuth、mergeRustformation、mergeJwt、mergeCORS、mergeFaultInjection等约 25 个字段级合并器在合并每个字段时同步维护MergeOrigins深合并路径AugmentedDeepMerge/OverridableDeepMerge调用mergeOrigins.Append(extProc, p2Ref, p2MergeOrigins)等把参与合并的第二个策略追加为该字段的来源浅合并路径通过defaultMerge内部的mergeOrigins.SetOne(...)记录字段被哪个策略设置特殊场景如 buffer 与 HTTP upgrade 互斥冲突解决还会通过delete(mergeOrigins, buffer)移除被剔除字段的来源记录。写入 Envoy 元数据addMergeOriginsToFilterMetadata见 pkg/kgateway/translator/irtranslator/policy.go在合并结果非空时将MergeOrigins以merge.group/kind为 key 写入 EnvoyMetadata.FilterMetadataconst mergeMetadataKeyPrefix merge. func addMergeOriginsToFilterMetadata(gk schema.GroupKind, mergeOrigins ir.MergeOrigins, metadata *envoycorev3.Metadata) *envoycorev3.Metadata { if !mergeOrigins.IsSet() { return metadata } pb : mergeOrigins.ToProtoStruct() ... metadata.FilterMetadata[mergeMetadataKeyPrefixgk.String()] pb return metadata }这样下发的 Envoy 监听器配置中就带上了每个合并字段的来源策略信息供诊断工具分析某个字段最终来自哪个策略。设计文档明确表示将来工具可以利用该元数据深入洞察策略合并结果。状态示例解读以下三个示例均取自设计文档展示了三种典型场景下Gateway祖先条目的完整状态controllerName为kgateway.dev/kgateway。场景一策略成功挂载到全部目标status: ancestors: - ancestorRef: group: gateway.networking.k8s.io kind: Gateway name: test namespace: default conditions: - lastTransitionTime: 2025-07-24T18:06:29Z message: Policy accepted observedGeneration: 1 reason: Valid status: True type: Accepted - lastTransitionTime: 2025-07-24T18:06:29Z message: Attached to all targets observedGeneration: 1 reason: Attached status: True type: Attached controllerName: kgateway.dev/kgatewayAcceptedTrue/Valid表示策略有效AttachedTrue/Attached表示策略未经过合并、直接挂载到了所有目标。场景二策略与其他策略合并但部分挂载status: ancestors: - ancestorRef: group: gateway.networking.k8s.io kind: Gateway name: test namespace: default conditions: - lastTransitionTime: 2025-07-24T18:06:29Z message: Policy accepted observedGeneration: 1 reason: Valid status: True type: Accepted - lastTransitionTime: 2025-07-24T18:06:29Z message: Merged with other policies in target(s) and attached observedGeneration: 1 reason: Merged status: True type: Attached controllerName: kgateway.dev/kgatewayAttachedTrue/Merged说明策略已生效但其部分字段与更高优先级策略合并——消息Merged with other policies in target(s) and attached与 pkg/pluginsdk/reporter/types.go 中的PolicyMergedMsg完全一致。场景三策略被接受但未挂载status: ancestors: - ancestorRef: group: gateway.networking.k8s.io kind: Gateway name: test namespace: default conditions: - lastTransitionTime: 2025-07-24T18:06:29Z message: Policy accepted observedGeneration: 1 reason: Valid status: True type: Accepted - lastTransitionTime: 2025-07-24T18:06:29Z message: Overridden due to conflict with higher priority policy in target(s) observedGeneration: 1 reason: Overridden status: False type: Attached controllerName: kgateway.dev/kgateway这是设计文档最想解决的场景AcceptedTrue/Valid但AttachedFalse/Overridden。策略本身合法却在目标上被更高优先级策略完全覆盖用户一眼即可看出策略被接受了但没有生效而无需逐个比对策略优先级。状态如何落到 Kubernetes 对象上策略状态的最终写入由状态同步层完成。在 pkg/kgateway/proxy_syncer/status.go 中可以看到各来源的报告生成函数如GenerateBackendPolicyReport为挂载到 Backend 上的策略生成Accepted/Attached条件而 pkg/reports/policy.go 的MergePolicyReports负责跨贡献折叠报告当ReportMap中某策略已有报告时把src的祖先条目合并进去同一祖先在两边都出现时以src的条目替换。写入端的核心约束见 pkg/reports/policy.go 的注释是其他控制器拥有的祖先条目被有意保留祖先数量上限cap与仅替换我方条目逻辑放在写入路径statussync.MergePolicyAncestorStatuses执行该路径才能权威地读取 live 对象——这保证了多控制器共存时状态不被误删同时BuildPolicyStatus中的排序保证消费方如 golden-output 翻译测试拿到确定性输出。测试与验证设计文档的 Test Plan 要求通过单元测试、translator 测试与 e2e 测试验证策略 Status API。仓库中的对应测试覆盖包括pkg/reports/policy_test.go验证BuildPolicyStatus生成的Attached条件如AttachedTrue/Attached、消息Attached to all targets。pkg/pluginsdk/ir/merge_test.go覆盖MergeOrigins的Get、SetOne、Append、IsSet、GetRefCount等全部操作方法包括浅合并覆盖与深合并追加的来源记录行为。pkg/kgateway/proxy_syncer/policy_target_status_test.go 与 pkg/reports/observed_generation_test.go验证TargetNotFound上报、observedGeneration与状态纯度的行为。pkg/kgateway/extensions2/plugins/trafficpolicy/merge_test.go验证具体字段合并时MergeOrigins的记录是否符合预期。总结kgateway 通过将gwv1.PolicyStatus中的状态拆分为Accepted与Attached两个自定义 Condition彻底解决了策略被接受但未生效难以诊断的问题Accepted反映策略本身的合法性与目标可解析性Attached反映策略是否真正挂载到目标资源并通过Attached、Merged、Overridden三种原因按Overridden Merged Attached的严重程度聚合描述合并场景下的最终生效状态同时MergeOrigins作为元数据写入下发的 Envoy 配置记录了每个合并字段的来源策略为构建策略合并结果洞察类工具提供了数据基础。这套设计让运维人员可以用kubectl get policy -o yaml直接读取状态条件快速区分配置写错了AcceptedFalse与配置被覆盖了AcceptedTrue但AttachedFalse/Overridden显著提升了多策略叠加场景下的可观测性与排障效率。赞分享API网关云原生微服务【免费下载链接】kgatewayThe Cloud-Native API Gateway and AI Gateway项目地址https://gitcode.com/gh_mirrors/kg/kgateway点击查看免费下载相关推荐PDF ProcessingPDF Processing Quick start Extract text with pdfplumber: code example Advanced f人工智能AI 应用AI 技能/插件AI Agent金融科技ngxtop函数测试策略基于行为与基于状态的测试ngxtop函数测试策略基于行为与基于状态的测试 引言 在软件开发中测试是确保代码质量和可靠性的关键环节。对于ngxtop这样的实时Nginx服务器指标工具运维可观测性CLIReselect与GraphQL结合API数据的状态选择策略Reselect与GraphQL结合API数据的状态选择策略 你是否在React应用中遇到过这样的困境GraphQL获取的数据需要复杂处理后才能在UI展示状态管理上一篇Lobe Theme 布局模式深度解析双列视图与可调节画布比例下一篇5分钟快速上手BRV框架让Android列表开发效率提升300%创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考