23 DaemonSets: Node-spezifische Services in Kubernetes

23.1 Einführung

DaemonSets sind eine spezialisierte Controller-Ressource zur Verwaltung von Services, die auf jedem Node im Cluster laufen müssen. Während Deployments und StatefulSets eine bestimmte Anzahl von Replikas verwalten, stellt ein DaemonSet sicher, dass genau ein Pod pro Node (oder einer Teilmenge von Nodes) ausgeführt wird.

23.2 Was sind DaemonSets?

Ein DaemonSet verwaltet Pods, die auf jedem Node des Clusters laufen und typischerweise infrastrukturelle Services bereitstellen. Diese Services benötigen direkten Zugriff auf Node-Ressourcen und müssen auf jedem Node verfügbar sein, um clusterweit zu funktionieren.

Kernmerkmale: - Ein Pod pro Node: Automatische Bereitstellung auf allen verfügbaren Nodes - Automatische Node-Integration: Neue Nodes erhalten automatisch einen Pod - Node-lokale Services: Direkter Zugriff auf Host-Ressourcen und Node-spezifische Daten - Cluster-weite Abdeckung: Gewährleistung konsistenter Services auf allen Nodes

23.3 Abgrenzung zu anderen Controllern

Merkmal Deployment StatefulSet DaemonSet
Pod-Anzahl Benutzer-definiert Benutzer-definiert Ein Pod pro Node
Pod-Verteilung Scheduler-entschieden Sequenziell Node-basiert
Speicher Shared/Ephemeral Persistent pro Pod Host-Volumes/Ephemeral
Skalierung Manuell/automatisch Manuell Automatisch bei Node-Änderungen
Node-Zugriff Eingeschränkt Eingeschränkt Vollzugriff möglich
Typische Anwendungen Web-Services Datenbanken Monitoring, Logging, Networking

23.4 Kernkonzepte

23.4.1 Automatische Node-Abdeckung

DaemonSets überwachen kontinuierlich den Cluster-Zustand: - Neue Nodes erhalten automatisch einen DaemonSet-Pod - Entfernte Nodes führen zur automatischen Pod-Löschung - Node-Labels und Selectors bestimmen die Ziel-Nodes

23.4.2 Host-Integration

DaemonSet-Pods haben typischerweise erweiterte Berechtigungen: - Zugriff auf Host-Dateisystem über Volume-Mounts - Host-Netzwerk-Zugriff für Netzwerk-Services - Privilegierte Container für System-Level-Operationen - Direct-Access auf Node-Metriken und Logs

23.4.3 Node-Selektion

Flexible Steuerung der Pod-Platzierung: - Node Selectors für spezifische Node-Typen - Node Affinity für komplexe Placement-Regeln - Tolerations für Tainted Nodes - Field Selectors für Node-Eigenschaften

23.5 Häufige Anwendungsfälle

23.5.1 Logging-Systeme

23.5.2 Monitoring und Metriken

23.5.3 Netzwerk-Services

23.5.4 Storage und CSI

23.5.5 Security und Compliance

23.6 Praktisches Beispiel: Node Exporter für Prometheus

Hier ist ein vollständiges Beispiel für ein Node Exporter DaemonSet:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
  labels:
    app: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true
      hostPID: true
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule
      containers:
      - name: node-exporter
        image: prom/node-exporter:v1.6.1
        args:
        - '--path.procfs=/host/proc'
        - '--path.sysfs=/host/sys'
        - '--path.rootfs=/host/root'
        - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
        - '--web.listen-address=:9100'
        ports:
        - containerPort: 9100
          protocol: TCP
          name: metrics
        resources:
          limits:
            cpu: 200m
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 100Mi
        volumeMounts:
        - name: proc
          mountPath: /host/proc
          readOnly: true
        - name: sys
          mountPath: /host/sys
          readOnly: true
        - name: root
          mountPath: /host/root
          mountPropagation: HostToContainer
          readOnly: true
        securityContext:
          runAsNonRoot: true
          runAsUser: 65534
      volumes:
      - name: proc
        hostPath:
          path: /proc
      - name: sys
        hostPath:
          path: /sys
      - name: root
        hostPath:
          path: /
---
apiVersion: v1
kind: Service
metadata:
  name: node-exporter
  namespace: monitoring
  labels:
    app: node-exporter
spec:
  type: ClusterIP
  ports:
  - port: 9100
    targetPort: 9100
    name: metrics
  selector:
    app: node-exporter

