Metadata enrichment of all telemetry originating from Kubernetes workloads

Prerequisites

  • Dynatrace Operator is installed and running in your Kubernetes cluster.
  • A valid DynaKube is applied to your cluster.
  • Metadata enrichment is enabled.

Use cases

  • Enhance your metrics, logs, trace data, events and entities with information about Kubernetes cluster, namespace, and workload
  • Enhance your metrics, logs, trace data, events and entities with additional information using Kubernetes annotations and labels.
  • Enhance your metrics, logs, trace data, events and entities with additional information using OpenTelemetry environment variables
  • Enriched data can be used for defining access control to users, or for solving cost allocation in DPS.

Automatic enrichment of telemetry data with information about Kubernetes cluster, namespace, and workload

When following the Dynatrace deployment models with enabled metadata enrichment, all your telemetry (metrics, logs, and trace data) will be automatically enriched with the following Kubernetes metadata information:

  • k8s.cluster.name
  • k8s.cluster.uid
  • k8s.namespace.name
  • k8s.workload.name
  • k8s.workload.kind
  • dt.entity.kubernetes_cluster

Metrics that are about Kubernetes nodes, pods, and containers, as well as host and process metrics, additionally get the following information:

  • k8s.pod.name
  • k8s.pod.uuid
  • k8s.node.name
  • dt.entity.kubernetes_node

This enables you to always associate any kind of telemetry with the underlying Kubernetes deployment and infrastructure.

Security context and cost allocation

In Dynatrace you can set up policy boundaries, for fine-granular restrictions on the data level. Per default you can use k8s.namespace.name and k8s.cluster.name, but sometimes this is not enough and you need a more fine grained way to set up your boundries. You might already have defined such boundaries for yourself and defined them as Kubernetes labels or annotations. This feature enables you to use these at the source for your security context in Dynatrace. If you have not done so already Dynatrace does recommend to either use cluster or namespace name or setup a dedicated annotation for your Kubernetes workloads that serves as your security context.

Similarly Dynatrace provides a solution for cost allocation in DPS. You might already have the necessary data like department and product available in your existing Kubernetes labels or annotations. Even if not you might find it very convenient to setup up cost allocation as a Kubernetes annotation or label, which is what Dynatrace recommends. This feature then enables you to use these labels and annotations as the means to solving cost allocation in DPS.

The following attributes are supported:

If annotations with the same keys are specified in both the namespace and pod, the pod annotations will take precedence.

Prerequisites

Operator version 1.3.0+, ActiveGate version 1.305+, OneAgent version 1.303+

Which data will be enriched

Icon

Meaning


GA

Generally available.


Future

A feature or technology support that is on the roadmap.

Data

Availability

Kubernetes metrics via ActiveGate monitoring

Kubernetes monitored entities (dt.security_context only)

Kubernetes events

OneAgent version 1.309

OneAgent events

OneAgent version 1.309

OneAgent metrics

OneAgent version 1.309

Process entities

OneAgent version 1.309

Service metrics

Service entities

JMX metrics

Enrichment options

Depending on the specific use case, the following enrichment options are supported:

Use existing labels and annotations

You can enrich your data using existing Kubernetes namespace labels and annotations via Kubernetes enrichment rules. You can define up to 20 rules on a tenant or Kubernetes cluster level that define the labels or annotations for your security context or cost allocation.

