diff --git a/docs/metrics/dimensions.yaml b/docs/metrics/dimensions.yaml index 5e75e7f2..8f56880c 100755 --- a/docs/metrics/dimensions.yaml +++ b/docs/metrics/dimensions.yaml @@ -29,6 +29,19 @@ dest.workload.name: brief: See workload.name description: See workload.name +workload.uid: + brief: Kubernetes workload or application UUID. + description: If the associated metric comes from a monitored Kubernetes cluster running the k8-collector, the metric may note the UUID of the source and destination workload that the traffic being measured moved between. This UUID represents the unique identifier of the associated Deployment or DaemonSet. + example: 0485c36b-283e-496e-af47-1a69545cd887 + +source.workload.uid: + brief: See workload.uid + description: See workload.uid + +dest.workload.uid: + brief: See workload.uid + description: See workload.uid + image_version: brief: Kubernetes pod version label of the workload. description: If the associated metric comes from a monitored Kubernetes cluster running the k8-collector, the metric may note the source and destination versions that the traffic being measured moved between. The version label is optionally set by the administrator configuring Kubernetes. Sometimes referred to as the 'service version.' May be found in the docker (pod) image or Kubernetes metadata. diff --git a/reducer/aggregation/agg_root_span.cc b/reducer/aggregation/agg_root_span.cc index 4106923d..4889b22a 100644 --- a/reducer/aggregation/agg_root_span.cc +++ b/reducer/aggregation/agg_root_span.cc @@ -57,6 +57,9 @@ void AggRootSpan::update_node( using role_t = ::ebpf_net::aggregation::spans::role::s_t; auto role = as_short_string(msg->role, stat_counters.trunc_role); + using uid_t = ::ebpf_net::aggregation::spans::role::uid_t; + auto role_uid = as_short_string(msg->role_uid, stat_counters.trunc_role_uid); + using version_t = ::ebpf_net::aggregation::spans::role::version_t; auto version = as_short_string(msg->version, stat_counters.trunc_version); @@ -84,6 +87,7 @@ void AggRootSpan::update_node( if (!role_ref.valid()) { return; } + role_ref.modify().uid(role_uid); auto az_ref = index.az.by_key({az, role_ref.loc()}); if (!az_ref.valid()) { diff --git a/reducer/aggregation/labels.h b/reducer/aggregation/labels.h index e16a67ba..3ac12b60 100644 --- a/reducer/aggregation/labels.h +++ b/reducer/aggregation/labels.h @@ -20,6 +20,7 @@ struct NodeLabels { std::string ip; std::string az; std::string role; + std::string role_uid; std::string version; std::string env; std::string ns; diff --git a/reducer/aggregation/labels.inl b/reducer/aggregation/labels.inl index 6e7830fd..941c9328 100644 --- a/reducer/aggregation/labels.inl +++ b/reducer/aggregation/labels.inl @@ -9,6 +9,7 @@ #define FOREACH_NODE_LABEL(FUNC) \ FUNC("workload.name", role) \ + FUNC("workload.uid", role_uid) \ FUNC("availability_zone", az) \ FUNC("id", id) \ FUNC("ip", ip) \ @@ -39,6 +40,7 @@ inline NodeLabels::NodeLabels(::ebpf_net::aggregation::weak_refs::az az_ref) : N inline NodeLabels::NodeLabels(::ebpf_net::aggregation::weak_refs::role role_ref) { role = role_ref.s().to_string(); + role_uid = role_ref.uid().to_string(); version = role_ref.version().to_string(); env = role_ref.env().to_string(); ns = role_ref.ns().to_string(); diff --git a/reducer/aggregation/stat_counters.h b/reducer/aggregation/stat_counters.h index bf4c08f6..b778d748 100644 --- a/reducer/aggregation/stat_counters.h +++ b/reducer/aggregation/stat_counters.h @@ -17,7 +17,8 @@ FN(pod_name, 6) \ FN(process, 7) \ FN(role, 8) \ - FN(version, 9) + FN(version, 9) \ + FN(role_uid, 10) namespace reducer::aggregation { diff --git a/reducer/ingest/agent_span.cc b/reducer/ingest/agent_span.cc index 80e8ddb8..acb7fc35 100644 --- a/reducer/ingest/agent_span.cc +++ b/reducer/ingest/agent_span.cc @@ -610,6 +610,7 @@ void AgentSpan::bpf_lost_samples( void AgentSpan::set_pod_new( std::string_view uid, std::string_view owner_name, + std::string_view owner_uid, std::string_view pod_name, std::string_view ns, std::string_view version, @@ -640,7 +641,7 @@ void AgentSpan::set_pod_new( version); // populate the pod span with pod metadata - k8s_pod.set_pod_detail(jb_blob(owner_name), jb_blob{pod_name}, jb_blob(ns), jb_blob(version)); + k8s_pod.set_pod_detail(jb_blob(owner_name), jb_blob{pod_name}, jb_blob(ns), jb_blob(version), jb_blob(owner_uid)); // Add pod to k8s_pod_set if it isn't already there. @@ -661,18 +662,18 @@ void AgentSpan::set_pod_new( void AgentSpan::pod_new_legacy(::ebpf_net::ingest::weak_refs::agent span_ref, u64 timestamp, jsrv_ingest__pod_new_legacy *msg) { - set_pod_new(msg->uid, msg->owner_name, {}, msg->ns, {}, msg->ip); + set_pod_new(msg->uid, msg->owner_name, msg->owner_uid, {}, msg->ns, {}, msg->ip); } void AgentSpan::pod_new_legacy2(::ebpf_net::ingest::weak_refs::agent span_ref, u64 timestamp, jsrv_ingest__pod_new_legacy2 *msg) { - set_pod_new(msg->uid, msg->owner_name, {}, msg->ns, msg->version, msg->ip); + set_pod_new(msg->uid, msg->owner_name, msg->owner_uid, {}, msg->ns, msg->version, msg->ip); } void AgentSpan::pod_new_with_name( ::ebpf_net::ingest::weak_refs::agent span_ref, u64 timestamp, jsrv_ingest__pod_new_with_name *msg) { - set_pod_new(msg->uid, msg->owner_name, msg->pod_name, msg->ns, msg->version, msg->ip); + set_pod_new(msg->uid, msg->owner_name, msg->owner_uid, msg->pod_name, msg->ns, msg->version, msg->ip); } void AgentSpan::pod_container(::ebpf_net::ingest::weak_refs::agent span_ref, u64 timestamp, jsrv_ingest__pod_container *msg) diff --git a/reducer/ingest/agent_span.h b/reducer/ingest/agent_span.h index ebc0c423..c5ebae2e 100644 --- a/reducer/ingest/agent_span.h +++ b/reducer/ingest/agent_span.h @@ -107,6 +107,7 @@ class AgentSpan : public ::ebpf_net::ingest::AgentSpanBase { void set_pod_new( std::string_view uid, std::string_view owner_name, + std::string_view owner_uid, std::string_view pod_name, std::string_view ns, std::string_view version, diff --git a/reducer/matching/flow_span.cc b/reducer/matching/flow_span.cc index 9ed3fcde..0d1c9d68 100644 --- a/reducer/matching/flow_span.cc +++ b/reducer/matching/flow_span.cc @@ -230,7 +230,8 @@ void FlowSpan::update_node(::ebpf_net::matching::weak_refs::agg_root agg_root, F jb_blob(n.address), jb_blob(n.comm), jb_blob(n.container_name), - jb_blob(n.pod_name)); + jb_blob(n.pod_name), + jb_blob(n.role_uid)); } void FlowSpan::create_agg_root(::ebpf_net::matching::weak_refs::flow flow, NodeData const &node_a, NodeData const &node_b) @@ -316,6 +317,7 @@ FlowSpan::NodeData FlowSpan::resolve_node(::ebpf_net::matching::weak_refs::flow auto [id, az, is_autonomous_system] = get_id_az(side); std::string role; + std::string role_uid; std::string version; std::string env; std::string ns; @@ -364,6 +366,7 @@ FlowSpan::NodeData FlowSpan::resolve_node(::ebpf_net::matching::weak_refs::flow // enrich node_type = NodeResolutionType::K8S_CONTAINER; role = pod.owner_name(); + role_uid = pod.owner_uid(); version = pod.version(); ns = pod.ns(); @@ -477,6 +480,7 @@ FlowSpan::NodeData FlowSpan::resolve_node(::ebpf_net::matching::weak_refs::flow .id = id, .az = az, .role = role, + .role_uid = role_uid, .version = version, .env = env, .ns = ns, diff --git a/reducer/matching/flow_span.h b/reducer/matching/flow_span.h index 8ed1b505..0010339b 100644 --- a/reducer/matching/flow_span.h +++ b/reducer/matching/flow_span.h @@ -97,6 +97,7 @@ class FlowSpan : public ::ebpf_net::matching::FlowSpanBase { std::string id; std::string az; std::string role; + std::string role_uid; std::string version; std::string env; std::string ns; diff --git a/reducer/matching/k8s_pod_span.cc b/reducer/matching/k8s_pod_span.cc index 7bc0df27..f9ddd05f 100644 --- a/reducer/matching/k8s_pod_span.cc +++ b/reducer/matching/k8s_pod_span.cc @@ -20,6 +20,7 @@ void K8sPodSpan::set_pod_detail( { span_ref.modify() .owner_name({short_string_behavior::truncate, msg->owner_name}) + .owner_uid({short_string_behavior::truncate, msg->owner_uid}) .pod_name({short_string_behavior::truncate, msg->pod_name}) .ns({short_string_behavior::truncate, msg->ns}) .version({short_string_behavior::truncate, msg->version}); diff --git a/render/ebpf_net.render b/render/ebpf_net.render index b18c23a1..093ab36b 100644 --- a/render/ebpf_net.render +++ b/render/ebpf_net.render @@ -1098,6 +1098,9 @@ app ingest { // can be obtained from docker label `io.kubernetes.pod.name`?? string<64> owner_name // name of the Deployment, DaemonSet, ReplicaSet or StatefulSet owning the pod + // owner uid + string<64> owner_uid + // can be obtained from docker label `io.kubernetes.pod.namespace` string<64> ns @@ -1343,6 +1346,7 @@ app matching { u64 uid_hash string<64> owner_name // name of the Deployment, DaemonSet, ReplicaSet or StatefulSet owning the pod + string<64> owner_uid string<64> pod_name string<64> ns string<64> version @@ -1357,6 +1361,7 @@ app matching { 2: string pod_name 3: string ns 4: string version + 5: string owner_uid } } /* span k8s_pod */ @@ -1425,6 +1430,7 @@ app aggregation { pool_size 70000 index (s, version, env, ns, node_type, process, container) string<80> s + string<80> uid string<64> version string<32> env string<64> ns @@ -1498,6 +1504,7 @@ app aggregation { 11: string process 12: string container 13: string pod_name + 14: string role_uid } 14: msg update_tcp_metrics { 1: u8 direction