K8s学习笔记(十四) DaemonSet
在 Kubernetes 中,DaemonSet 是一种专门用于在集群所有节点(或指定节点)上运行相同 Pod 副本的工作负载控制器。它的核心特点是:只要节点存在于集群中,DaemonSet 就会确保该节点上有且仅有一个对应 Pod 在运行(新节点加入时自动部署,节点移除时自动清理),非常适合运行 “节点级服务”。
下面从 “为什么需要 DaemonSet”→核心特性→关键配置→实操案例→与 Deployment 的区别 逐步讲解,帮你快速掌握。
1 为什么需要 DaemonSet?
有些服务必须在集群的每个节点上运行(或指定节点),比如:
- 日志收集:如 Fluentd、Logstash,需要在每个节点上收集容器日志。
- 监控代理:如 Prometheus Node Exporter,需要在每个节点上采集节点指标(CPU、内存等)。
- 网络插件:如 Calico、Flannel,需要在每个节点上运行以提供网络功能。
- 存储插件:如 Ceph 客户端,需要在节点上运行以挂载分布式存储。
这些服务的核心需求是 “覆盖集群所有节点”,而普通的 Deployment(通过replicas
指定副本数)无法满足:
- 若集群节点数量变化(新增 / 删除节点),Deployment 不会自动调整副本分布(可能导致新节点上没有服务,旧节点上有多个)。
- 无法保证 “每个节点只运行一个副本”(Deployment 可能在一个节点上调度多个 Pod)。
DaemonSet 正是为解决这些问题设计的 —— 它直接与节点绑定,确保 “节点在,Pod 在;节点不在,Pod 清”。
2 DaemonSet 的核心特性(必懂)
- 节点全覆盖:默认在集群所有节点上运行一个 Pod 副本(可通过配置限制在特定节点)。
- 自动扩缩容:
- 新节点加入集群时,DaemonSet 自动在新节点上创建 Pod。
- 节点从集群移除时,DaemonSet 自动删除该节点上的 Pod。
- 单节点单副本:每个节点上最多运行一个该 DaemonSet 的 Pod(避免资源浪费或冲突)。
- 更新策略:支持滚动更新(默认)或替换更新,确保节点级服务升级时不中断。
3 DaemonSet 的关键配置(核心属性)
定义 DaemonSet 时,核心是控制 “哪些节点运行 Pod” 和 “如何更新 Pod”,关键配置如下:
3.1 节点选择:控制 Pod 运行在哪些节点
通过以下配置限制 Pod 仅在符合条件的节点上运行(默认无限制,所有节点均运行):
配置项 | 作用 | 示例 |
---|---|---|
spec.template.spec.nodeSelector | 节点标签选择器(仅在带指定标签的节点上运行) | disk: ssd (仅在有disk=ssd 标签的节点上运行) |
spec.template.spec.affinity.nodeAffinity | 更复杂的节点亲和性规则(如 “排除某类节点”“优先选某类节点”) | 见下文示例 |
spec.template.spec.tolerations | 容忍节点污点(允许 Pod 运行在有污点的节点上,如 master 节点) | 见下文示例 |
3.2 更新策略:控制 Pod 如何升级
当 DaemonSet 的 Pod 模板(spec.template
)更新时(如镜像版本变更),通过updateStrategy
控制更新方式:
策略类型 | 作用 | 适用场景 |
---|---|---|
RollingUpdate (默认) | 逐个节点更新:先删除旧 Pod,再创建新 Pod,确保服务不中断 | 生产环境(需持续提供服务) |
OnDelete | 仅在手动删除旧 Pod 后,才会创建新 Pod(需手动触发更新) | 测试环境(需严格控制更新时机) |
4 实操案例:部署一个 DaemonSet(监控节点指标)
以 “在所有节点上运行 Prometheus Node Exporter(监控节点指标)” 为例,完整步骤如下:
步骤 1:创建 DaemonSet
# 保存为daemonset-node-exporter.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:name: node-exporter # DaemonSet名称namespace: monitoring # 放在monitoring命名空间
spec:selector:matchLabels:app: node-exporter # 匹配Pod的标签template:metadata:labels:app: node-exporter # Pod标签spec:hostNetwork: true # 使用节点网络(方便采集主机端口指标)hostPID: true # 允许访问节点的PID命名空间(方便采集进程指标)# 容忍master节点的污点(默认master节点有污点,阻止普通Pod调度)tolerations:- key: node-role.kubernetes.io/mastereffect: NoScheduleoperator: Exists# 节点选择器(可选:仅在有"monitor=yes"标签的节点上运行)# nodeSelector:# monitor: "yes"containers:- name: node-exporterimage: prom/node-exporter:v1.5.0 # 监控镜像args:- --path.procfs=/host/proc # 挂载节点的proc目录- --path.sysfs=/host/sys # 挂载节点的sys目录volumeMounts:- name: procmountPath: /host/procreadOnly: true- name: sysmountPath: /host/sysreadOnly: truevolumes:- name: prochostPath:path: /proc # 节点的/proc目录- name: syshostPath:path: /sys # 节点的/sys目录# 更新策略:滚动更新(默认)updateStrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 1 # 最多允许1个节点的Pod不可用(控制更新速度)
步骤 2:部署并验证
# 创建命名空间(如果不存在)
kubectl create namespace monitoring# 部署DaemonSet
kubectl apply -f daemonset-node-exporter.yaml# 查看DaemonSet
kubectl get daemonset -n monitoring
# 输出示例(DESIRED和CURRENT等于节点数):
# NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
# node-exporter 3 3 3 3 3 <none> 1m# 查看Pod(每个节点上有一个,NAME包含节点名)
kubectl get pods -n monitoring -o wide
# 输出示例(3个节点,3个Pod,分别运行在不同节点):
# NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
# node-exporter-2f4x9 1/1 Running 0 1m 10.244.1.5 k8s-node-1 <none>
# node-exporter-5k7d3 1/1 Running 0 1m 10.244.2.3 k8s-node-2 <none>
# node-exporter-8s9z7 1/1 Running 0 1m 10.244.0.6 k8s-master <none> # 因为配置了tolerations,所以master节点也有
步骤 3:验证 “自动适应节点变化”
- 新增节点:向集群添加一个新节点(如
k8s-node-3
),等待几分钟后查看 Pod,会发现自动新增node-exporter-xxx
运行在k8s-node-3
上。 - 删除节点:从集群移除
k8s-node-2
,查看 Pod,node-exporter-5k7d3
会自动被删除。
5 DaemonSet vs Deployment(核心区别)
特性 | DaemonSet | Deployment |
---|---|---|
副本调度目标 | 每个节点(或指定节点)1 个副本 | 不绑定节点,按replicas 指定总副本数 |
扩缩容方式 | 随节点数量自动扩缩容(节点增减→Pod 增减) | 手动或 HPA 调整replicas (与节点数量无关) |
适用场景 | 节点级服务(日志、监控、网络插件) | 无状态服务(Web、API、微服务) |
节点亲和性 | 核心功能(默认覆盖所有节点,可限制节点) | 可选功能(仅用于优化调度,不强制节点分布) |
6 常见问题与排错
-
DaemonSet 的 Pod 在某些节点上未运行:
- 原因 1:节点有污点(Taint),而 Pod 没有对应的容忍(Toleration)。例如 master 节点默认有
node-role.kubernetes.io/master:NoSchedule
污点,需在 DaemonSet 中添加容忍(如案例中的tolerations
配置)。 - 原因 2:节点标签不匹配(如配置了
nodeSelector: {monitor: yes}
,但节点没有该标签)。 - 排查:
kubectl describe pod <pod名称> -n <命名空间>
,查看Events
中的调度失败原因(如 “node (s) had taint {xxx}, that the pod didn’t tolerate”)。
- 原因 1:节点有污点(Taint),而 Pod 没有对应的容忍(Toleration)。例如 master 节点默认有
-
更新 DaemonSet 后 Pod 未刷新:
- 原因:使用了
OnDelete
更新策略,需手动删除旧 Pod 才会创建新 Pod。 - 解决:切换为
RollingUpdate
(默认),或手动删除旧 Pod(kubectl delete pod <旧Pod名称>
)。
- 原因:使用了
-
需要限制 DaemonSet 的资源使用:
-
解决:在 Pod 模板中添加
resources.limits
和requests
,避免 Pod 占用节点过多资源:resources:limits:cpu: "100m"memory: "128Mi"requests:cpu: "50m"memory: "64Mi"
-
7 总结
DaemonSet 的核心价值是 “节点级服务全覆盖”,它的典型使用场景:
- 日志收集(Fluentd、Filebeat);
- 节点监控(Node Exporter、Grafana Agent);
- 网络插件(Calico、Flannel、Weave);
- 存储插件(Ceph-CSI、GlusterFS 客户端);
- 安全代理(节点级防火墙、入侵检测)。