This requires a pod restart.

  1. Go to Kubernetes App > Namespace > Select your namespace to have an overview of your existing namespace labels.

    Namespace details opened in the K8s App, pointing to the current namespace labels

  2. Go to Settings > Cloud and virtualization > Kubernetes telemetry enrichment.

    To configure the data enrichment on the Kubernetes cluster level, go to Kubernetes > [Kubernetes Cluster] > Settings > Telemetry enrichment.

    Global enrichment settings will not apply to Kubernetes clusters that have cluster-specific rules set.

  3. Select Add rule.

  4. Select Annotation or Label in the Metadata type dropdown.

  5. Enter the annotation/label key in the Source field, following Kubernetes conventions:

    source := (prefix/)?name
    prefix := [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*
    name := ([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]

    The source maximum length is 75 characters. The name maximum length is 63 characters.

  6. Select the Target - the name of the attribute on the Dynatrace data.

    Enrichment Settings with the value from the namespace label

  7. Select Save changes.

  8. Wait for up to 45 minutes and restart your pods.

  9. Navigate to one of your spans and verify that the metadata is successfully enriched.

    Span details with enriched metadata

In order for all data enrichment to work the Dynatrace Operator stores the values of the namespace annotations and labels on pods as special annotations using the following conventions:

annotations:
metadata.dynatrace.com/<target>: <value> # created by the Operator

The pod annotation will be used to enrich the Dynatrace data with attributes: <target>: <value>

Example

Rules
"rules":
[
{
# rule #1
"type": "Annotation",
"source": "metadata.example.com/team",
"target": "dt.security_context"
},
{
# rule #2
"type": "Label",
"source": "department",
"target": "dt.cost.costcenter"
},
{
# rule #3
"type": "Label",
"source": "app/name",
"target": "dt.cost.product"
}
]
Namespace
metadata:
annotations:
metadata.example.com/team: sre
labels:
department: it_services
app/name: fin_app
Pod

The Operator will create pod annotations:

metadata:
annotations:
metadata.dynatrace.com/dt.security_context: sre # created by the Operator from metadata.example.com/team namespace annotation by rule #1
metadata.dynatrace.com/dt.cost.costcenter: it_services # created by the Operator from department namespace label by rule #2
metadata.dynatrace.com/dt.cost.product: fin_app # created by the Operator from app/name namespace label by rule #3
Attributes on the telemetry data

The following attributes will enrich the data:

# come from pod annotations with the metadata.dynatrace.com prefix
dt.security_context: sre
dt.cost.costcenter: it_services
dt.cost.product: fin_app

Use dedicated dynatrace metadata pod annotations

You can enrich your data using dedicate pod annotations. You might create the following annotations at the pod level

metadata:
annotations:
metadata.dynatrace.com/dt.security_context: sre
metadata.dynatrace.com/dt.cost.costcenter: it_services
metadata.dynatrace.com/dt.cost.product: fin_app
metadata.dynatrace.com/my.own.attribute: my_value

The following attributes will enrich the data:

dt.security_context: sre
dt.cost.costcenter: it_services
dt.cost.product: fin_app
my.own.attribute: my_value

Manually added custom attributes, so anything that is not dt.security_context, dt.cost.costcenter or dt.cost.product, do not yet enrich K8s events and metrics.

Use OpenTelemetry environment variables

You can also choose to enrich your data via OpenTelemetry environment variable.

Best for

Enrichment via environment variables can be utilized in the following scenarios:

How it works

You can use the OTEL_RESOURCE_ATTRIBUTES environment variable to configure attributes.

Both OneAgent and OpenTelemetry will enrich your data with the attributes defined in OTEL_RESOURCE_ATTRIBUTES.

See the Resource semantic conventions for details.

  1. Store DynaKube name
DYNAKUBE="dynakube" # set this to the name of your DynaKube / kubectl get dynakube -n dynatrace
  1. Get k8s.cluster.uid
K8S_CLUSTER_UID="$(kubectl get dynakube -o jsonpath='{.status.kubeSystemUUID}' -n dynatrace $DYNAKUBE)"
  1. Get k8s.cluster.name
K8S_CLUSTER_NAME="$(kubectl get dynakube -o jsonpath='{.status.kubernetesClusterName}' -n dynatrace $DYNAKUBE)"
  1. Get Kubernetes entity dt.entity.kubernetes_cluster
DT_ENTITY_KUBERNETES_CLUSTER="$(kubectl get dynakube -o jsonpath='{.status.kubernetesClusterMEID}' -n dynatrace $DYNAKUBE)"
  1. Create config map
kubectl create configmap dynatrace-metadata \
--from-literal K8S_CLUSTER_UID=$K8S_CLUSTER_UID \
--from-literal K8S_CLUSTER_NAME=$K8S_CLUSTER_NAME \
--from-literal DT_ENTITY_KUBERNETES_CLUSTER=$DT_ENTITY_KUBERNETES_CLUSTER

k8s.container.name cannot be set via downward API. It needs to be provided as a static string.

envFrom:
- configMapRef:
name: dynatrace-metadata
optional: false
env:
- name: K8S_CONTAINER_NAME
value: "" # replace with actual container name
- name: K8S_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: K8S_POD_UID
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.uid
- name: K8S_POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: K8S_WORKLOAD_KIND
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.annotations['metadata.dynatrace.com/k8s.workload.kind'] # only works when metadata enrichment is enabled
- name: K8S_WORKLOAD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.annotations['metadata.dynatrace.com/k8s.workload.name'] # only works when metadata enrichment is enabled
- name: K8S_NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
- name: DT_SECURITY_CONTEXT # only works when automatic security context enrichment is configured
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.annotations['metadata.dynatrace.com/dt.security_context']
- name: DT_COST_PRODUCT # only works when automatic cost product enrichment is configured
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.annotations['metadata.dynatrace.com/dt.cost.product']
- name: DT_COST_COSTCENTER # only works when automatic cost center enrichment is configured
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.annotations['metadata.dynatrace.com/dt.cost.costcenter']

This example shows all our recommended attributes. Remove attributes that are not in use.

- name: OTEL_RESOURCE_ATTRIBUTES
value: k8s.cluster.name=$(K8S_CLUSTER_NAME),k8s.cluster.uid=$(K8S_CLUSTER_UID),k8s.node.name=$(K8S_NODE_NAME),k8s.workload.name=$(K8S_WORKLOAD_NAME),k8s.workload.kind=$(K8S_WORKLOAD_KIND),k8s.pod.name=$(K8S_POD_NAME),k8s.pod.uid=$(K8S_POD_UID),k8s.namespace.name=$(K8S_POD_NAMESPACE),k8s.container.name=$(K8S_CONTAINER_NAME),dt.entity.kubernetes_cluster=$(DT_ENTITY_KUBERNETES_CLUSTER),dt.security_context=$(DT_SECURITY_CONTEXT),dt.cost.costcenter=$(DT_COST_COSTCENTER),dt.cost.product=$(DT_COST_PRODUCT)