Begriff
DaemonSet
Warum wichtig?
Dieser Begriff ist ein Knoten im SengakujiWorks-Wissensnetz. Nutze Level 0 für die erste Einordnung, Level 1 für Praxis, Level 2 für technische Struktur und Level 3 für Grenzen, Fallstricke und Expertenkontext.
In Kubernetes willst du meistens: "Starte 3 Kopien meiner App, egal wo." (Das macht ein Deployment). Aber manchmal willst du: "Starte genau eine Kopie auf jedem Computer (Node) im Cluster". Beispiele:
- Ein Programm, das Logs sammelt (Fluentd).
- Ein Programm, das Metriken misst (Prometheus Node Exporter).
- Ein Netzwerk-Plugin (CNI). Das ist ein DaemonSet. Wenn du einen neuen Node zum Cluster hinzufügst, startet Kubernetes dort automatisch den DaemonSet-Pod. Wenn du einen Node entfernst, wird der Pod gelöscht (und nicht woanders neu gestartet).
Merksatz: Ein Kubernetes Workload-Controller, der sicherstellt, dass auf allen (oder bestimmten) Nodes genau eine Instanz (Replica) eines Pods läuft.
YAML:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd
template:
metadata:
labels:
name: fluentd
spec:
containers:
- name: fluentd
image: fluent/fluentd:v1
Einfach kubectl apply -f ds.yaml.
Du siehst dann einen Pod pro Node.
Wenn du 100 Nodes hast, hast du 100 Pods.
1. Taints & Tolerations
DaemonSets sind hartnäckig.
Normalerweise plant der Scheduler keine Pods auf den "Master Nodes" (Control Plane), weil diese "Taints" haben (NoSchedule).
DaemonSets (wie Netzwerktreiber) müssen aber dort laufen.
Deshalb ignorieren ("tolerieren") DaemonSets standardmäßig gewisse Taints (z. B. DiskPressure, MemoryPressure).
Für Master-Nodes musst du manuell eine Toleration hinzufügen:
key: node-role.kubernetes.io/master, effect: NoSchedule.
2. Rolling Updates
Auch DaemonSets müssen geupdated werden (v1 -> v2).
Früher (vor K8s 1.6) musste man sie manuell löschen.
Heute unterstützt DaemonSet Rolling Updates.
Strategie: maxUnavailable.
Default ist 1. K8s stoppt Pod auf Node 1, updated, startet neu. Dann Node 2.
Dies verhindert, dass das gesamte Log-System gleichzeitig ausfällt.
3. Node Selector / Affinity
Du willst das DaemonSet vielleicht nicht auf allen Nodes.
Beispiel: GPU-Treiber nur auf GPU-Nodes.
Lösung: nodeSelector: accelerator=nvidia.
Dann läuft der Pod nur auf Nodes mit diesem Label.
Der DaemonSet Controller Lifecycle
Historisch (vor Kubernetes v1.12) planten DaemonSets die Pods komplett am eigentlichen Kube-Scheduler vorbei. Der DaemonSet-Controller fügte Pods einfach direkt mit dem fest eingetragenen nodeName in etcd ein.
Dies führte zu Ressourcen-Konflikten, da der Scheduler oft dachte, er hätte Platz für ein Deployment, ignorierte aber den asynchron landenden DaemonSet-Pod.
Heute orchestriert der Controller die Pods mit Hilfe des regulären Schedulers. Hierfür erzeugt er extrem spezifische nodeAffinity Regeln in der Pod-Spec. Der Scheduler entscheidet die Platzierung nicht, validiert aber die Ressourcen. Dies ist essenziell für Priority und Preemption: Ein kritischer DaemonSet-Pod kann sich nun auf einem vollen Node Platz "freikämpfen", indem der Kubelet unwichtigere Deployment-Pods abschießt (Eviction).
HostNetwork und Privileged Mode (Risiken)
Da DaemonSets fast immer eng mit der Hardware verzahnt sind (Storage-CSI, CNI-Network, Monitoring), nutzen sie oft Features, die normale Pods niemals erhalten.
Monitoring-Tools (Datadog, Prometheus Node Exporter) brauchen oftmals hostNetwork: true. Das heißt, der Pod bricht aus dem isolierten Container-Netzwerk (Overlay) aus und bindet seine Ports direkt an das eth0-Interface des Nodes. Erlaubt ist auch das Start-Kommando im --privileged Modus mit Mounts auf /proc oder /sys des Hosts.
Bricht ein Angreifer in diesen DaemonSet Container ein, hat er sofort vollen Root-Administrationszugriff auf die Linux-Maschine des Worker-Nodes. Daher sichert man diese Pods oft mit massiven AppArmor, SELinux Policies oder seccomp Profilen ab.
Node Cordons und Upgrades
Wenn du ein Kubernetes Cluster upgradest, "cordonst" (Sperren für neues Scheduling) und "drainst" (Evakuieren aller Pods) du Node für Node.
Die Tücke: Der kubectl drain Befehl weigert sich standardmäßig zu operieren, wenn DaemonSet-Pods laufen. Im DaemonSet verankerte CNI/CSI Pods können schlicht nicht wegmigriert werden, da sie auf anderen Nodes bereits exakt einmal laufen.
Lösung: Der Flag --ignore-daemonsets teilt dem Drainer mit, alle Application-Pods zu räumen und die harten DaemonSets zu ignorieren. Sie werden dann in dem Moment brutal gekillt, in dem der Node in den Linux-Reboot geht.
Quick-Check
Unterschied zu ReplicaSet?
ReplicaSet sagt "Ich will X Kopien". DaemonSet sagt "Ich will X Kopien PRO NODE". ReplicaSet kümmert sich nicht, wo sie laufen (können alle auf Node 1 sein).Was passiert im "Scale Up"?
Wenn der Cluster Auto-Scaler neue Nodes hinzufügt (weil Last hoch ist), bemerkt der DaemonSet-Controller das sofort und startet dort seinen Pod. Das ist wichtig, damit der neue Node sofort Logs sendet und im Netzwerk ist.Static Pods?
DaemonSets werden vom API-Server verwaltet. Static Pods (z. B. etcd, kube-apiserver selbst) werden direkt vom Kubelet auf dem Node gestartet (yaml-Datei in /etc/kubernetes/manifests). Ähnliches Konzept (einer pro Node), aber Static Pods laufen "außerhalb" der normalen Control Plane Logik.