DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, 也会为他们新增一个 Pod 。当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
使用 DaemonSet 的一些典型用法:
glusterd、ceph。fluentd、logstash。collectd、Dynatrace OneAgent、 AppDynamics 代理、 Datadog 代理、New Relic 代理, Ganglia gmond 或 Instana agent。一个简单的用法是在所有的节点上都启动一个 DaemonSet,将被作为每种类型的 daemon 使 用。 一个稍微复杂的用法是单独对每种 daemon 类型使用多个 DaemonSet,但具有不同的标志, 和/或对不同硬件类型具有不同的内存、CPU要求。
您可以在 YAML 文件中描述 DaemonSet。例如,下面的 daemonset.yaml 文件描述了一个运行 fluentd-elasticsearch Docker 镜像的 DaemonSet:
controllers/daemonset.yaml
|
|---|
|
基于 YAML 文件创建 DaemonSet:
kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml
和其它所有 Kubernetes 配置一样,DaemonSet 需要 apiVersion、kind 和 metadata 字段。有关配置文件的基本信息,详见文档 部署应用、配置容器 和 使用kubectl进行对象管理 。
DaemonSet 也需要一个 .spec 配置段。
.spec 唯一必需的字段是 .spec.template。
.spec.template 是一个 Pod 模板。它与 Pod 具有相同的 schema,除了它是嵌套的,而且不具有 apiVersion 或 kind 字段。
除了 Pod 必需字段外,在 DaemonSet 中的 Pod 模板必须指定合理的标签(查看 Pod Selector)。
在 DaemonSet 中的 Pod 模板必须具有一个值为 Always 的 RestartPolicy,或者未指定它的值,默认是 Always。
.spec.selector 字段表示 Pod Selector,它与 Job 的 .spec.selector 的作用是相同的。
从 Kubernetes 1.8开始,您必须指定与 .spec.template 的标签匹配的 pod selector。当不配置时,pod selector 将不再有默认值。selector 默认与 kubectl apply 不兼容。 此外,一旦创建了 DaemonSet,它的 .spec.selector 就不能修改。修改 pod selector 可能导致成为 孤儿Pod,并且这对用户来说是困惑的。
spec.selector 表示一个对象,它由如下两个字段组成:
matchLabels - 与 ReplicationController 的 .spec.selector 的作用相同。matchExpressions - 允许构建更加复杂的 Selector,可以通过指定 key、value 列表
,以及与 key 和 value 列表相关的操作符。当上述两个字段都指定时,结果表示的是 AND 关系。
如果指定了 .spec.selector,必须与 .spec.template.metadata.labels 相匹配。如果与它们配置的不匹配,则会被 API 拒绝。
此外,您通常不应该创建任何 pods,它们的 label 与 selector 匹配,或者直接创建,或者通过另一个 DaemonSet、或者其他控制器,比如 ReplicaSet。否则,DaemonSet 控制器会认为这些 Pod 是由它创建的。Kubernetes 不会阻止你这样做。 您可能希望这样做的一种情况是在节点上手动创建具有不同值的 Pod 以进行测试。
如果指定了 .spec.template.spec.nodeSelector,DaemonSet Controller 将在能够与 Node Selector 匹配的节点上创建 Pod。类似这种情况,可以指定 .spec.template.spec.affinity,然后 DaemonSet Controller 将在能够与 node Affinity 匹配>的节点上创建 Pod。
如果根本就没有指定,则 DaemonSet Controller 将在所有节点上创建 Pod。
正常情况下,Pod 运行在哪个机器上是由 Kubernetes 调度器来选择的。然而,由 DaemonSet Controller 创建的 Pod 已经确定了在哪个机器上(Pod 创建时指定了 .spec.nodeName,调度器会忽略它),因此:
unschedulable 字段。Kubernetes v1.14
beta
DaemonSet 确保所有符合条件的节点都运行一个 Pod 的副本。通常,运行 Pod 的节点由 Kubernetes scheduler 选择。然而,DaemonSet pods 由 DaemonSet controller 创建和调度。这将引入以下问题:
Pending 状态,但 DaemonSet pods 未在 Pending 状态下创建。 这使用户感到困惑。ScheduleDaemonSetPods 允许您使用默认 scheduler 而不是 DaemonSet 控制器来调度 DaemonSets,方法是将 NodeAffinity 添加到 DaemonSet pods,而不是 .spec.nodeName。 然后使用默认 scheduler 将 pod 绑定到目标主机。 如果 DaemonSet pod的亲和节点已存在,则替换它。 DaemonSet 控制器仅在创建或修改 DaemonSet pods 时执行这些操作,并且不对 DaemonSet的 spec.template 进行任何更改。
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- target-host-name此外,node.kubernetes.io/unschedulable:NoSchedule toleration 会自动添加到 DaemonSet Pods。 在调度DaemonSet Pod 时,默认调度器会忽略 unschedulable节点。
尽管 Daemon Pods 尊重taints and tolerations,根据相关特性,会自动将以下 tolerations 添加到 DaemonSet Pods 中。
| Toleration Key | Effect | Version | Description |
|---|---|---|---|
node.kubernetes.io/not-ready |
NoExecute | 1.13+ | DaemonSet pods will not be evicted when there are node problems such as a network partition. |
node.kubernetes.io/unreachable |
NoExecute | 1.13+ | DaemonSet pods will not be evicted when there are node problems such as a network partition. |
node.kubernetes.io/disk-pressure |
NoSchedule | 1.8+ | |
node.kubernetes.io/memory-pressure |
NoSchedule | 1.8+ | |
node.kubernetes.io/unschedulable |
NoSchedule | 1.12+ | DaemonSet pods tolerate unschedulable attributes by default scheduler. |
node.kubernetes.io/network-unavailable |
NoSchedule | 1.12+ | DaemonSet pods, who uses host network, tolerate network-unavailable attributes by default scheduler. |
与 DaemonSet 中的 Pod 进行通信,几种可能的模式如下:
hostPort,从而可以通过节点 IP 访问到 Pod。客户端能通过某种方法知道节点 IP 列表,并且基于此也可以知道端口
。endpoints 资源或从 DNS 检索到多个 A 记录来发现 DaemonSet。如果修改了节点标签(Label),DaemonSet 将立刻向新匹配上的节点添加 Pod,同时删除不能够匹配的节点上的 Pod。
您可以修改 DaemonSet 创建的 Pod。然而,不允许对 Pod 的所有字段进行更新。当下次 节点(即使具有相同的名称)被创建时,DaemonSet Controller 还会使用最初的模板。
您可以删除一个 DaemonSet。如果使用 kubectl 并指定 --cascade=false 选项,则 Pod 将被保留在节点上。然后可以创建具有不同模板的新 DaemonSet。具有不同模板的新 DaemonSet 将能够通过标签匹配并识别所有已经存在的 Pod。它不会修改或删除它们,即使是错误匹配了 Pod 模板。通过删除 Pod 或者删除节点,可以强制创建新的 Pod。
在 Kubernetes 1.6 或以后版本,可以在 DaemonSet 上 执行滚动升级。
我们很可能希望直接在一个节点上启动 daemon 进程(例如,使用 init、upstartd、或 systemd)。这非常好,但基于 DaemonSet 来运行这些进程有如下一些好处:
kubectl)。可能要直接创建 Pod,同时指定其运行在特定的节点上。然而,DaemonSet 替换了由于任何原因被删除或终止的 Pod,例如节点失败、例行节点维护、内核升级。由于这个原因,我们应该使用 DaemonSet 而不是单独创建 Pod。
可能需要通过在一个指定目录下编写文件来创建 Pod,该目录受 Kubelet 所监视。这些 Pod 被称为 静态 Pod。 不像 DaemonSet,静态 Pod 不受 kubectl 和其它 Kubernetes API 客户端管理。静态 Pod 不依赖于 apiserver,这使得它们在集群启动的情况下非常有用。而且,未来静态 Pod 可能会被废弃掉。
DaemonSet 与 Deployments非常类似,它们都能创建 Pod,这些 Pod 对应的进程都不希望被终止掉(例如,Web 服务器、存储服务器)。 为无状态的 Service 使用 Deployments,比如前端 Frontend 服务,实现对副本的数量进行扩缩容、平滑升级,比基于精确控制 Pod 运行在某个主机上要重要得多。 需要 Pod 副本总是运行在全部或特定主机上,并需要先于其他 Pod 启动,当这被认为非常重要时,应该使用 Daemon Controller。
此页是否对您有帮助?
Thanks for the feedback. If you have a specific, answerable question about how to use Kubernetes, ask it on Stack Overflow. Open an issue in the GitHub repo if you want to report a problem or suggest an improvement.