资讯动态

External Secrets Operator PushSecret Metadata 设计演进:从非结构化 JSON 到 Kubernetes 风格 apiVersion/kind/spec

发布时间:2026/9/18 16:25:49 来源:尧图企业网站定制
External Secrets Operator PushSecret Metadata 设计演进从非结构化 JSON 到 Kubernetes 风格 apiVersion/kind/spec【免费下载链接】external-secretsExternal Secrets Operator reads information from a third-party service like AWS Secrets Manager and automatically injects the values as Kubernetes Secrets.项目地址: https://gitcode.com/GitHub_Trending/ex/external-secrets本技术文章以 design/010-pushsecret-metadata.md 设计文档为骨架讲解 External Secrets OperatorESO中 PushSecret 向外部 Provider 传递任意元数据metadata的机制与演进方案。你将理解 metadata 字段的现有实现形态、为何必须引入 Kubernetes 风格的结构化包装apiVersion/kind/spec、该方案在各 Provider 中的具体配置写法以及源码中对应的解析与校验实现从而能在实际集群中正确编写和演进 PushSecret metadata。一、功能起源PushSecret 的任意元数据能力External Secrets Operator 的 PushSecret 资源负责把 Kubernetes Secret 推送到外部密钥服务。在早期设计中data数组中的每一条目都支持携带一段任意结构的 metadata随密钥一起传给 ProviderapiVersion: external-secrets.io/v1alpha1 kind: PushSecret metadata: name: pushsecret-example spec: # ... data: - match: secretKey: key1 remoteRef: remoteKey: test1 metadata: annotations: key1: value1 labels: key1: value1从类型定义看PushSecretData.Metadata被声明为*apiextensionsv1.JSON见 apis/externalsecrets/v1alpha1/pushsecret_types.go即任意 JSON/YAML内容可以是任何东西。这种放任自由的设计赋予了每个 Provider 自行解释 metadata 结构的灵活性但也埋下了后续演进困难的伏笔——这是本设计文档讨论的核心矛盾。二、现状盘点各 Provider 的 metadata 实现概览设计文档列出了三个典型 Provider 对 metadata 的既有约定AWS Parameter Store通过secretType声明参数类型如StringList。# AWS Parameter Store apiVersion: kubernetes.external-secrets.io/v1alpha1 kind: PushSecretMetadata spec: secretType: StringListGCP Secrets Manager直接使用扁平化的labels与annotations键值对。# GCP Secrets Manager labels: {} annotations: {}AWS Secrets Manager使用secretPushFormat控制推送格式。# AWS Secrets Manager secretPushFormat: ...这些约定互不兼容、结构各异且都没有版本标识。以当前仓库源码为例各 Provider 的 metadata spec 结构确实五花八门AWS Secrets Manager 的PushSecretMetadataSpec包含tags、description、secretPushFormat、kmsKeyId、resourcePolicy、replicationLocations等字段见 providers/v1/aws/secretsmanager/secretsmanager.goAWS Parameter Store 的PushSecretMetadataSpec则包含secretType、kmsKeyID、tier含type与policies、encodeAsDecoded、tags、description见 providers/v1/aws/parameterstore/parameterstore.goKubernetes Provider 的PushSecretMetadataSpec实现了targetMergePolicy、sourceMergePolicy、labels、annotations、remoteNamespace见 providers/v1/kubernetes/metadata.go。三、问题描述为什么非结构化 metadata 是隐患设计文档明确提出一个核心约束我们永远无法做出破坏性变更只能向现有结构追加内容。这为什么是问题无法修复历史错误一旦某个字段命名错误mis-nomer或结构设计不合理并被合并、发布由于没有版本标识ESO 无法针对不同时期的 metadata 结构做差异化解码——所有旧数据都必须按同一套逻辑解析。缺乏分支依据如果 metadata 中带有apiVersion字段控制器就能据此用不同方式解码 metadata并在代码分支中应用对应逻辑从而简化修复与大规模重构。社区协作的现实ESO 是社区驱动项目贡献者背景和经验层次差异很大解决方案的视角高度依赖贡献者与评审者。随着时间推移必然会出现需要跨 Provider 对齐 metadata 结构或命名的时刻——届时若没有版本机制对齐即破坏。四、提议方案Kubernetes 风格的结构化包装设计文档的提议是将非结构化 metadata 包装成一个 Kubernetes 风格alike的资源包含apiVersion、kind和spec三个顶层字段。这样每个 Provider 的 metadata 都拥有独立的 API 版本标识与类型名解码逻辑可以根据apiVersion分派。4.1 Kubernetes Provider 示例Kubernetes Provider 的 metadata 描述推送到远端 Secret 时本地 Secret 与目标 Secret 的 labels/annotations 如何合并通过sourceMergePolicy与targetMergePolicy控制合并方向与策略apiVersion: external-secrets.io/v1alpha1 kind: PushSecret metadata: name: pushsecret-example spec: # ... data: - match: secretKey: key1 remoteRef: remoteKey: test1 metadata: apiVersion: kubernetes.external-secrets.io/v1alpha1 kind: PushSecretMetadata spec: sourceMergePolicy: Merge targetMergePolicy: Merge labels: color: red annotations: yes: please在源码层面该设计已被实现runtime/esutils/metadata/metadata.go中定义了泛型结构PushSecretMetadata[T]其字段正是Kind、APIVersion和SpecT为各 Provider 自定义的 spec 类型并硬编码了常量APIVersion kubernetes.external-secrets.io/v1alpha1、Kind PushSecretMetadata见 runtime/esutils/metadata/metadata.go。解析函数ParseMetadataParameters[T]使用yaml.Unmarshal(..., yaml.DisallowUnknownFields)严格反序列化并校验传入的apiVersion与kind必须与常量完全一致否则报错见 runtime/esutils/metadata/metadata.go——这正是设计文档按 apiVersion 分派解码逻辑的落地形态。Kubernetes Provider 侧的合并语义也值得展开mergeSourceMetadata把本地 Secret 的 labels/annotations 与 push metadata 合并Merge时逐键覆盖、Replace时整体替换mergeTargetMetadata则把合并结果应用到远端 Secret支持Merge、Replace、Ignore三种策略Ignore用于只想推数据、不想触碰远端元数据的场景具体见 providers/v1/kubernetes/metadata.go。4.2 AWS Secrets Manager 示例AWS Secrets Manager 的 metadata 使用secretFormat控制推送格式例如二进制binary或字符串stringapiVersion: external-secrets.io/v1alpha1 kind: PushSecret metadata: name: pushsecret-example spec: # ... data: - match: secretKey: key1 remoteRef: remoteKey: test1 metadata: apiVersion: secretsmanager.aws.external-secrets.io/v1alpha1 kind: PushSecretMetadata spec: secretFormat: binary # string从源码看AWS Secrets Manager 在推送时通过constructMetadataWithDefaults解析 metadata 并填充默认值若secretPushFormat为空则默认取binary若取值既不是binary也不是string则直接报错invalid secret push format见 providers/v1/aws/secretsmanager/secretsmanager.go。此外它仍兼容旧的扁平化读取方式esutils.FetchValueFromMetadata(SecretPushFormatKey, psd.GetMetadata(), SecretPushFormatBinary)可直接从非结构化 JSON 中提取secretPushFormat字段见 providers/v1/aws/secretsmanager/secretsmanager.go。4.3 AWS Parameter Store 示例AWS Parameter Store 的 metadata 覆盖了参数类型、层级tier、KMS 加密与过期通知策略等完整能力apiVersion: external-secrets.io/v1alpha1 kind: PushSecret metadata: name: pushsecret-example spec: # ... data: - match: secretKey: key1 remoteRef: remoteKey: test1 metadata: apiVersion: parameterstore.aws.external-secrets.io/v1alpha1 kind: PushSecretMetadata spec: tier: Advanced type: StringList keyID: arn:... policies: - type: ExpirationNotification version: 1.0 attributes: before: 15 unit: Days对应源码中Parameter Store 的PushSecretMetadataSpec里的Tier结构恰好包含typessmTypes.ParameterTier与policies*apiextensionsv1.JSON两个子字段见 providers/v1/aws/parameterstore/parameterstore.go与设计示例一一对应。4.4 方案利弊设计文档对该方案给出的评估PROS优点对 Kubernetes 用户是熟悉的结构其他项目已采用该模式可以复用现有工具链例如用于结构校验和文档生成。CONS缺点可能让用户困惑于嵌套的自定义资源存在一定的样板代码boilerplate需要消化。五、与既有实现的兼容策略v1alpha1 保留v1beta1 移除针对现有实现怎么办的问题设计文档给出了明确的分阶段处理路径v1alpha1阶段保留旧的非结构化 metadata 作为向后兼容措施文档层面立即从文档中移除旧写法的示例只文档化新的apiVersion/kind/spec方案旧方案仍可通过文档的版本切换version switch访问从而缓慢引导用户迁移到新方案v1beta1发布时随 PushSecretv1beta1一起考虑移除旧 API。这一策略与我们只能追加、不能破坏的总原则完全一致先用版本标识让新旧结构共存再在合适的里程碑完成切换。当前仓库的 metadata 泛型工具与 Provider 侧的解析实现均位于v1alpha1路径下如 runtime/esutils/metadata/metadata.go与设计文档的阶段划分吻合。六、备选方案最小化的 version 字段设计文档还记录了一个最小可行的替代思路不引入kind与apiVersion两个字段只增加一个version字段作为 spec 结构的解码提示。从技术上讲这已足以满足上述需求apiVersion: external-secrets.io/v1alpha1 kind: PushSecret metadata: name: pushsecret-example spec: # ... data: - match: secretKey: key1 remoteRef: remoteKey: test1 metadata: version: kubernetes/v1alpha1 spec: sourceMergePolicy: Merge targetMergePolicy: Merge labels: color: red annotations: yes: pleasePROS优点更简洁样板代码更少。CONS缺点无法直接复用现有工具链如 CRD 校验、文档生成。设计文档最终倾向于完整的 Kubernetes 风格包装方案核心考量正是复用现有工具链带来的长期收益大于样板代码的短期成本。七、当前仓库中的落地形态与使用提示尽管 010 号设计文档标注为 draft草稿其核心思想已在当前仓库中落地为可用的基础设施通用解析层runtime/esutils/metadata/metadata.go 提供PushSecretMetadata[T]泛型与ParseMetadataParameters[T]所有需要结构化 metadata 的 Provider 都复用同一套 apiVersion/kind 校验逻辑Provider 实现层Kubernetesproviders/v1/kubernetes/metadata.go、AWS Secrets Managerproviders/v1/aws/secretsmanager/secretsmanager.go、AWS Parameter Storeproviders/v1/aws/parameterstore/parameterstore.go均已定义各自的PushSecretMetadataSpec并接入泛型解析API 文档层PushSecret 的metadata字段含dataTo批量推送场景在 docs/api/pushsecret.md 中有说明——Provider-specific metadata to attach to all pushed secrets. Structure depends on the provider即结构依 Provider 而定这正是本设计文档所规范的按 Provider 定义、按 apiVersion 分派语义。实际编写 PushSecret 时建议遵循设计文档的迁移路径新配置一律采用apiVersionkindspec三件套并为每个 Provider 查阅其对应的PushSecretMetadataSpec字段定义在 ESO 尚处v1alpha1阶段时旧式扁平 metadata 仍可工作但应尽快迁移为未来v1beta1的 API 收敛做好准备。【免费下载链接】external-secretsExternal Secrets Operator reads information from a third-party service like AWS Secrets Manager and automatically injects the values as Kubernetes Secrets.项目地址: https://gitcode.com/GitHub_Trending/ex/external-secrets创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价