23.6.1 Service Monitor für Prometheus

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: node-exporter
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics

23.7 Node-Selektion und Scheduling

23.7.1 Basic Node Selector

spec:
  template:
    spec:
      nodeSelector:
        disktype: ssd
        node-type: worker

23.7.2 Erweiterte Node Affinity

spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/arch
                operator: In
                values:
                - amd64
                - arm64
              - key: node-role.kubernetes.io/worker
                operator: Exists
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            preference:
              matchExpressions:
              - key: node-zone
                operator: In
                values:
                - zone-a

23.7.3 Tolerations für Tainted Nodes

spec:
  template:
    spec:
      tolerations:
      # Master/Control-Plane Nodes
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule
      # Custom Taints
      - key: dedicated
        operator: Equal
        value: logging
        effect: NoSchedule
      # Tolerations für Node-Probleme
      - key: node.kubernetes.io/not-ready
        operator: Exists
        effect: NoExecute
        tolerationSeconds: 300

23.8 Update-Strategien

23.8.1 Rolling Update (Standard)

spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1

Verhalten: - Updates erfolgen Node für Node - maxUnavailable begrenzt gleichzeitige Updates - Gewährleistet kontinuierliche Service-Verfügbarkeit

23.8.2 OnDelete

spec:
  updateStrategy:
    type: OnDelete

Anwendung: - Manuelle Kontrolle über Update-Timing - Kritische Services mit speziellen Update-Anforderungen - Koordinierte Updates mit externen Systemen

23.9 Erweiterte Konfiguration

23.9.1 Privilegierte Container

spec:
  template:
    spec:
      containers:
      - name: system-collector
        securityContext:
          privileged: true
          runAsUser: 0
        volumeMounts:
        - name: host-var-log
          mountPath: /var/log
          readOnly: true
        - name: host-dev
          mountPath: /dev
          readOnly: true
      volumes:
      - name: host-var-log
        hostPath:
          path: /var/log
      - name: host-dev
        hostPath:
          path: /dev

23.9.2 Host-Network-Zugriff

spec:
  template:
    spec:
      hostNetwork: true
      hostPID: true
      dnsPolicy: ClusterFirstWithHostNet

Hinweis: Host-Network ermöglicht direkten Zugriff auf Node-Netzwerk, erfordert aber sorgfältige Port-Verwaltung.

23.10 Überwachung und Debugging

23.10.1 DaemonSet-Status prüfen

kubectl get daemonset -n monitoring
kubectl describe daemonset node-exporter -n monitoring

23.10.2 Pod-Verteilung analysieren

kubectl get pods -o wide -l app=node-exporter
kubectl get nodes --show-labels

23.10.3 Node-Coverage überprüfen

# Alle Nodes
kubectl get nodes --no-headers | wc -l

# DaemonSet Pods
kubectl get pods -l app=node-exporter --no-headers | wc -l

# Fehlende Pods identifizieren
kubectl get pods -l app=node-exporter -o wide | \
  awk '{print $7}' | sort | uniq > /tmp/nodes-with-pods
kubectl get nodes --no-headers | \
  awk '{print $1}' | sort > /tmp/all-nodes
diff /tmp/all-nodes /tmp/nodes-with-pods

23.11 Best Practices

23.11.1 Resource Limits definieren

resources:
  limits:
    cpu: 200m
    memory: 200Mi
  requests:
    cpu: 100m
    memory: 100Mi

Wichtig: Resource Limits verhindern, dass ein DaemonSet-Pod einen Node destabilisiert.

23.11.2 Health Checks konfigurieren

livenessProbe:
  httpGet:
    path: /metrics
    port: 9100
  initialDelaySeconds: 30
  periodSeconds: 10
readinessProbe:
  httpGet:
    path: /metrics
    port: 9100
  initialDelaySeconds: 5
  periodSeconds: 5

23.11.3 Security Context optimieren

securityContext:
  runAsNonRoot: true
  runAsUser: 65534
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  capabilities:
    drop:
    - ALL
    add:
    - NET_BIND_SERVICE  # Nur wenn erforderlich

23.11.4 Pod Disruption Budgets

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: node-exporter-pdb
spec:
  minAvailable: 80%
  selector:
    matchLabels:
      app: node-exporter

Hinweis: PDBs sind für DaemonSets besonders wichtig, da sie kritische Node-Services schützen.

