UP | HOME

DaemonSet

Table of Contents

概念

DaemonSet 确保 全部 (或者一些) Node运行 一个 Pod 的副本

  • 当有 Node 加入集群时,也会为他们新增一个 Pod
  • 当有 Node 从集群移除时,这些 Pod 也会被回收
  • 删除 DaemonSet 将会删除它创建的所有 Pod

使用 DaemonSet 的一些典型用法:

  • 运行集群存储 daemon

    例如在每个 Node 上运行 glusterd、ceph
    
  • 在每个 Node 上运行日志收集 daemon

    例如fluentd、logstash
    
  • 在每个 Node 上运行监控 daemon

    例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond
    
一个简单的用法是,在所有的 Node 上都存在一个 DaemonSet,将被作为每种类型的 daemon 使用

一个稍微复杂的用法可能是,对单独的每种类型的 daemon 使用多个 DaemonSet,但具有不同的标志,和/或对不同硬件类型具有不同的内存、CPU要求

编写

必需字段

和其它所有 Kubernetes 配置一样,DaemonSet 需要 apiVersionkindmetadata 字段。DaemonSet 也需要一个 .spec 配置段

Pod 模板

.spec 唯一必需 的字段是 .spec.template ,是一个 Pod 模板

它与 Pod 具有相同的 schema,除了它是嵌套的,而且不具有 apiVersion 或 kind 字段

Pod 除了必须字段外:

  • 在 DaemonSet 中的 Pod 模板必须 指定 合理的标签 (查看 pod selector)
  • 在 DaemonSet 中的 Pod 模板必需具有一个值为 AlwaysRestartPolicy

    或者未指定 RestartPolicy的值,默认是 Always
    

Pod Selector

.spec.selector 字段表示 Pod Selector 。spec.selector 表示一个对象,它由如下两个字段组成:

  • matchLabels : 与 ReplicationController 的 .spec.selector 的原理相同
  • matchExpressions : 允许构建更加复杂的 Selector,可以通过指定 keyvalue 列表 ,以及与 key 和 value 列表的 相关的操作符
当上述两个字段都指定时,结果表示的是 AND 关系

如果指定了 .spec.selector,必须与 .spec.template.metadata.labels匹配

如果没有指定,它们默认是等价的

如果与它们配置的不匹配,则会被 API 拒绝

如果 Pod 的 label 与 selector 匹配,或者直接基于其它的 DaemonSet、或者 Controller(例如 ReplicationController),也 不可以创建 任何 Pod

否则 DaemonSet Controller 将认为那些 Pod 是它创建的

Kubernetes 不会阻止这样做。一个场景是,可能希望在一个具有不同值的、用来测试用的 Node 上手动创建 Pod

仅在相同的 Node 上运行 Pod

如果指定了 .spec.template.spec.nodeSelector ,DaemonSet Controller 将在能够匹配上 Node Selector 的 Node 上创建 Pod

类似这种情况,可以指定 .spec.template.spec.affinity,然后 DaemonSet Controller 将在能够匹配上 Node Affinity 的 Node 上创建 Pod

如果根本就没有指定,则 DaemonSet Controller 将在所有 Node 上创建 Pod

调度

正常情况下,Pod 运行在哪个机器上是由 Kubernetes 调度器进行选择的。然而,由 Daemon Controller 创建的 Pod 已经确定了在哪个机器上(Pod 创建时指定了 .spec.nodeName),因此:

  • DaemonSet Controller 并不关心一个 Node 的 unschedulable 字段
  • DaemonSet Controller 可以创建 Pod, 即使调度器还没有被启动 ,这对集群启动是非常有帮助的
Daemon Pod 关心 Taint 和 Toleration,它们会为没有指定 tolerationSeconds 的 node.alpha.kubernetes.io/notReady 和 node.alpha.kubernetes.io/unreachable 的 Taint,而创建具有 NoExecute 的 Toleration

这确保了当 alpha 特性的 TaintBasedEvictions 被启用,当 Node 出现故障,比如网络分区,这时它们将不会被清除掉

