K8s Node Agent (DaemonSet)
Per-node DaemonSet that scrapes kubelet and host metrics, tails pod logs with the container parser and file_storage checkpoints, enriches everything with k8sattributes, and forwards to the in-cluster gateway.
The per-node half of a Kubernetes setup, meant to run as a DaemonSet: kubeletstats scrapes container, pod, node, and volume metrics from the local kubelet; hostmetrics reads CPU, memory, load, disk, network, and filesystem from the node under `/hostfs`; and filelog tails pod logs with the `container` operator handling docker, containerd, and CRI-O formats. k8sattributes enriches everything with namespace, deployment, pod, and container metadata, associating by connection first and pod UID as the fallback. It forwards over OTLP to an in-cluster gateway at `otel-gateway.observability.svc.cluster.local` — change that to wherever your gateway Service lives. File offsets checkpoint to file_storage so a pod restart doesn't replay logs. It needs the usual DaemonSet privileges: a service account that can read the kubelet API and hostPath mounts for `/var/log` and `/hostfs`; `insecure_skip_verify` is on because kubelets commonly serve self-signed certificates.
Before you use this
Sends data to
You'll need to set these before it runs
K8S_NODE_NAMEThe configuration
# OpenTelemetry Collector Configuration
# Generated by Telflo
receivers:
kubeletstats:
auth_type: 'serviceAccount'
endpoint: '${env:K8S_NODE_NAME}:10250'
insecure_skip_verify: true
collection_interval: '30s'
metric_groups:
- 'container'
- 'pod'
- 'node'
- 'volume'
hostmetrics:
collection_interval: '30s'
root_path: '/hostfs'
scrapers:
cpu: null
memory: null
load: null
disk: null
network: null
filesystem: null
filelog:
include:
- '/var/log/pods/*/*/*.log'
include_file_path: true
start_at: 'end'
storage: 'file_storage'
operators:
- id: 'container-parser'
type: 'container'
max_log_size: 102400
retry_on_failure:
enabled: true
processors:
memory_limiter:
check_interval: '1s'
limit_percentage: 85
spike_limit_percentage: 20
k8sattributes:
passthrough: false
filter:
node_from_env_var: 'K8S_NODE_NAME'
extract:
otel_annotations: true
metadata:
- 'k8s.namespace.name'
- 'k8s.deployment.name'
- 'k8s.node.name'
- 'k8s.pod.name'
- 'k8s.pod.uid'
- 'k8s.container.name'
pod_association:
- sources:
- from: 'connection'
- sources:
- from: 'resource_attribute'
name: 'k8s.pod.uid'
batch:
timeout: '10s'
exporters:
otlp:
endpoint: 'otel-gateway.observability.svc.cluster.local:4317'
tls:
insecure: true
extensions:
file_storage:
directory: '/var/lib/otelcol'
create_directory: true
service:
extensions: [file_storage]
pipelines:
metrics:
receivers: [kubeletstats, hostmetrics]
processors: [memory_limiter, k8sattributes, batch]
exporters: [otlp]
logs:
receivers: [filelog]
processors: [memory_limiter, k8sattributes, batch]
exporters: [otlp]
Validated against otelcol-contrib v0.147.0. Fill in the ${env:…} placeholders before running it.