OpenTelemetry Kubernetes attributes processor(k8sattributes)已升到 v1.0.0。真正会改名的只有 7 类属性:标签与注解从复数变成单数,container.image.tag 变成 container.image.tags。k8s.pod.name、k8s.namespace.name、k8s.deployment.name 等核心资源属性保持不变。默认只抽取这些核心字段的 Collector 配置(例如 EDOT kube-stack 默认 Helm values)基本不受影响;真正要提前改的,是自定义查询、告警、看板里对旧标签/注解属性名的引用。

本文依据 OpenTelemetry 官方公告(2026-09-16) 与 Elastic Observability Labs 迁移说明(2026-09-28) 整理。后者补充了 EDOT 9.6 默认切换与双写迁移细节。

v1.0.0 意味着什么

v1.0.0 表示该组件已满足 Collector「稳定」标准:文档、测试、基准、遥测稳定性,以及可作为 Go 库或发行版二进制分发时的 API 承诺。稳定输出依赖的是稳定的语义约定。K8s Semantic Conventions SIG 从 2025 年 11 月起集中推进;约定在 2026 年 3 月 进入 Release Candidate,并在 2026 年 6 月 随 Semantic Conventions v1.42.0 进入 stable。处理器随后走完毕业流程(含生产用户与发行方背书),对齐新的属性命名。

上游公告写明:这次升级会给既有用户带来一部分破坏性变更,因此配套了迁移说明。变更范围集中在标签、注解与镜像 tag 命名空间,并不是整套 K8s 资源属性推倒重来。

按 Elastic 文中的说法,v1.0.0 已合入 OpenTelemetry Collector Contrib main,随 contrib v0.161.0 发布;EDOT Collector 在 9.6 引入,并把相关 feature gate 默认翻成「只发 v1」。Elastic 工程师也参与了上游毕业相关工作,包括 feature gate 机制、K8s 基准与负载测试,以及最终 promotion PR。

7 处更名(旧名 → 新名)

两篇主源与处理器 README 的 Semantic Conventions Compatibility 一节给出的对应关系一致:

v0 属性名 v1 属性名
container.image.tag container.image.tags
k8s.pod.labels.<key> k8s.pod.label.<key>
k8s.pod.annotations.<key> k8s.pod.annotation.<key>
k8s.node.labels.<key> k8s.node.label.<key>
k8s.node.annotations.<key> k8s.node.annotation.<key>
k8s.namespace.labels.<key> k8s.namespace.label.<key>
k8s.namespace.annotations.<key> k8s.namespace.annotation.<key>

规律很简单:标签/注解属性去掉末尾的 s(labels → label,annotations → annotation),镜像 tag 则从单数变成复数。<key> 是你实际抽取的标签或注解键名。例如抽取了 app 标签时,字段从 k8s.pod.labels.app 变为 k8s.pod.label.app。

哪些属性没改

下列核心属性在 v0 与 v1 下同名。依赖它们的查询、告警、看板在升级后仍可继续工作(类别划分取自 Elastic 文):

类别 属性
Pod 身份 k8s.pod.name、k8s.pod.uid、k8s.pod.ip、k8s.pod.start_time
工作负载 k8s.deployment.name、k8s.replicaset.name、k8s.statefulset.name、k8s.daemonset.name、k8s.job.name、k8s.cronjob.name
集群位置 k8s.namespace.name、k8s.node.name
容器 / 服务 container.id;service.name、service.version、service.instance.id

EDOT kube-stack 默认的 k8s_attributes 抽取列表也正是这些核心字段,不包含 labels、annotations 或 container.image.tag。DaemonSet collector 额外会加 container.id,并用 filter.node_from_env_var 把元数据查找限制在本节点。因此「只用默认 Helm values」时,Elastic 侧内置的 kubernetes_otel 包(12 个看板、18 个告警模板、2 个 ML 模块、4 个 SLO 模板)经审计后无需改字段名。

Feature gate:何时开始只发 v1

处理器通过两个 feature gate 控制 v0 / v1 属性发射(整条 v1 发行线内仍标为 beta):

Feature gate EDOT 9.6 之前 EDOT 9.6 起默认 开启后效果
processor.k8sattributes.EmitV1K8sConventions 关闭 开启 发射 v1 属性名
processor.k8sattributes.DontEmitV0K8sConventions 关闭 开启 停止发射 v0 属性名

