一、DaemonSet 到底解决什么问题

DaemonSet 的规则非常直接:在所有符合条件的节点上,各运行一个 Pod。

它和 Deployment 最大的不同,不是谁“更高级”,而是调度目标不同:

  • Deployment 关心的是总副本数
  • StatefulSet 关心的是稳定身份和顺序
  • DaemonSet 关心的是匹配节点覆盖率

因此只要有新节点加入集群,符合条件时 DaemonSet 就会自动补一份 Pod;节点移除后,对应 Pod 也会回收。

二、哪些场景最适合 DaemonSet

原文列出的典型场景非常标准:

  • 节点存储代理,如 Gluster、Ceph 等
  • 日志采集组件,如 Fluentd、Filebeat
  • 节点监控组件,如 Prometheus Node Exporter
  • 任何需要在每台节点都运行一个实例的基础设施服务

另外一个容易忽略的点是:DaemonSet 同样有命名空间隔离,但它通常直接管理 Pod,版本历史更多依赖 ControllerRevision

三、先创建一个最小可用的 DaemonSet

原始示例非常精简:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
        name: nginx

部署后可以直接观察它在不同节点上的落点:

kubectl create -f nginx-ds.yaml
kubectl get pods -o wide

如果集群有 5 个匹配节点,通常就会看到 5 个 Pod,且每个 Pod 分别落在不同节点上。

四、怎么只把 DaemonSet 下发到指定节点

很多人第一次用 DaemonSet 时会踩的坑是:它默认会覆盖所有匹配节点。如果你只想下发到一部分节点,最直接的办法就是先打标签,再做 nodeSelector

先给节点打标签:

kubectl label node k8s-node01 k8s-node02 disktype=ssd

如果要撤销标签:

kubectl label node k8s-node01 k8s-node02 disktype-

然后在 DaemonSet 里指定:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeSelector:
        disktype: ssd
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
        name: nginx

这样最终只会在带 disktype=ssd 的节点上生成 Pod。

五、理解 DaemonSet 的关键,不是 YAML,而是“覆盖逻辑”

看 DaemonSet 时,最重要的问题不是“我设了几个副本”,而是:

  • 哪些节点会命中选择条件
  • 每个命中节点是否只会有一个实例
  • 新节点加入后是否会自动补齐

只要这三个问题想清楚,DaemonSet 的使用场景就会非常明确:它不是用来部署业务副本的,而是用来铺设节点级基础能力的。