feat: derive k8s.node from OTLP resource attributes (#9002)

The k8s.pod runs_on k8s.node rule can only fire from kube_pod_info: it is
the only table declaring both endpoints, and co-declared edges require
both on the same row. A deployment sending only OTLP has no
kube-state-metrics tables, so its node layer is invisible and that rule
has no source at all, even though the resource attributes carry
k8s.node.name.

Declare k8s.node in otlp_trace_entities and in the synthesized resource
descriptor, and project k8s.node.name in the descriptor writer so the
column the declaration needs exists. Identity is the name rather than
k8s.node.uid: kube-state-metrics carries no node UID, so the name is the
only identity both sources can agree on.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
This commit is contained in:
dennis zhuang
2026-09-02 05:12:30 +00:00
committed by GitHub
parent 6f1dd0cb76
commit 02278d301b
4 changed files with 33 additions and 10 deletions
@@ -75,6 +75,11 @@ otlp_trace_entities:
descriptive:
- resource_attributes.k8s.pod.name
- resource_attributes.k8s.namespace.name
# Named, not k8s.node.uid: kube-state-metrics carries no node UID, so the
# name is the only identity both sources can agree on. Same-named nodes in
# different clusters therefore merge.
- entity: k8s.node
id: [resource_attributes.k8s.node.name]
# Implicit declarations for Prometheus entity-descriptor metrics, keyed by
# table name. Pod and service identities are the UIDs (names stay
@@ -184,3 +189,6 @@ otel_info_metrics:
descriptive:
- k8s.pod.name
- k8s.namespace.name
# Named for the same reason as on the trace side above.
- entity: k8s.node
id: [k8s.node.name]