升级到 EDOT 9.6 且未覆盖这些开关时,Collector 默认只写 v1 名。这才是自定义资产容易「静默断数据」的转折点。

通用 Collector(contrib / k8s distro)同样用这两个 gate;具体默认何时翻转为「只发 v1」,以你所用发行版的发行说明为准。Elastic 文中的时间线绑定的是 EDOT 9.6。可在 kube-stack Helm 的 feature-gates 里按 collector(cluster / daemon)分别覆盖。

上游实现还有一条约束:不能只开 DontEmitV0K8sConventions 却不开 EmitV1K8sConventions,否则启动会失败。双写正确写法是关闭 DontEmitV0、开启 EmitV1。

静默失败风险:过滤、查询、看板

危险之处在于:字段名对不上时,后端通常不会报错,只会查不到新写入的数据。Elastic 文明确写道:自定义资产在 EDOT 9.6 之后若仍查 k8s.pod.labels.* 或 container.image.tag,会安静地不再返回新数据,没有报错,也没有空状态提示。

另一层后果来自存储侧:Elasticsearch 不会把已索引字段改名。旧文档继续带 v0 名,新文档写 v1 名。只查其中一个名字,时间线会被拦腰截断。

在升级前,建议在自己的看板、告警规则、transform、ingest pipeline、保存的搜索里扫一遍这些旧前缀:

k8s.pod.labels.
k8s.pod.annotations.
k8s.node.labels.
k8s.node.annotations.
k8s.namespace.labels.
k8s.namespace.annotations.
container.image.tag

若服务通过 Collector 注入了业务标签(例如 app、version)或注解做路由过滤,对应的字段名也会落在上述命名空间里。Spring Boot / Micrometer / OTel Java agent 本身通常只产出应用侧属性;K8s 标签与注解是 Collector 侧 k8sattributes 抽取后才写入资源属性的。

过渡期双写与迁移步骤

若已有自定义资产引用了旧名,Elastic 建议在升级到 EDOT 9.6 时先开双写:同时发射 v0 与 v1,给迁移留窗口。Helm feature-gates 示例(daemon / cluster 可分别设置):

# 双写:发 v1,同时保留 v0(迁移过渡)
collectors:
  daemon:
    args:
      feature-gates: -processor.k8sattributes.DontEmitV0K8sConventions,processor.k8sattributes.EmitV1K8sConventions
  cluster:
    args:
      feature-gates: -processor.k8sattributes.DontEmitV0K8sConventions,processor.k8sattributes.EmitV1K8sConventions

若短期仍需只发 v0(规划迁移时):

collectors:
  daemon:
    args:
      feature-gates: -processor.k8sattributes.EmitV1K8sConventions,-processor.k8sattributes.DontEmitV0K8sConventions

可按这个顺序落地:

  1. 升级前先盘点自定义资产是否引用上表旧名。
  2. 升级时开启双写(或先短期锁在 v0),保证内置资产与旧自定义查询都能读到数据。
  3. 把看板、告警、查询里的字段改成 v1 名。
  4. 确认无遗漏后,去掉 -processor.k8sattributes.DontEmitV0K8sConventions 覆盖,回到只发 v1,降低索引冗余。

Elastic 在 kind 与 GKE 上用 feature gate 强制 v1-only 输出做过端到端验证,并对 kubernetes_otel 包做了字段审计。双写是过渡手段,不宜长期保留。完整迁移说明见处理器 README 的 Semantic Conventions Compatibility 一节,以及上文两篇主源。

升级前最小核对清单

  • 确认发行版:contrib v0.161.0+,或 EDOT 9.6+(及你所用 distro 的对应版本)。
  • 若配置只抽取核心 metadata、未开 labels/annotations/container.image.tag,优先做一次冒烟即可。
  • 若抽取了标签/注解或镜像 tag,按上表改字段,并决定是否双写。
  • 核对后端已索引文档:历史 v0 与新写入 v1 会并存,查询条件要覆盖迁移窗口。

主源链接:OpenTelemetry:Kubernetes attributes processor reaches v1.0.0、Elastic:Kubernetes attributes processor v1 for EDOT Collector。

— 感谢阅读 —

一起交流

分享你的思考,让讨论更进一步。