Kubernetes DaemonSet 详细介绍

文章目录
-
- [Kubernetes DaemonSet 详细介绍](#Kubernetes DaemonSet 详细介绍)
-
- [1. 主要用途](#1. 主要用途)
- [2. 工作原理](#2. 工作原理)
- [3. 调度机制](#3. 调度机制)
-
- [3.1 nodeSelector](#3.1 nodeSelector)
- [3.2 节点亲和性 (nodeAffinity)](#3.2 节点亲和性 (nodeAffinity))
- [3.3 污点和容忍度 (Taints and Tolerations)](#3.3 污点和容忍度 (Taints and Tolerations))
- [4. 创建与管理](#4. 创建与管理)
- [5. Pod 调度细节](#5. Pod 调度细节)
- [6. 更新策略](#6. 更新策略)
-
- [6.1 RollingUpdate(默认)](#6.1 RollingUpdate(默认))
- [6.2 OnDelete](#6.2 OnDelete)
- [7. 回滚](#7. 回滚)
- [8. 与 Deployment 的区别](#8. 与 Deployment 的区别)
- [9. 常见用例示例](#9. 常见用例示例)
-
- [9.1 在每个节点运行 Fluentd 收集日志](#9.1 在每个节点运行 Fluentd 收集日志)
- [9.2 在每个节点运行 Node Exporter](#9.2 在每个节点运行 Node Exporter)
- [10. 高级特性与注意事项](#10. 高级特性与注意事项)
- [11. 总结](#11. 总结)
DaemonSet 是 Kubernetes 中一种重要的控制器资源,它确保在集群中的 所有(或部分)节点 上运行一个 Pod 的副本。当有新节点加入集群时,DaemonSet 会自动在该节点上创建指定的 Pod;当节点从集群中移除时,这些 Pod 也会被回收。删除 DaemonSet 将清理它之前创建的所有 Pod。
【冷知识】DaemonSet 的翻译:官方/技术文档中通常不翻译,如果硬要翻译,可以翻译为:守护进程集(借鉴了 Linux 系统中"守护进程"(Daemon)的概念,指在每个节点上长期运行的后台任务。这个翻译比较贴切地表达了它在每个节点上运行"守护"角色的含义。)
1. 主要用途
DaemonSet 通常用于部署那些需要在每个节点上都运行的后台支撑服务,典型的应用场景包括:
- 日志收集:如 Fluentd、Logstash,用于采集每个节点的容器日志。
- 监控代理:如 Prometheus Node Exporter、Datadog Agent,收集节点级别的指标。
- 集群存储守护进程:如 GlusterFS、Ceph 的客户端 daemon,为节点提供持久化存储支持。
- 网络插件 :如 Calico、Flannel 的节点代理(如
calico-node、flanneld),实现节点网络互通。 - 安全与合规:如运行节点扫描、入侵检测 agent。
- 系统组件 :如
kube-proxy本身也常以 DaemonSet 形式运行,确保每个节点都有网络代理。
2. 工作原理
DaemonSet 控制器运行在 Kubernetes 控制平面中,持续监控集群节点的状态。它的核心逻辑是:
- 每当一个新节点添加到集群时,控制器检查该节点是否需要运行 DaemonSet 的 Pod(根据调度约束)。
- 如果需要,且该 Pod 尚未在该节点上运行,控制器就会创建 Pod,并将其绑定到目标节点(绕过默认调度器)。
- 当节点被删除时,控制器自动回收该节点上的对应 Pod。
- 当 DaemonSet 被更新(如镜像版本变更)时,控制器根据更新策略逐步替换旧的 Pod。
3. 调度机制
DaemonSet 创建的 Pod 默认会被调度到所有节点上,但可以通过以下方式限制 Pod 运行的节点范围:
3.1 nodeSelector
在 DaemonSet 的 Pod 模板中设置 spec.nodeSelector,只有标签匹配的节点才会运行 Pod。
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: my-daemon
spec:
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
nodeSelector:
disktype: ssd # 仅 disktype=ssd 的节点运行
containers:
- name: main
image: myimage
3.2 节点亲和性 (nodeAffinity)
使用更灵活的节点亲和性规则,例如要求节点在某个区域,或优先选择某些节点。
yaml
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1
3.3 污点和容忍度 (Taints and Tolerations)
如果节点设置了污点(Taint),DaemonSet 的 Pod 必须定义对应的容忍度(Toleration)才能在该节点上运行。这常用于隔离专用节点(如 GPU 节点、基础设施节点)。
yaml
spec:
template:
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
4. 创建与管理
DaemonSet 使用 YAML 定义,结构类似于 Deployment,但没有 replicas 字段(副本数由节点数量决定)。关键字段:
apiVersion: apps/v1kind: DaemonSetmetadata: 名称、标签等spec:selector: 选择器,必须与 Pod 模板的标签匹配。template: Pod 模板,定义 Pod 的规范(容器、卷、环境变量等)。updateStrategy: 更新策略(见下文)。minReadySeconds: Pod 被认为可用的最短时间。revisionHistoryLimit: 保留的历史版本数量。
创建 DaemonSet:
bash
kubectl apply -f daemonset.yaml
查看 DaemonSet 状态:
bash
kubectl get daemonsets
kubectl describe daemonset <name>
5. Pod 调度细节
DaemonSet 控制器在创建 Pod 时,会直接在 Pod 的 spec.nodeName 字段中指定目标节点,从而绕过 Kubernetes 调度器。这意味着:
- 即使节点有资源压力、调度器不可用,DaemonSet 依然能尝试将 Pod 调度到节点上(但节点必须满足资源要求,否则 Pod 会处于 Pending 状态)。
- 因此,DaemonSet 通常用于部署关键的系统级守护进程,它们应该尽量保证在节点上运行,除非明确排除。
6. 更新策略
DaemonSet 支持两种更新策略:
6.1 RollingUpdate(默认)
逐步替换旧的 Pod。可以通过 spec.updateStrategy.rollingUpdate.maxUnavailable 控制同时不可用的 Pod 数量(绝对值或百分比),避免全部中断。
yaml
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
当 DaemonSet 模板变化后,执行 kubectl rollout status daemonset/<name> 可以查看更新进度。
6.2 OnDelete
只有手动删除 Pod 时,才会创建新的 Pod。适用于需要逐个节点手动控制的场景。
yaml
updateStrategy:
type: OnDelete
7. 回滚
DaemonSet 支持版本回滚,类似于 Deployment:
bash
# 查看历史版本
kubectl rollout history daemonset <name>
# 回滚到上一个版本
kubectl rollout undo daemonset <name>
# 回滚到指定版本
kubectl rollout undo daemonset <name> --to-revision=<revision>
8. 与 Deployment 的区别
| 特性 | DaemonSet | Deployment |
|---|---|---|
| 副本数 | 自动匹配节点数量(受调度约束影响) | 手动指定 replicas |
| Pod 分布 | 每个节点最多一个 Pod(通常每个节点一个) | 可任意分布,多个 Pod 可在同一节点(若允许) |
| 调度方式 | 控制器直接指定节点,绕过调度器 | 由调度器分配节点 |
| 典型用途 | 系统级守护进程(日志、监控、网络) | 无状态应用(Web 服务、API) |
| 节点扩展 | 新节点自动运行 Pod | 需调度器分配,可能因资源不足而 pending |
9. 常见用例示例
9.1 在每个节点运行 Fluentd 收集日志
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
spec:
selector:
matchLabels:
name: fluentd
template:
metadata:
labels:
name: fluentd
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd
image: fluent/fluentd:v1.14
volumeMounts:
- name: varlog
mountPath: /var/log
- name: containers
mountPath: /var/lib/docker/containers
volumes:
- name: varlog
hostPath:
path: /var/log
- name: containers
hostPath:
path: /var/lib/docker/containers
这个例子还添加了容忍度,允许在 master 节点上运行,并使用 hostPath 挂载宿主机日志目录。
9.2 在每个节点运行 Node Exporter
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
hostPID: true
hostNetwork: true
containers:
- name: node-exporter
image: prom/node-exporter:latest
args:
- --path.procfs=/host/proc
- --path.sysfs=/host/sys
volumeMounts:
- name: proc
mountPath: /host/proc
readOnly: true
- name: sys
mountPath: /host/sys
readOnly: true
volumes:
- name: proc
hostPath:
path: /proc
- name: sys
hostPath:
path: /sys
这里使用了 hostPID 和 hostNetwork,让 Pod 能够访问宿主机的进程和网络命名空间。
10. 高级特性与注意事项
- 资源预留:由于 DaemonSet Pod 可能运行在所有节点上,需要合理设置资源请求(requests)和限制(limits),避免资源竞争影响其他工作负载。
- 优先级:可以为 DaemonSet Pod 设置优先级(PriorityClass),确保关键系统守护进程在节点资源紧张时优先调度。
- 节点不可用 :如果节点处于
NotReady状态,DaemonSet 不会立即删除该节点上的 Pod,而是等待节点恢复;但可以通过spec.minReadySeconds控制。 - 容忍度与守护 :DaemonSet 通常需要容忍
node.kubernetes.io/not-ready和node.kubernetes.io/unreachable等常见污点,以确保在节点临时故障时 Pod 不会被驱逐(默认添加了tolerationSeconds为 300 秒的容忍度,Kubernetes 会自动注入这些容忍度给 DaemonSet 的 Pod)。
11. 总结
DaemonSet 是 Kubernetes 中针对节点级守护进程的专用控制器,它保证每个符合条件的节点上都运行一个 Pod 副本。理解其调度机制、更新策略和典型用例,有助于在集群中高效部署监控、日志、网络等基础组件,实现集群的自运维能力。