K8s DaemonSet 实战:从日志收集到节点选择的完整指南
在 Kubernetes 集群中,有些任务需要在每个节点(或指定节点)上运行一个实例——比如日志收集、监控代理、网络插件等。DaemonSet 正是为这类场景设计的控制器。本文将通过一个日志收集的实战案例,详解 DaemonSet 的核心特性、配置方法和节点选择策略,帮助初学者快速掌握其用法。
什么是 DaemonSet?
DaemonSet 是 Kubernetes 提供的一种控制器,用于在集群的所有节点(或符合条件的节点)上运行且仅运行一个 Pod 实例。它的核心特性包括:
- 自动部署:新节点加入集群时,DaemonSet 会自动在该节点上创建对应的 Pod
- 自动清理:节点从集群移除后,DaemonSet 会自动删除该节点上的 Pod
- 节点选择:可通过标签选择器指定仅在特定节点上部署 Pod
- 无副本数配置:无需手动设置
replicas
,Pod 数量由集群节点数决定(受节点选择限制)
最典型的应用场景就是日志收集(如本文的 Fluentd 案例)和节点监控(如 Prometheus Node Exporter)。
DaemonSet(守护进程集)的核心作用:日志收集与自动化管理
对于初学者来说,可以这样理解 DaemonSet 的核心价值:
1. 解决什么问题?—— 日志收集的“痛点”
传统微服务部署时,会遇到一个麻烦:
- 一个集群有多个节点(node),每个节点上可能运行多个微服务的 Pod;
- 每个 Pod 都有自己的日志,分散在各个节点的本地文件里;
- 如果服务出故障,需要逐个登录节点、逐个查找 Pod 日志,效率极低。
DaemonSet 的第一个作用,就是在每个节点上“自动部署一个专用的日志收集进程”(比如你提到的 Fluentd),统一收集该节点上所有 Pod 的日志,再发送到 Elasticsearch(日志存储)或 Prometheus(监控),避免手动逐个节点查日志。
2. 为什么用 DaemonSet 而不是普通 Deployment?
普通 Deployment 是“指定数量部署”(比如部署 3 个 Pod),而 DaemonSet 有两个关键特性,完美适配日志收集场景:
- “节点级守护”:只要集群里有新节点加入,DaemonSet 会自动在新节点上部署一个 Pod(确保每个节点都有日志收集进程);
- “自动化管理”:不需要手动登录节点启动进程,只需写一个 DaemonSet 配置文件,K8s 会自动完成部署、重启、扩容(新节点加入时)。
3. 如何指定“要收集哪些日志”?
如果只想收集某类节点的日志(比如只收集标记为“生产环境”的节点),可以用 nodeSelector
做筛选:
- 先给目标节点打标签(比如
kubectl label nodes 节点名 type=production
); - 在 DaemonSet 配置里加
nodeSelector: {type: production}
; - 这样 DaemonSet 只会在带有
type=production
标签的节点上部署日志收集进程,避免“无差别收集”。
实战场景:用 DaemonSet 部署 Fluentd 日志收集器
我们将通过部署 Fluentd(一款日志收集工具),演示 DaemonSet 的工作流程。目标是让 Fluentd 在指定节点上运行,收集节点上的容器日志并发送到存储后端(如 Elasticsearch)。
步骤1:编写 DaemonSet 配置文件
创建 fluentd-ds.yaml
配置文件,定义 DaemonSet 及相关配置:
apiVersion: apps/v1
kind: DaemonSet # 资源类型为 DaemonSet
metadata:
name: fluentd # DaemonSet 名称
spec:
selector: # 标签选择器(必须与 Pod 标签匹配)
matchLabels:
app: logging
template: # Pod 模板(定义要运行的容器)
metadata:
labels:
app: logging # 与 selector.matchLabels 对应
id: fluentd
spec:
containers:
- name: fluentd-es # 容器名称
image: agilestacks/fluentd-elasticsearch:v1.3.0 # Fluentd 镜像
env: # 环境变量(简化日志输出)
- name: FLUENTD_ARGS
value: -qq # 安静模式,减少日志输出
volumeMounts: # 挂载主机目录(用于读取日志)
- name: containers # 数据卷名称(与下方 volumes 对应)
mountPath: /var/lib/docker/containers # 容器日志存储路径(主机目录)
- name: varlog # 数据卷名称
mountPath: /var/log # 系统日志路径(主机目录)
volumes: # 定义数据卷(关联主机目录)
- name: containers
hostPath:
path: /var/lib/docker/containers # 主机上的容器日志目录
- name: varlog
hostPath:
path: /var/log # 主机上的系统日志目录
配置关键点解析:
- 无副本数配置:DaemonSet 无需设置
replicas
,Pod 数量由节点数决定 - 数据卷挂载:通过
hostPath
将主机的日志目录(/var/lib/docker/containers
和/var/log
)挂载到容器,使 Fluentd 能读取节点日志 - 标签选择器:
selector
用于关联 DaemonSet 和 Pod,必须与 Pod 模板的labels
匹配
步骤2:创建 DaemonSet 并查看初始状态
执行以下命令创建 DaemonSet:
kubectl create -f fluentd-ds.yaml
查看 DaemonSet 状态:
kubectl get ds # ds 是 daemonsets 的缩写
输出如下(DESIRED
表示期望在 2 个节点上部署):
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
fluentd 2 2 0 2 0 <none> 14s
查看 Pod 分布:
kubectl get po -o wide # -o wide 显示 Pod 所在节点
输出显示 Pod 分布在 k8snode1
和 k8snode2
上(默认不会部署在 master 节点,因 master 有 node-role.kubernetes.io/control-plane
标签限制):
NAME READY STATUS IP NODE ...
fluentd-c27qt 1/1 Running 10.244.2.61 k8snode2 ...
fluentd-mzrcc 1/1 Running 10.244.1.58 k8snode1 ...
关键结论:
- DaemonSet 会自动在所有符合条件的节点上部署 Pod(默认排除 master 节点)
- 无需配置
replicas
,Pod 数量自动匹配节点数(受节点选择限制)
步骤3:用节点标签限制 DaemonSet 部署范围
默认情况下,DaemonSet 会在所有非 master 节点部署 Pod。但实际场景中,我们可能只需要在“微服务节点”上收集日志。此时可通过节点标签 + 节点选择器实现。
操作1:为节点添加标签
给需要部署 Fluentd 的节点(如 k8snode1
)添加 type=microservices
标签:
kubectl label node k8snode1 type=microservices
查看标签是否生效:
kubectl get nodes --show-labels
输出显示 k8snode1
已添加标签:
NAME STATUS LABELS... type=microservices # k8snode1 的标签
k8snode2 Ready LABELS... # 无 type=microservices 标签
操作2:配置 DaemonSet 的节点选择器
通过 kubectl edit ds fluentd
编辑 DaemonSet,添加节点选择器:
spec:
template:
spec:
nodeSelector: # 仅在带有 type=microservices 标签的节点上部署
type: microservices
操作3:验证部署结果
查看 DaemonSet 和 Pod 状态:
# 查看 DaemonSet:DESIRED 变为 1(仅 k8snode1 符合标签条件)
kubectl get ds
# 输出:NAME DESIRED CURRENT READY NODE SELECTOR AGE
# fluentd 1 1 1 type=microservices ...
# 查看 Pod:仅在 k8snode1 上运行
kubectl get po -o wide
# 输出:NAME READY NODE ...
# fluentd-vn5zh 1/1 k8snode1 ...
关键结论:
- 通过
nodeSelector
可限制 DaemonSet 仅在带有指定标签的节点上部署 Pod - 标签更新后,DaemonSet 会自动删除不符合条件的 Pod,在符合条件的节点上创建新 Pod
步骤4:动态调整部署节点(添加新标签)
若后续需要在 k8snode2
上也部署 Fluentd,只需给 k8snode2
添加相同标签:
kubectl label node k8snode2 type=microservices
查看 Pod 状态,发现 DaemonSet 自动在 k8snode2
上创建了新 Pod:
kubectl get po -o wide
# 输出:
# fluentd-lgjjs 1/1 Running 10.244.2.62 k8snode2 ...
# fluentd-vn5zh 1/1 Running 10.244.1.59 k8snode1 ...
关键结论:
- 节点标签更新后,DaemonSet 会自动调整 Pod 分布(新增符合条件的节点时自动部署,移除标签时自动删除)
DaemonSet 核心特性总结
通过上述实战,我们可以总结 DaemonSet 的核心特性:
特性 | 说明 |
---|---|
部署策略 | 在所有符合条件的节点上运行且仅运行一个 Pod |
自动扩缩容 | 新节点加入时自动部署 Pod,节点移除时自动删除 Pod |
节点选择 | 通过 nodeSelector + 节点标签,限制仅在特定节点部署 |
无副本数配置 | 无需设置 replicas ,Pod 数量由符合条件的节点数决定 |
默认行为 | 不部署在 master 节点(因 master 有 control-plane 标签限制) |
DaemonSet vs Deployment:核心差异
特性 | DaemonSet | Deployment |
---|---|---|
Pod 分布 | 每个节点最多一个 Pod(按节点部署) | 不限制节点,按副本数部署(随机分布) |
副本数控制 | 由节点数决定(无需配置 replicas) | 需手动配置 replicas |
典型用途 | 日志收集、监控代理、网络插件(节点级任务) | 微服务、API 服务(应用级任务) |
扩缩容方式 | 添加/移除节点或标签 | 调整 replicas 数量 |
总结
本文通过部署 Fluentd 日志收集器,演示了 DaemonSet 的核心用法:
- 核心作用:在指定节点上运行且仅运行一个 Pod,适合节点级任务(如日志收集、监控)
- 自动部署:新节点加入时自动部署 Pod,无需手动操作
- 节点选择:通过
nodeSelector
+ 节点标签,灵活控制部署范围 - 与 Deployment 区别:DaemonSet 按节点部署,Deployment 按副本数部署
掌握 DaemonSet 后,你可以轻松实现节点级工具的批量部署和管理,为集群监控、日志收集等基础能力提供支撑。
https://github.com/0voice