Appearance
DaemonSet
DaemonSet 用来保证符合条件的每个节点都运行一个 Pod。日志采集、节点监控、CNI、CSI 节点插件、kube-proxy 这类组件都很适合用 DaemonSet:它们不服务某个业务副本,而是贴着节点工作。
Deployment 关心副本数,DaemonSet 关心节点覆盖率。节点新增时自动补一个 Pod,节点删除时对应 Pod 跟着消失。排查 DaemonSet 时,重点是哪些节点应该有 Pod、哪些节点没有、为什么没有调度上去。
一、基本结构
一个日志 Agent 的 DaemonSet:
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: log-agent
namespace: logging
spec:
selector:
matchLabels:
app: log-agent
template:
metadata:
labels:
app: log-agent
spec:
serviceAccountName: log-agent
containers:
- name: fluent-bit
image: fluent/fluent-bit:3.2
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi
volumeMounts:
- name: varlog
mountPath: /var/log
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/logDaemonSet 通常会挂载宿主机目录、读取节点日志、访问 kubelet 或容器运行时 socket,因此权限比普通业务 Pod 更敏感。镜像来源、ServiceAccount 权限、hostPath 范围都要收口。
二、节点选择和污点容忍
DaemonSet 默认会在所有可调度节点上创建 Pod。只希望跑在部分节点时,用 nodeSelector 或亲和性:
yaml
spec:
template:
spec:
nodeSelector:
node-role.kubernetes.io/worker: "true"控制平面节点常带有污点,普通 Pod 不会调度上去。节点级组件如果也要覆盖控制平面节点,需要配置 tolerations:
yaml
spec:
template:
spec:
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"监控 Agent、日志 Agent 是否覆盖控制平面节点,取决于集群运维策略。控制平面日志和节点指标也需要采集时,DaemonSet 要能容忍对应污点。
三、滚动更新
DaemonSet 支持滚动更新:
yaml
spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1maxUnavailable: 1 表示一次最多让一个节点上的 Agent 不可用。日志采集、监控采集这类组件升级时,过大的不可用比例会造成短时间采集断档。
查看更新状态:
bash
kubectl rollout status daemonset/log-agent -n logging
kubectl rollout history daemonset/log-agent -n logging回滚:
bash
kubectl rollout undo daemonset/log-agent -n loggingDaemonSet 回滚只负责恢复 Pod 模板,不会恢复外部系统配置。比如日志后端地址改错,回滚 YAML 能恢复采集 Agent,但后端里已经产生的异常数据不会自动清掉。
四、常见系统组件
Kubernetes 集群里常见的 DaemonSet:
| 组件 | 作用 |
|---|---|
kube-proxy | 在每个节点维护 Service 转发规则 |
| CNI 节点组件 | 配置 Pod 网络、路由、策略或 eBPF 程序 |
| CSI node plugin | 在节点上完成卷挂载、卸载 |
node-exporter | 采集 Linux 主机指标 |
| 日志 Agent | 读取节点日志文件并发送到日志后端 |
| 安全 Agent | 节点安全审计、运行时检测 |
这些组件异常时,影响面通常跟节点有关。比如某个节点的 CNI DaemonSet Pod 异常,该节点上的业务 Pod 可能都出现网络问题;某个节点的 CSI 插件异常,该节点上的 PVC 挂载会失败。
五、查看覆盖情况
bash
kubectl get daemonset -A
kubectl get daemonset log-agent -n logging -o wide
kubectl get pod -n logging -l app=log-agent -o wideDaemonSet 状态字段:
| 字段 | 含义 |
|---|---|
DESIRED | 期望覆盖的节点数 |
CURRENT | 当前已创建的 Pod 数 |
READY | Ready 的 Pod 数 |
UP-TO-DATE | 使用最新模板的 Pod 数 |
AVAILABLE | 可用 Pod 数 |
如果 DESIRED 小于节点数,要看 nodeSelector、亲和性和污点;如果 CURRENT 等于 DESIRED 但 READY 不足,要看 Pod 事件、镜像、权限、探针和宿主机挂载。
六、排查路径
bash
# 看哪些节点没有对应 Pod
kubectl get pod -n logging -l app=log-agent -o wide
# 看 DaemonSet 选择器、更新策略和事件
kubectl describe daemonset log-agent -n logging
# 看某个 Pod 在节点上为什么没起来
kubectl describe pod <pod-name> -n logging
kubectl logs <pod-name> -n logging几个常见原因:
| 现象 | 可能原因 |
|---|---|
| 某些节点没有 Pod | nodeSelector 不匹配、污点没有 toleration、节点不可调度 |
| Pod Pending | 资源不足、镜像拉取失败、hostPath 路径不存在 |
| Pod CrashLoopBackOff | 配置文件错误、权限不足、后端地址不可达 |
| 升级卡住 | 新版本探针失败、maxUnavailable 太小且旧 Pod 退出异常 |
DaemonSet 本身很简单,真正复杂的是它经常触碰节点层能力。hostNetwork、hostPID、privileged、hostPath 都会扩大权限,适合写清楚理由和范围。