The following configuration example shows how you configure a Collector instance to fetch logs from all Kubernetes pods. It also shows how to enrich the logs with Kubernetes metadata in order to automatically link OpenTelemetry services to pods and attach the logs to the Kubernetes services and pods.
This sample configuration uses the same Kubernetes enrichment approach as the use case at Enrich from Kubernetes.
In addition to the Collector configuration, be sure to also update your Kubernetes configuration for the following components:
receivers:# configure the filelog receiver to access the pod and container logs# from the mounted volumesfilelog:include:- /var/log/pods/*/*/*.log- /var/log/containers/*.loginclude_file_name: falseinclude_file_path: truestart_at: endoperators:- id: container-parsertype: containerprocessors:k8sattributes:extract:metadata:- k8s.pod.name- k8s.pod.uid- k8s.deployment.name- k8s.statefulset.name- k8s.daemonset.name- k8s.cronjob.name- k8s.namespace.name- k8s.node.name- k8s.cluster.uidpod_association:- sources:- from: resource_attributename: k8s.pod.name- from: resource_attributename: k8s.namespace.name- sources:- from: resource_attributename: k8s.pod.ip- sources:- from: resource_attributename: k8s.pod.uid- sources:- from: connectiontransform:error_mode: ignoretrace_statements:- context: resourcestatements: &k8s-statements- set(attributes["dt.kubernetes.workload.kind"], "statefulset") where IsString(attributes["k8s.statefulset.name"])- set(attributes["dt.kubernetes.workload.name"], attributes["k8s.statefulset.name"]) where IsString(attributes["k8s.statefulset.name"])- set(attributes["dt.kubernetes.workload.kind"], "deployment") where IsString(attributes["k8s.deployment.name"])- set(attributes["dt.kubernetes.workload.name"], attributes["k8s.deployment.name"]) where IsString(attributes["k8s.deployment.name"])- set(attributes["dt.kubernetes.workload.kind"], "daemonset") where IsString(attributes["k8s.daemonset.name"])- set(attributes["dt.kubernetes.workload.name"], attributes["k8s.daemonset.name"]) where IsString(attributes["k8s.daemonset.name"])- set(attributes["dt.kubernetes.cluster.id"], attributes["k8s.cluster.uid"]) where IsString(attributes["k8s.cluster.uid"])log_statements:- context: resourcestatements: &k8s-statementsexporters:otlphttp:endpoint: ${env:DT_ENDPOINT}headers:Authorization: "Api-Token ${env:DT_API_TOKEN}"service:pipelines:logs:receivers: [filelog]processors: [k8sattributes,transform]exporters: [otlphttp]
Validate your settings to avoid any configuration issues.
Configure the following rbac.yaml
file with your Kubernetes instance, to allow the Collector to use the Kubernetes API with the service-account authentication type.
apiVersion: v1kind: ServiceAccountmetadata:labels:app: collectorname: collector---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:name: collectorlabels:app: collectorrules:- apiGroups:- ''resources:- 'pods'- 'namespaces'verbs:- 'get'- 'watch'- 'list'- apiGroups:- 'apps'resources:- 'replicasets'verbs:- 'get'- 'list'- 'watch'- apiGroups:- 'extensions'resources:- 'replicasets'verbs:- 'get'- 'list'- 'watch'---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:name: collectorlabels:app: collectorroleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: collectorsubjects:- kind: ServiceAccountname: collectornamespace: default
If you are running the Collector on GKE Autopilot, you need the following adjustments in the configuration:
/var/log/pods
to be read-only, otherwise the collector will not be able to access the log files
within that directory.Below is an example configuration for a Collector DaemonSet with the required volume mounts for gathering the pod logs:
apiVersion: apps/v1kind: DaemonSetmetadata:name: dynatrace-otel-collectorspec:selector:matchLabels:app.kubernetes.io/name: dynatrace-otel-collectortemplate:metadata:labels:app.kubernetes.io/instance: dynatrace-otel-collectorapp.kubernetes.io/name: dynatrace-otel-collectorspec:serviceAccountName: collectortolerations:# these tolerations are to have the daemonset runnable on control plane nodes# remove them if your control plane nodes should not run pods- key: node-role.kubernetes.io/control-planeoperator: Existseffect: NoSchedule- key: node-role.kubernetes.io/masteroperator: Existseffect: NoSchedulecontainers:- args: ["--config", "/conf/otel-collector-config.yaml"]env:- name: MY_POD_IPvalueFrom:fieldRef:apiVersion: v1fieldPath: status.podIPimage: ghcr.io/dynatrace/dynatrace-otel-collector/dynatrace-otel-collector:v0.19.0name: otel-collectorresources:limits:memory: 512MivolumeMounts:- name: dynatrace-otel-collector-configmountPath: /conf# read-only volumeMount for the directory containing the pod logs- name: logsmountPath: /var/logreadOnly: truevolumes:- configMap:name: dynatrace-otel-collector-configitems:- key: otel-collector-configpath: otel-collector-config.yamlname: dynatrace-otel-collector-config# hostPath volume containing the pod logs of the respective node the collector instance is running on- hostPath:path: /var/logname: logs
In the Collector configuration defined in otel-collector-config.yaml
, only the /var/log/pods
directory is required to be read by the filelog
receiver, and the /var/log/containers
directory
can be removed from the list of observed directories, as it is not used by GKE. This results in the following change of the filelog
receiver in the otel-collector-config.yaml
:
...receivers:filelog:include:# only include the /var/log/pods directory here, as the /var/log/containers directory is not used on GKE Autopilot- /var/log/pods/*/*/*.loginclude_file_name: falseinclude_file_path: truestart_at: endoperators:- id: container-parsertype: container...
For our configuration, we configured the following components.
Under receivers
, we specify the filelog
receiver as active receiver component for our Collector instance.
The Filelog receiver supports a number of configuration parameters, which enable you to customize its behavior. For the example, we use the following:
include
—Specifies the path pattern of the files we want to ingest.start_at
—Specifies if the receiver should read from the beginning of the file or, for the most recent entries only, the end.operators
—Configures the container
operator, which automatically parses each log entry.Under processors
, we specify the k8sattributes
processor with the following parameters:
extract
—Specifies which information should be extracted.pod_association
—Specifies how the pod information is linked to attributes.Under exporters
, we specify the default otlphttp
exporter and configure it with our Dynatrace API URL and the required authentication token, as set up and configured under Kubernetes Secrets.
Under service
, we assemble our receiver, processor, and exporter objects into pipelines for traces, metrics, and logs. These pipelines allow us to send OpenTelemetry signals via the Collector instance and have them automatically enriched with additional Kubernetes-specific details.