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 客户端);
  • 安全代理(节点级防火墙、入侵检测)。
相关推荐
报错小能手4 小时前
linux学习笔记(19)进程间通讯——消息队列
linux·笔记·学习
进击的圆儿4 小时前
【学习笔记05】C++11新特性学习总结(下)
c++·笔记·学习
低音钢琴5 小时前
【碎片化学习】工具文:计算机通用术语中常见的100个英文单词
学习
火星MARK5 小时前
k8s面试题
容器·面试·kubernetes
聪明的笨猪猪6 小时前
Java Spring “IOC + DI”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
im_AMBER6 小时前
Web 开发 24
前端·笔记·git·学习
赵渝强老师7 小时前
【赵渝强老师】Docker容器的资源管理机制
linux·docker·容器·kubernetes
递归不收敛8 小时前
吴恩达机器学习课程(PyTorch 适配)学习笔记:3.4 强化学习
pytorch·学习·机器学习
烧冻鸡翅QAQ8 小时前
考研408笔记
笔记·考研