当 TaintBasedEvictions 特性没有启用,在这些场景下也不会被清除,但会因为 NodeController 的硬编码行为而被清除,Toleration 是不会的

通信

与 DaemonSet 中的 Pod 进行通信,几种可能的模式如下:

  • Push : 配置 DaemonSet 中的 Pod 向其它 Service 发送更新

    例如统计数据库。它们没有客户端
    
  • NodeIP已知端口 :DaemonSet 中的 Pod 可以使用 hostPort,从而可以通过 Node IP 访问到 Pod。客户端能通过某种方法知道 Node IP 列表,并且基于此也可以知道端口
  • DNS :创建具有相同 Pod Selector 的 Headless Service,然后通过使用 endpoints 资源或从 DNS 检索到多个 A 记录来发现 DaemonSet
  • Service :创建具有相同 Pod Selector 的 Service,并使用该 Service 访问到某个随机 Node 上的 daemon

    没有办法访问到特定 Node
    

更新

  • 如果修改了 Node Label,DaemonSet 将立刻向新匹配上的 Node 添加 Pod,同时删除新近无法匹配上的 Node 上的 Pod
  • 可以修改 DaemonSet 创建的 Pod,然而,不允许对 Pod 的所有字段进行更新

    当下次 Node(即使具有相同的名称)被创建时,DaemonSet Controller 还会使用最初的模板
    
  • 可以删除一个 DaemonSet,如果使用 kubectl 并指定 –cascade=false 选项,则 Pod 将被保留在 Node 上
    • 然后可以创建具有不同模板的新 DaemonSet,将鞥能够通过 Label 匹配识别所有已经存在的 Pod。它不会修改或删除它们,即使是错误匹配了 Pod 模板
    • 通过删除 Pod 或者 删除 Node,可以强制创建新的 Pod
在 Kubernetes 1.6 或以后版本,可以在 DaemonSet 上 执行滚动升级

其他方案

init 脚本

很可能通过直接在一个 Node 上启动 daemon 进程(例如,使用 init、upstartd、或 systemd)。这非常好,基于 DaemonSet 来运行这些进程有如下一些好处:

  • 像对待应用程序一样,具备为 daemon 提供监控和管理日志的能力
  • 为 daemon 和应用程序使用相同的配置语言和工具(如 Pod 模板、kubectl)
  • Kubernetes 未来版本可能会支持对 DaemonSet 创建 Pod 与 Node升级工作流进行集成
  • 在资源受限的容器中运行 daemon,能够增加 daemon 和应用容器的隔离性

    然而这也实现了在容器中运行 daemon,但却不能在 Pod 中运行,例如,直接基于 Docker 启动
    

裸 Pod

可能要直接创建 Pod,同时指定其运行在特定的 Node 上

然而,DaemonSet 替换了由于任何原因被删除或终止的 Pod,例如 Node 失败、例行节点维护,比如内核升级

由于这个原因,应该使用 DaemonSet 而不是单独创建 Pod

静态 Pod

很可能,通过在一个指定目录下编写文件来创建 Pod,该目录受 Kubelet 所监视。这些 Pod 被称为 静态 Pod

不像 DaemonSet,静态 Pod 不受 kubectl 和 其它 Kubernetes API 客户端管理

静态 Pod 不依赖于 apiserver,这使得它们在集群启动的情况下非常有用。 但启动之后 静态 Pod 可能会被删除掉

Replication Controller

DaemonSet 与 Replication Controller 非常类似,它们都能创建 Pod,这些 Pod 都具有不期望被终止的进程(例如,Web 服务器、存储服务器)

为无状态的 Service 使用 Replication Controller,像 frontend,实现对副本的数量进行扩缩容、平滑升级,比之于精确控制 Pod 运行在某个主机上要重要得多

需要 Pod 副本总是运行在全部或特定主机上,并需要先于其他 Pod 启动,当这被认为非常重要时,应该使用 Daemon Controller

Next: ReplicaSet

Previous: StatefulSet

Home:Controller