一、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 的使用场景就会非常明确:它不是用来部署业务副本的,而是用来铺设节点级基础能力的。