23.12 Troubleshooting

23.12.1 Pod startet nicht auf bestimmten Nodes

Symptom: DaemonSet-Pods fehlen auf einzelnen Nodes

Diagnose:

kubectl describe node <node-name>
kubectl get events --field-selector involvedObject.name=<pod-name>

Häufige Ursachen und Lösungen: - Node Taints: Tolerations hinzufügen oder Node un-tainting - Resource Constraints: Node-Kapazitäten und Resource Requests prüfen - Node Selectors: Label-Matching überprüfen - Image Pull Issues: Registry-Zugriff und Image-Verfügbarkeit validieren

23.12.2 Performance-Probleme durch DaemonSet

Symptom: Node-Performance degradiert nach DaemonSet-Deployment

Diagnose:

kubectl top nodes
kubectl top pods -l app=<daemonset-name>

Lösungsansätze: - Resource Limits reduzieren - CPU/Memory Requests optimieren - Sampling-Intervalle anpassen - I/O-intensive Operationen begrenzen

23.12.3 Updates schlagen fehl

Symptom: Rolling Update hängt oder schlägt fehl

Diagnose:

kubectl rollout status daemonset/<name>
kubectl describe daemonset <name>

Troubleshooting: - Pod-Readiness überprüfen - Health Check Timeouts anpassen - maxUnavailable Parameter optimieren - Node-Kapazitäten während Updates überwachen

23.13 Sicherheitsaspekte

23.13.1 Network Policies für DaemonSets

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: node-exporter-netpol
spec:
  podSelector:
    matchLabels:
      app: node-exporter
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 9100
  egress:
  - {}  # Ausgehender Traffic erlaubt

23.13.2 Pod Security Standards

apiVersion: v1
kind: SecurityContext
metadata:
  name: restricted-scc
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
  - securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
        - ALL

23.13.3 RBAC für privilegierte DaemonSets

apiVersion: v1
kind: ServiceAccount
metadata:
  name: node-exporter
  namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-exporter
rules:
- apiGroups: [""]
  resources: ["nodes", "nodes/metrics"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: node-exporter
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: node-exporter
subjects:
- kind: ServiceAccount
  name: node-exporter
  namespace: monitoring

23.14 Erweiterte Patterns

23.14.1 Init Container für Setup

spec:
  template:
    spec:
      initContainers:
      - name: node-setup
        image: alpine:3.18
        command: ['sh', '-c', 'sysctl -w vm.max_map_count=262144']
        securityContext:
          privileged: true
        volumeMounts:
        - name: host-sys
          mountPath: /host/sys
      containers:
      - name: main-app
        # ... Hauptcontainer-Konfiguration

23.14.2 Multi-Container DaemonSets

spec:
  template:
    spec:
      containers:
      - name: log-collector
        image: fluentd:v1.16
        volumeMounts:
        - name: host-logs
          mountPath: /var/log
      - name: metrics-exporter
        image: node-exporter:latest
        ports:
        - containerPort: 9100
      volumes:
      - name: host-logs
        hostPath:
          path: /var/log

23.14.3 DaemonSet mit ConfigMap-Integration

apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-config
data:
  fluent.conf: |
    <source>
      @type tail
      path /var/log/containers/*.log
      pos_file /var/log/fluentd-containers.log.pos
      tag kubernetes.*
      format json
    </source>
---
spec:
  template:
    spec:
      containers:
      - name: fluentd
        volumeMounts:
        - name: config
          mountPath: /fluentd/etc
      volumes:
      - name: config
        configMap:
          name: fluentd-config

23.15 Performance-Optimierung

23.15.1 CPU und Memory Tuning

resources:
  requests:
    cpu: 50m      # Niedrige Baseline
    memory: 64Mi
  limits:
    cpu: 200m     # Burst-Kapazität
    memory: 128Mi

23.15.2 I/O-Optimierung

volumeMounts:
- name: host-logs
  mountPath: /var/log
  readOnly: true              # Read-only wenn möglich
- name: tmp-storage
  mountPath: /tmp
volumes:
- name: tmp-storage
  emptyDir:
    sizeLimit: 1Gi           # Begrenzte temporäre Speicher

23.15.3 Netzwerk-Performance

spec:
  template:
    spec:
      hostNetwork: false        # Vermeiden wenn nicht erforderlich
      dnsPolicy: ClusterFirst   # Optimierte DNS-Auflösung