Node-level agents for logging, monitoring, networking and storage are all DaemonSets.
A DaemonSet ensures one pod runs on each eligible node. When a node joins, it gets a pod; when it leaves, the pod goes with it. There is no replicas field.
Typical uses:
- log collectors (Fluent Bit, Vector) reading
/var/logfrom the host, - metrics agents (node-exporter, Datadog agent),
- network plugins (Cilium, Calico) and kube-proxy,
- CSI storage node plugins.
Restrict which nodes run it with nodeSelector or node affinity in the pod template (only GPU nodes, only Linux nodes). Control-plane and specially tainted nodes are skipped unless the DaemonSet's pods have matching tolerations; agents that must run everywhere usually tolerate everything.
DaemonSet pods often need host access: hostPath volumes, hostNetwork: true, or extra privileges. Grant only what is needed; these are high-value targets.
Updates use RollingUpdate with maxUnavailable (default 1 node at a time), or OnDelete to update a node only when you delete its pod by hand.
Set resource requests carefully: a DaemonSet's requests are reserved on every node, so 200Mi times 100 nodes adds up.
Example
apiVersion: apps/v1
kind: DaemonSet
metadata: {name: node-logs, namespace: logging}
spec:
selector: {matchLabels: {app: node-logs}}
template:
metadata: {labels: {app: node-logs}}
spec:
tolerations:
- {operator: Exists} # run on tainted nodes too
containers:
- name: fluent-bit
image: fluent/fluent-bit:4.0
resources: {requests: {cpu: 50m, memory: 64Mi}, limits: {memory: 128Mi}}
volumeMounts: [{name: varlog, mountPath: /var/log, readOnly: true}]
volumes:
- {name: varlog, hostPath: {path: /var/log}}
# kubectl -n logging get ds node-logs # DESIRED = number of nodesRemember
- One pod per eligible node; follows nodes in and out
- Use nodeSelector/affinity to target, tolerations to reach tainted nodes
- Requests are paid on every node
Watch out for
- Forgetting tolerations, so the agent silently skips tainted node pools.