Skip to content

DaemonSet

DaemonSet 用来保证符合条件的每个节点都运行一个 Pod。日志采集、节点监控、CNI、CSI 节点插件、kube-proxy 这类组件都很适合用 DaemonSet:它们不服务某个业务副本,而是贴着节点工作。

Deployment 关心副本数,DaemonSet 关心节点覆盖率。节点新增时自动补一个 Pod,节点删除时对应 Pod 跟着消失。排查 DaemonSet 时,重点是哪些节点应该有 Pod、哪些节点没有、为什么没有调度上去。

一、基本结构

一个日志 Agent 的 DaemonSet:

yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-agent
  namespace: logging
spec:
  selector:
    matchLabels:
      app: log-agent
  template:
    metadata:
      labels:
        app: log-agent
    spec:
      serviceAccountName: log-agent
      containers:
        - name: fluent-bit
          image: fluent/fluent-bit:3.2
          resources:
            requests:
              cpu: 50m
              memory: 64Mi
            limits:
              cpu: 500m
              memory: 256Mi
          volumeMounts:
            - name: varlog
              mountPath: /var/log
              readOnly: true
      volumes:
        - name: varlog
          hostPath:
            path: /var/log

DaemonSet 通常会挂载宿主机目录、读取节点日志、访问 kubelet 或容器运行时 socket,因此权限比普通业务 Pod 更敏感。镜像来源、ServiceAccount 权限、hostPath 范围都要收口。

二、节点选择和污点容忍

DaemonSet 默认会在所有可调度节点上创建 Pod。只希望跑在部分节点时,用 nodeSelector 或亲和性:

yaml
spec:
  template:
    spec:
      nodeSelector:
        node-role.kubernetes.io/worker: "true"

控制平面节点常带有污点,普通 Pod 不会调度上去。节点级组件如果也要覆盖控制平面节点,需要配置 tolerations:

yaml
spec:
  template:
    spec:
      tolerations:
        - key: "node-role.kubernetes.io/control-plane"
          operator: "Exists"
          effect: "NoSchedule"

监控 Agent、日志 Agent 是否覆盖控制平面节点,取决于集群运维策略。控制平面日志和节点指标也需要采集时,DaemonSet 要能容忍对应污点。

三、滚动更新

DaemonSet 支持滚动更新:

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

maxUnavailable: 1 表示一次最多让一个节点上的 Agent 不可用。日志采集、监控采集这类组件升级时,过大的不可用比例会造成短时间采集断档。

查看更新状态:

bash
kubectl rollout status daemonset/log-agent -n logging
kubectl rollout history daemonset/log-agent -n logging

回滚:

bash
kubectl rollout undo daemonset/log-agent -n logging

DaemonSet 回滚只负责恢复 Pod 模板,不会恢复外部系统配置。比如日志后端地址改错,回滚 YAML 能恢复采集 Agent,但后端里已经产生的异常数据不会自动清掉。

四、常见系统组件

Kubernetes 集群里常见的 DaemonSet:

组件作用
kube-proxy在每个节点维护 Service 转发规则
CNI 节点组件配置 Pod 网络、路由、策略或 eBPF 程序
CSI node plugin在节点上完成卷挂载、卸载
node-exporter采集 Linux 主机指标
日志 Agent读取节点日志文件并发送到日志后端
安全 Agent节点安全审计、运行时检测

这些组件异常时,影响面通常跟节点有关。比如某个节点的 CNI DaemonSet Pod 异常,该节点上的业务 Pod 可能都出现网络问题;某个节点的 CSI 插件异常,该节点上的 PVC 挂载会失败。

五、查看覆盖情况

bash
kubectl get daemonset -A
kubectl get daemonset log-agent -n logging -o wide
kubectl get pod -n logging -l app=log-agent -o wide

DaemonSet 状态字段:

字段含义
DESIRED期望覆盖的节点数
CURRENT当前已创建的 Pod 数
READYReady 的 Pod 数
UP-TO-DATE使用最新模板的 Pod 数
AVAILABLE可用 Pod 数

如果 DESIRED 小于节点数,要看 nodeSelector、亲和性和污点;如果 CURRENT 等于 DESIREDREADY 不足,要看 Pod 事件、镜像、权限、探针和宿主机挂载。

六、排查路径

bash
# 看哪些节点没有对应 Pod
kubectl get pod -n logging -l app=log-agent -o wide

# 看 DaemonSet 选择器、更新策略和事件
kubectl describe daemonset log-agent -n logging

# 看某个 Pod 在节点上为什么没起来
kubectl describe pod <pod-name> -n logging
kubectl logs <pod-name> -n logging

几个常见原因:

现象可能原因
某些节点没有 PodnodeSelector 不匹配、污点没有 toleration、节点不可调度
Pod Pending资源不足、镜像拉取失败、hostPath 路径不存在
Pod CrashLoopBackOff配置文件错误、权限不足、后端地址不可达
升级卡住新版本探针失败、maxUnavailable 太小且旧 Pod 退出异常

DaemonSet 本身很简单,真正复杂的是它经常触碰节点层能力。hostNetwork、hostPID、privileged、hostPath 都会扩大权限,适合写清楚理由和范围。