通过前面章节的学习,我们对 Kubernetes 中一些常见工作负载已经有所了解。比如无状态工作负载 Dployment 可以帮助我们运行指定数目的服务副本,并维护其状态,而对于有状态服务来说,我们同样可以采用 StatefulSet 来做到这一点。

但是,在实际使用的时候,有些场景,比如监控各个节点的状态,使用 Deployment 或者 StatefulSet 都无法满足我们的需求,因为这个时候我们可能会有以下这些需求。

  1. 希望每个节点上都可以运行一个副本,且只运行一个副本。虽然通过调整 spec.replicas 的数值,可以使之等于节点数目,再配合一些调度策略(我们后面讲调度原理的时候会深入解释)可以实现这一点。但是如果节点数目发生了变化呢?
  2. 希望在新节点上也快速拉起副本。比如集群扩容,这个时候会有一些新节点加入进来,如何立即感知到这些节点,并在上面部署新的副本。
  3. 希望节点下线的时候,对应的 Pod 也可以被删除。
  4. ……

Kubernetes 提供的 DaemonSet 就可以完美地解决上述问题,其主要目的就是可以在集群内的每个节点上(或者指定的一堆节点上)都只运行一个副本,即 Pod 和 Node 是一一对应的关系。DaemonSet 会结合节点的情况来帮助你管理这些 Pod,见下面的拓扑结构:

image-20220127103710920

今天我们就来学习一下 DaemonSet,先来看看其主要的使用场景。

DaemonSet 的使用场景

跟 Deployment 和 StatefulSet 一样,DaemonSet 也是一种工作负载,可以管理一些 Pod。 通常来说,主要有以下的用法:

  • 监控数据收集,比如可以将节点信息收集上报给 Prometheus;
  • 日志的收集、轮转和清理;
  • 监控节点状态,比如运行 node-problem-detector 来监测节点的状态,并上报给 APIServer;
  • 负责在每个节点上网络、存储等组件的运行,比如 glusterd、ceph、flannel 等;

现在我们来尝试部署一个 DaemonSet。

部署你的第一个 DaemonSet

这里是一个 DaemonSet 的 YAML 文件:

apiVersion: apps/v1 # 这个地方已经不是 extension/v1beta1 了,在1.16版本已经废弃了,请使用 apps/v1
kind: DaemonSet # 这个是类型名
metadata:
  name: fluentd-elasticsearch # 对象名
  namespace: kube-system # 所属的命名空间
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
        volumeMounts:
        - name: varlog