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 的核心特性(必懂)

  1. 节点全覆盖 :默认在集群所有节点上运行一个 Pod 副本(可通过配置限制在特定节点)。
  2. 自动扩缩容:
    • 新节点加入集群时,DaemonSet 自动在新节点上创建 Pod。
    • 节点从集群移除时,DaemonSet 自动删除该节点上的 Pod。
  3. 单节点单副本:每个节点上最多运行一个该 DaemonSet 的 Pod(避免资源浪费或冲突)。
  4. 更新策略:支持滚动更新(默认)或替换更新,确保节点级服务升级时不中断。

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

yaml 复制代码
# 保存为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/master
        effect: NoSchedule
        operator: Exists
      # 节点选择器(可选:仅在有"monitor=yes"标签的节点上运行)
      # nodeSelector:
      #   monitor: "yes"
      containers:
      - name: node-exporter
        image: prom/node-exporter:v1.5.0  # 监控镜像
        args:
        - --path.procfs=/host/proc  # 挂载节点的proc目录
        - --path.sysfs=/host/sys    # 挂载节点的sys目录
        volumeMounts:
        - name: proc
          mountPath: /host/proc
          readOnly: true
        - name: sys
          mountPath: /host/sys
          readOnly: true
      volumes:
      - name: proc
        hostPath:
          path: /proc  # 节点的/proc目录
      - name: sys
        hostPath:
          path: /sys   # 节点的/sys目录
  # 更新策略:滚动更新(默认)
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1  # 最多允许1个节点的Pod不可用(控制更新速度)

步骤 2:部署并验证

bash 复制代码
# 创建命名空间(如果不存在)
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 常见问题与排错

  1. 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")。
  2. 更新 DaemonSet 后 Pod 未刷新

    • 原因:使用了OnDelete更新策略,需手动删除旧 Pod 才会创建新 Pod。
    • 解决:切换为RollingUpdate(默认),或手动删除旧 Pod(kubectl delete pod <旧Pod名称>)。
  3. 需要限制 DaemonSet 的资源使用

    • 解决:在 Pod 模板中添加resources.limitsrequests,避免 Pod 占用节点过多资源:

      yaml 复制代码
      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 客户端);
  • 安全代理(节点级防火墙、入侵检测)。
相关推荐
www.0219 小时前
linux服务器升级显卡驱动(笔记)
linux·运维·服务器·笔记·ubuntu·服务器环境
せいしゅん青春之我19 小时前
【JavaEE初阶】TCP核心机制10——异常情况的处理
java·网络·笔记·网络协议·tcp/ip·java-ee
wdfk_prog19 小时前
[Linux]学习笔记系列 -- [kernel][time]hrtimer
linux·笔记·学习
摇滚侠19 小时前
Spring Boot3零基础教程,把 Java 程序打包为 Linux 可执行文件,笔记91
java·linux·笔记
四谎真好看20 小时前
Java 黑马程序员学习笔记(进阶篇21)
java·开发语言·笔记·学习·学习笔记
立志成为大牛的小牛20 小时前
数据结构——三十三、Dijkstra算法(王道408)
数据结构·笔记·学习·考研·算法·图论
何故染尘優20 小时前
docker学习笔记,从入门开始!
笔记·学习·docker
不爱笑的良田21 小时前
从零开始的云原生之旅(四):K8s 工作负载完全指南
云原生·容器·kubernetes
D.....l1 天前
STM32学习(MCU控制)(WiFi and MQTT)
stm32·单片机·学习
摆烂积极分子1 天前
安卓开发学习10-中级控件
学习