Replace <DD_API_KEY> with your actual Datadog API key.
Configure the OTel Collector
After deploying the OTel Operator, create the OpenTelemetryCollector resource that triggers the deployment of the Collector.
Use the node-collector.yaml file to specify your OpenTelemetryCollector daemonset configuration.
node-collector.yaml
apiVersion:opentelemetry.io/v1beta1kind:OpenTelemetryCollectormetadata:name:node-collectorspec:# Deploy 1 instance per node, that will collect telemetry from that node's podsmode:daemonsetcommand:['otel-agent','run']# Will no longer be necessary from 7.82.0 onwardsconfig:exporters:datadog:api:key:${env:DD_API_KEY}site:${env:DD_SITE}sending_queue:batch:flush_timeout:10sservice:telemetry:resource:k8s.cluster.name:${env:K8S_CLUSTER_NAME}env:- name:DD_API_KEYvalueFrom:secretKeyRef:key:api-keyname:datadog-apikey- name:DD_SITEvalueFrom:secretKeyRef:key:sitename:datadog-apikey- name:DD_OTELCOLLECTOR_CONVERTER_FEATURESvalue:datadog,pprof,zpages,prometheus,infraattributes- name:K8S_CLUSTER_NAMEvalue:<CLUSTER_NAME># vvv Will no longer be necessary from 7.83.0 onwards vvv- name:DD_OTEL_STANDALONEvalue:'true'# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^# vvv Will no longer be necessary from 7.82.0 onwards vvv- name:DD_OTELCOLLECTOR_ENABLEDvalue:'true'# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Replace <CLUSTER_NAME> with a name for your cluster.
Add an OTLP receiver and the Datadog exporter for all desired signals. Publish the OTLP ports on the node with hostPort so that application pods can reach the Collector instance running on the same node:
node-collector.yaml
# [...]spec:# [...]# Publish the OTLP ports on the node's network interfaceports:- name:otlp-grpcport:4317protocol:TCPhostPort:4317- name:otlp-httpport:4318protocol:TCPhostPort:4318config:receivers:otlp:protocols:grpc:endpoint:0.0.0.0:4317http:endpoint:0.0.0.0:4318# [...]service:# [...]pipelines:logs:receivers:['otlp']exporters:['datadog']metrics:receivers:['otlp']exporters:['datadog']traces:receivers:['otlp']exporters:['datadog']
(Optional) Enable additional features:
Enabling these features may incur additional charges. Review the pricing page and talk to your Customer Success Manager before proceeding.
node-collector.yaml
spec:config:receivers:host_metrics:collection_interval:15sscrapers:cpu:{}load:{}memory:{}network:{}disk:{}kubelet_stats:auth_type:serviceAccountcollection_interval:15sendpoint:${env:K8S_NODE_NAME}:10250node:${env:K8S_NODE_NAME}metric_groups:- pod- container- volumeprocessors:infraattributes:cardinality:2resource/add-cluster-name:attributes:- key:k8s.cluster.namevalue:${env:K8S_CLUSTER_NAME}action:upsertconnectors:datadog/connector:traces:compute_top_level_by_span_kind:truepeer_tags_aggregation:truecompute_stats_by_span_kind:trueextensions:health_check:endpoint:"${env:K8S_POD_IP}:13133"# [...]service:# [...]extensions:['health_check']pipelines:logs:# [...]processors:['resource/add-cluster-name','infraattributes']metrics:receivers:['host_metrics','otlp','kubelet_stats','datadog/connector']processors:['resource/add-cluster-name','infraattributes']# [...]traces:# [...]processors:['resource/add-cluster-name','infraattributes']exporters:['datadog','datadog/connector']env:# [...]- name:K8S_POD_IPvalueFrom:fieldRef:apiVersion:v1fieldPath:status.podIP# K8S_NODE_NAME is added automatically by the operator
(Optional) Collect container logs from the node’s file system:
Enabling log collection may incur additional charges. Review the pricing page and talk to your Customer Success Manager before proceeding.
The filelog receiver reads container logs from the node. Because the Operator does not mount host paths automatically, add the log directories as read-only volumes:
node-collector.yaml
spec:config:receivers:filelog:include:- /var/log/pods/*/*/*.log# Exclude the Collector's own logs to avoid a feedback loopexclude:- /var/log/pods/*_node-collector-collector-*_*/otc-container/*.logstart_at:endinclude_file_path:trueinclude_file_name:falseretry_on_failure:enabled:trueoperators:- id:container-parsertype:containermax_log_size:102400# [...]service:# [...]pipelines:logs:receivers:['otlp','filelog']# [...]# Mount the node's log directories into the Collector pod (read-only)volumes:- name:varlogpodshostPath:path:/var/log/pods- name:varlibdockercontainershostPath:path:/var/lib/docker/containersvolumeMounts:- name:varlogpodsmountPath:/var/log/podsreadOnly:true- name:varlibdockercontainersmountPath:/var/lib/docker/containersreadOnly:true
Completed node-collector.yaml file
Your node-collector.yaml file should look something like this:
node-collector.yaml
apiVersion:opentelemetry.io/v1beta1kind:OpenTelemetryCollectormetadata:name:node-collectorspec:# Deploy 1 instance per node, that will collect telemetry from that node's podsmode:daemonsetcommand:['otel-agent','run']# Will no longer be necessary from 7.82.0 onwards# Publish the OTLP ports on the node's network interfaceports:- name:otlp-grpcport:4317protocol:TCPhostPort:4317- name:otlp-httpport:4318protocol:TCPhostPort:4318config:receivers:otlp:protocols:grpc:endpoint:0.0.0.0:4317http:endpoint:0.0.0.0:4318host_metrics:collection_interval:15sscrapers:cpu:{}load:{}memory:{}network:{}disk:{}kubelet_stats:auth_type:serviceAccountcollection_interval:15sendpoint:${env:K8S_NODE_NAME}:10250node:${env:K8S_NODE_NAME}metric_groups:- pod- container- volumefilelog:include:- /var/log/pods/*/*/*.logexclude:- /var/log/pods/*_node-collector-collector-*_*/otc-container/*.logstart_at:endinclude_file_path:trueinclude_file_name:falseretry_on_failure:enabled:trueoperators:- id:container-parsertype:containermax_log_size:102400processors:infraattributes:cardinality:2resource/add-cluster-name:attributes:- key:k8s.cluster.namevalue:${env:K8S_CLUSTER_NAME}action:upsertconnectors:datadog/connector:traces:compute_top_level_by_span_kind:truepeer_tags_aggregation:truecompute_stats_by_span_kind:trueexporters:datadog:api:key:${env:DD_API_KEY}site:${env:DD_SITE}sending_queue:batch:flush_timeout:10sextensions:health_check:endpoint:"${env:K8S_POD_IP}:13133"service:telemetry:resource:k8s.cluster.name:${env:K8S_CLUSTER_NAME}extensions:['health_check']pipelines:logs:receivers:['otlp','filelog']processors:['resource/add-cluster-name','infraattributes']exporters:['datadog']metrics:receivers:['host_metrics','otlp','kubelet_stats','datadog/connector']processors:['resource/add-cluster-name','infraattributes']exporters:['datadog']traces:receivers:['otlp']processors:['resource/add-cluster-name','infraattributes']exporters:['datadog','datadog/connector']env:- name:DD_API_KEYvalueFrom:secretKeyRef:key:api-keyname:datadog-apikey- name:DD_SITEvalueFrom:secretKeyRef:key:sitename:datadog-apikey- name:DD_OTELCOLLECTOR_CONVERTER_FEATURESvalue:datadog,pprof,zpages,prometheus,infraattributes- name:K8S_CLUSTER_NAMEvalue:<CLUSTER_NAME>- name:K8S_POD_IPvalueFrom:fieldRef:apiVersion:v1fieldPath:status.podIP# K8S_NODE_NAME is added automatically by the operator# vvv Will no longer be necessary from 7.83.0 onwards vvv- name:DD_OTEL_STANDALONEvalue:'true'# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^# vvv Will no longer be necessary from 7.82.0 onwards vvv- name:DD_OTELCOLLECTOR_ENABLEDvalue:'true'# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^# Mount the node's log directories for the filelog receiver (read-only)volumes:- name:varlogpodshostPath:path:/var/log/pods- name:varlibdockercontainershostPath:path:/var/lib/docker/containersvolumeMounts:- name:varlogpodsmountPath:/var/log/podsreadOnly:true- name:varlibdockercontainersmountPath:/var/lib/docker/containersreadOnly:true
Replace <CLUSTER_NAME> with a name for your cluster.
Use a YAML file to specify the Helm chart parameters for the Collector chart.
Create an empty node-collector-values.yaml file:
touch node-collector-values.yaml
Unspecified parameters use defaults from values.yaml.
Choose the daemonset mode and use DDOT as the collector:
node-collector-values.yaml
mode:daemonsetimage:repository:datadog/ddot-collectortag:7.80.4ports:jaeger-compact:enabled:falsejaeger-grpc:enabled:falsejaeger-thrift:enabled:falsezipkin:enabled:false# Can be removed from 7.82.0 onwardscommand:name:opt/datadog-agent/embedded/bin/otel-agent
For FED, set tag: 7.80.4-fips to use the FIPS-compliant DDOT image. See FIPS compliance.
The Collector Helm chart publishes the OTLP ports on each node by default (hostPort: 4317 for gRPC and hostPort: 4318 for HTTP), so application pods can reach the Collector instance running on the same node. See Configure the application.
Configure the Datadog exporter and API key secret:
node-collector-values.yaml
config:exporters:datadog:api:key:${env:DD_API_KEY}site:${env:DD_SITE}sending_queue:batch:flush_timeout:10sextraEnvs:- name:DD_API_KEYvalueFrom:secretKeyRef:key:api-keyname:datadog-apikey- name:DD_SITEvalueFrom:secretKeyRef:key:sitename:datadog-apikey- name:DD_OTELCOLLECTOR_CONVERTER_FEATURESvalue:datadog,pprof,zpages,prometheus,infraattributes- name:K8S_CLUSTER_NAMEvalue:<CLUSTER_NAME># vvv Will no longer be necessary from 7.83.0 onwards vvv- name:DD_OTEL_STANDALONEvalue:'true'# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^# vvv Will no longer be necessary from 7.82.0 onwards vvv- name:DD_OTELCOLLECTOR_ENABLEDvalue:'true'# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Replace <CLUSTER_NAME> with a name for your cluster.
Your node-collector-values.yaml file should look something like this:
node-collector-values.yaml
mode:daemonset# vvv To be removed from 7.82.0 onwards vvvcommand:name:opt/datadog-agent/embedded/bin/otel-agent# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^image:repository:datadog/ddot-collectortag:7.80.4presets:hostMetrics:# Add an hostmetrics receiver to the metrics pipelineenabled:truekubeletMetrics:# Add a kubeletstats receiver to the metrics pipelineenabled:truelogsCollection:# Add a filelog receiver to the logs pipelineenabled:trueincludeCollectorLogs:falseconfig:connectors:datadog/connector:traces:compute_top_level_by_span_kind:truepeer_tags_aggregation:truecompute_stats_by_span_kind:trueexporters:datadog:api:key:${env:DD_API_KEY}site:${env:DD_SITE}sending_queue:batch:flush_timeout:10sprocessors:infraattributes:cardinality:2resource/add-cluster-name:attributes:- key:k8s.cluster.namevalue:${env:K8S_CLUSTER_NAME}action:upsertreceivers:otlp:protocols:grpc:endpoint:0.0.0.0:4317http:endpoint:0.0.0.0:4318service:extensions:- health_checkpipelines:logs:receivers:- otlpprocessors:- resource/add-cluster-name- infraattributesexporters:- datadogmetrics:receivers:- otlp- datadog/connectorprocessors:- resource/add-cluster-name- infraattributesexporters:- datadogtraces:receivers:- otlpprocessors:- resource/add-cluster-name- infraattributesexporters:- datadog- datadog/connectortelemetry:resource:k8s.cluster.name:${env:K8S_CLUSTER_NAME}extraEnvs:- name:DD_API_KEYvalueFrom:secretKeyRef:key:api-keyname:datadog-apikey- name:DD_SITEvalueFrom:secretKeyRef:key:sitename:datadog-apikey- name:DD_OTELCOLLECTOR_CONVERTER_FEATURESvalue:datadog,pprof,zpages,prometheus,infraattributes- name:K8S_CLUSTER_NAMEvalue:<CLUSTER_NAME># vvv Will no longer be necessary from 7.83.0 onwards vvv- name:DD_OTEL_STANDALONEvalue:'true'# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^# vvv Will no longer be necessary from 7.82.0 onwards vvv- name:DD_OTELCOLLECTOR_ENABLEDvalue:'true'# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ports:jaeger-compact:enabled:falsejaeger-grpc:enabled:falsejaeger-thrift:enabled:falsezipkin:enabled:false
Deploy the Collector
Apply the node-collector.yaml file to create the OpenTelemetryCollector resource. The Operator deploys the Collector as a DaemonSet, running one instance per node:
kubectl apply -f node-collector.yaml
Install the OpenTelemetry Collector chart with your values file:
Example application instrumented with the OpenTelemetry API
As an example, you can use the Calendar sample application that’s already instrumented for you. The following code instruments the CalendarService.getDate() method using the OpenTelemetry annotations and API:
Your application container must send data to the DDOT Collector running on the same node. Because the Collector publishes the OTLP ports on the node with hostPort, the application can reach the local Collector through the node’s IP address (status.hostIP).
If the OTEL_EXPORTER_OTLP_ENDPOINT environment variable is not already set, add it to your application’s Deployment manifest file:
Unified service tagging ties observability data together in Datadog so you can navigate across metrics, traces, and logs with consistent tags.
In containerized environments, set env, service, and version using OpenTelemetry Resource Attributes environment variables. The DDOT Collector detects this tagging configuration and applies it to the data it collects from containers.
Add the following environment variables to your application’s deployment manifest:
Redeploy your application to apply the changes made in the deployment manifest. After the updated configuration is active, Unified Service Tagging is fully enabled for your metrics, traces, and logs.
Explore observability data in Datadog
Use Datadog to explore the observability data for your application.
Fleet automation
Explore your Collector configuration.
Live container monitoring
Monitor your container health using Live Container Monitoring capabilities.
Infrastructure node health
View runtime and infrastructure metrics to visualize, monitor, and measure the performance of your nodes.
Logs
View logs to monitor and troubleshoot application and system operations.
Traces
View traces and spans to observe the status and performance of requests processed by your application, with infrastructure metrics correlated in the same trace.
Runtime metrics
Monitor your runtime (JVM) metrics for your applications.
Collector health metrics
View metrics from the DDOT Collector to monitor the Collector health.
Further reading
Additional helpful documentation, links, and articles: