在 Kubernetes 中部署集群级别的系统组件(如日志收集器、监控 Agent、网络探针等)时,一个常用且推荐的方式就是使用 DaemonSet。它能保证在集群的每个节点上运行一份 Pod,从而实现节点粒度的覆盖。
但很多人在使用 DaemonSet 部署日志和监控类组件时,容易踩一些坑,比如采集不到容器日志、Prometheus 监控不到容器数据、资源争抢等问题。
本文将从原理讲起,结合实践经验,讲解使用 DaemonSet 部署日志/监控类组件的 最佳实践与正确姿势。
一、什么是 DaemonSet?为什么适合部署日志/监控组件?
DaemonSet 是 Kubernetes 提供的一种控制器,用于在集群中 每个(或指定)节点上运行同样的 Pod 副本,常用于部署以下类型的服务:
- 日志采集器(如 Fluentd、Filebeat、Vector)
- 监控 Agent(如 Node Exporter、Prometheus Agent、Datadog Agent)
- 网络插件(如 Calico、Cilium)
- 安全组件(如 Falco、Sysdig)
为什么要使用 DaemonSet?
- 保证每个节点都有组件运行,确保数据采集不遗漏;
- 自动随节点加入/移除而部署或清理对应 Pod;
- 易于与 Node 本地资源(如日志目录、容器运行时)交互。
二、典型日志/监控类组件部署示意
假设你需要部署如下组件:
组件名称 | 类型 | 部署模式 |
---|---|---|
Fluentd | 日志收集 | DaemonSet |
Node Exporter | 系统监控 | DaemonSet |
Prometheus Agent | 采集代理 | DaemonSet |
通过 DaemonSet,可以轻松实现这些组件在 所有 Node 上"无感"部署,无需手动指定节点列表。
三、部署时必须注意的几个关键点
1. 挂载主机路径:才能看到容器的日志或系统信息
日志/监控组件要想读取主机日志文件、容器日志、系统指标,必须挂载宿主机路径。例如:
对于日志组件:
yaml
volumeMounts:
- name: varlog
mountPath: /var/log
- name: dockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
yaml
volumes:
- name: varlog
hostPath:
path: /var/log
- name: dockercontainers
hostPath:
path: /var/lib/docker/containers
如果使用的是 containerd 或 CRI-O,还需挂载 /var/log/pods
、/var/lib/containerd
等路径。
2. 设置正确的主机网络访问(hostNetwork)
一些组件(如 Node Exporter、Prometheus Agent)需要监听宿主机 IP 地址,在某些场景下必须启用 hostNetwork: true
:
yaml
spec:
hostNetwork: true
这会使 Pod 与 Node 使用相同的网络栈,使外部 Prometheus 能够访问其监听的端口。
⚠️ 注意启用 hostNetwork 后,容器端口必须避免与宿主机冲突!
3. 使用 hostPID
、hostIPC
时需谨慎
监控某些系统指标或运行容器探针时,可能需要访问宿主机的进程命名空间(如 Falco)。这时可以配置:
yaml
spec:
hostPID: true
但这会提高容器的权限等级,需谨慎使用,配合安全策略控制。
4. 使用 Node Affinity 或 NodeSelector 控制调度范围
如果你只希望日志或监控组件运行在特定 Node 上,例如只在 Linux 系统运行,可以用以下方式限制:
yaml
nodeSelector:
kubernetes.io/os: linux
或者使用 Node Affinity 更灵活地控制:
yaml
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/worker
operator: Exists
四、资源限制与稳定性建议
日志和监控组件常年运行,且容易因为数据量大而消耗资源,建议始终设置 requests/limits 以保护主业务容器的资源:
yaml
resources:
requests:
cpu: 100m
memory: 200Mi
limits:
cpu: 300m
memory: 500Mi
同时建议设置 priorityClassName: system-node-critical
确保这些核心组件优先调度,避免 OOM 被驱逐。
五、常见组件配置示例
1. Fluent Bit 日志收集 DaemonSet
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit
spec:
template:
spec:
containers:
- name: fluent-bit
image: fluent/fluent-bit:1.9
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
hostPath:
path: /var/log
可进一步配置 /var/log/containers
、/etc/machine-id
、/etc/hostname
等路径以增强日志信息。
2. Node Exporter 监控 DaemonSet
yaml
spec:
hostNetwork: true
containers:
- name: node-exporter
image: prom/node-exporter
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
监听主机端口后可直接被 Prometheus 抓取。
六、如何避免部署中的几个"坑"?
问题 | 可能原因 | 解决建议 |
---|---|---|
日志收集不到容器日志 | 没挂载容器日志目录 | 挂载 /var/log/pods /var/lib/docker/containers |
Prometheus 无法抓取 Agent 数据 | 未启用 hostNetwork,端口隔离 | 添加 hostNetwork: true |
容器频繁 OOM 被驱逐 | 未设置资源限制 | 添加 requests/limits |
Pod 未覆盖所有节点 | 节点被打了 Taint,DaemonSet未容忍 | 添加 tolerations 来容忍 Taint |
容器权限不足采集系统指标 | 缺少 CAP_SYS_TIME、hostPID 权限 | 增加所需权限或 RBAC 配置 |
七、总结:部署日志/监控组件的正确姿势
- 使用 DaemonSet 是部署系统级 Agent 的标准方式
- 挂载宿主机路径,是采集数据的前提
- 合理使用 hostNetwork、hostPID、tolerations 提升部署可达性
- 限制资源,避免 Agent 与业务容器抢占资源
- 根据节点角色设置调度约束,灵活控制部署范围
在云原生环境下,日志与监控的基础设施稳定性非常关键。而使用 DaemonSet 正确部署这些组件,是构建 observability(可观测性)平台的第一步。