DaemonSet
一个 DaemonSet 确保所有(或某些)节点运行一个 Pod 的副本。当节点添加到集群时,Pod 会添加到其中。当节点从集群中删除时,这些 Pod 会被垃圾回收。删除 DaemonSet 将会清理它创建的 Pod。
DaemonSet 的一些典型用途包括:
- 在每个节点上运行集群存储守护进程
- 在每个节点上运行日志收集守护进程
- 在每个节点上运行节点监控守护进程
在简单的情况下,每种类型的守护进程使用一个覆盖所有节点的 DaemonSet。更复杂的设置可能会为单个类型的守护进程使用多个 DaemonSet,但不同的硬件类型具有不同的标志和/或不同的内存和 CPU 请求。
编写 DaemonSet 规约
创建 DaemonSet
你可以在 YAML 文件中描述一个 DaemonSet。例如,下面的 daemonset.yaml
文件描述了一个运行 fluentd-elasticsearch Docker 镜像的 DaemonSet
apiVersion: 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:
tolerations:
# these tolerations are to have the daemonset runnable on control plane nodes
# remove them if your control plane nodes should not run pods
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
# it may be desirable to set a high priority class to ensure that a DaemonSet Pod
# preempts running Pods
# priorityClassName: important
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
基于 YAML 文件创建一个 DaemonSet
kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml
必需字段
与所有其他 Kubernetes 配置一样,DaemonSet 需要 apiVersion
、kind
和 metadata
字段。有关使用配置文件的常规信息,请参阅运行无状态应用程序和使用 kubectl 进行对象管理。
DaemonSet 对象的名称必须是有效的 DNS 子域名。
DaemonSet 还需要一个 .spec
部分。
Pod 模板
.spec.template
是 .spec
中必需的字段之一。
.spec.template
是一个 Pod 模板。它的架构与Pod完全相同,除了它是嵌套的并且没有 apiVersion
或 kind
。
除了 Pod 的必需字段外,DaemonSet 中的 Pod 模板还必须指定适当的标签(请参阅Pod 选择算符)。
DaemonSet 中的 Pod 模板必须具有一个等于 Always
的 RestartPolicy
,或者不指定,它默认为 Always
。
Pod 选择算符
.spec.selector
字段是一个 Pod 选择算符。它的工作方式与 Job 的 .spec.selector
相同。
你必须指定一个与 .spec.template
的标签匹配的 Pod 选择算符。此外,一旦创建了 DaemonSet,它的 .spec.selector
就不能被修改。修改 Pod 选择算符可能会导致 Pod 的意外孤立,并且发现这会让用户感到困惑。
.spec.selector
是一个包含两个字段的对象
matchLabels
- 与 ReplicationController 的.spec.selector
的工作方式相同。matchExpressions
- 允许通过指定键、值列表以及关联键和值的运算符来构建更复杂的选择算符。
当同时指定这两个时,结果会被进行 AND 运算。
.spec.selector
必须与 .spec.template.metadata.labels
匹配。API 将拒绝这两个不匹配的配置。
在选定的节点上运行 Pod
如果指定 .spec.template.spec.nodeSelector
,则 DaemonSet 控制器将在与该节点选择算符匹配的节点上创建 Pod。同样,如果指定 .spec.template.spec.affinity
,则 DaemonSet 控制器将在与该节点亲和性匹配的节点上创建 Pod。如果两者都不指定,则 DaemonSet 控制器将在所有节点上创建 Pod。
Daemon Pod 如何被调度
DaemonSet 可用于确保所有符合条件的节点都运行一个 Pod 的副本。DaemonSet 控制器为每个符合条件的节点创建一个 Pod,并添加 Pod 的 spec.affinity.nodeAffinity
字段以匹配目标主机。创建 Pod 后,默认调度器通常会接管,然后通过设置 .spec.nodeName
字段将 Pod 绑定到目标主机。如果新 Pod 无法容纳在节点上,则默认调度器可能会根据新 Pod 的优先级抢占(驱逐)一些现有 Pod。
说明
如果 DaemonSet Pod 在每个节点上运行非常重要,通常希望将 DaemonSet 的.spec.template.spec.priorityClassName
设置为具有较高优先级的PriorityClass,以确保发生此驱逐。用户可以通过设置 DaemonSet 的 .spec.template.spec.schedulerName
字段来为 DaemonSet 的 Pod 指定不同的调度器。
DaemonSet 控制器在评估符合条件的节点时会考虑在 .spec.template.spec.affinity.nodeAffinity
字段(如果指定)指定的原始节点亲和性,但在创建的 Pod 上会被替换为与符合条件的节点的名称匹配的节点亲和性。
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- target-host-name
污点和容忍
DaemonSet 控制器自动向 DaemonSet Pod 添加一组容忍
容忍键 | 效果 | 详情 |
---|---|---|
node.kubernetes.io/not-ready | NoExecute | DaemonSet Pod 可以被调度到不健康或未准备好接受 Pod 的节点上。任何在此类节点上运行的 DaemonSet Pod 都不会被驱逐。 |
node.kubernetes.io/unreachable | NoExecute | DaemonSet Pod 可以被调度到从节点控制器无法访问的节点上。任何在此类节点上运行的 DaemonSet Pod 都不会被驱逐。 |
node.kubernetes.io/disk-pressure | NoSchedule | DaemonSet Pod 可以被调度到存在磁盘压力问题的节点上。 |
node.kubernetes.io/memory-pressure | NoSchedule | DaemonSet Pod 可以被调度到存在内存压力问题的节点上。 |
node.kubernetes.io/pid-pressure | NoSchedule | DaemonSet Pod 可以被调度到存在进程压力问题的节点上。 |
node.kubernetes.io/unschedulable | NoSchedule | DaemonSet Pod 可以被调度到不可调度的节点上。 |
node.kubernetes.io/network-unavailable | NoSchedule | 仅针对请求主机网络的 DaemonSet Pod 添加,即具有 spec.hostNetwork: true 的 Pod。此类 DaemonSet Pod 可以被调度到网络不可用的节点上。 |
你也可以通过在 DaemonSet 的 Pod 模板中定义来向 DaemonSet 的 Pod 添加你自己的容忍。
由于 DaemonSet 控制器自动设置 node.kubernetes.io/unschedulable:NoSchedule
容忍,因此 Kubernetes 可以在标记为不可调度的节点上运行 DaemonSet Pod。
如果你使用 DaemonSet 提供重要的节点级功能,例如集群网络,那么 Kubernetes 在节点准备就绪之前将 DaemonSet Pod 放置在节点上是很有帮助的。例如,如果没有该特殊容忍,你可能会陷入僵局,因为网络插件未在那里运行,因此节点未被标记为准备就绪,同时网络插件未在该节点上运行,因为该节点尚未准备就绪。
与 Daemon Pod 通信
与 DaemonSet 中的 Pod 通信的一些可能的模式是
- 推送:DaemonSet 中的 Pod 被配置为向另一个服务(例如统计数据库)发送更新。它们没有客户端。
- NodeIP 和已知端口:DaemonSet 中的 Pod 可以使用
hostPort
,以便可以通过节点 IP 访问 Pod。客户端以某种方式知道节点 IP 的列表,并且按照约定知道端口。 - DNS:创建一个具有相同 Pod 选择算符的无头服务,然后使用
endpoints
资源发现 DaemonSet 或从 DNS 检索多个 A 记录。 - 服务:创建一个具有相同 Pod 选择算符的服务,并使用该服务访问随机节点上的守护进程。(无法访问特定节点。)
更新 DaemonSet
如果更改了节点标签,则 DaemonSet 将立即向新匹配的节点添加 Pod,并从新不匹配的节点删除 Pod。
你可以修改 DaemonSet 创建的 Pod。但是,Pod 不允许更新所有字段。此外,下次创建节点(即使具有相同的名称)时,DaemonSet 控制器将使用原始模板。
你可以删除 DaemonSet。如果在 kubectl
中指定 --cascade=orphan
,则 Pod 将保留在节点上。如果随后创建具有相同选择算符的新 DaemonSet,则新 DaemonSet 会采用现有 Pod。如果任何 Pod 需要替换,DaemonSet 会根据其 updateStrategy
替换它们。
你可以在 DaemonSet 上执行滚动更新。
DaemonSet 的替代方案
初始化脚本
当然可以通过直接在节点上启动它们(例如使用 init
、upstartd
或 systemd
)来运行守护进程。这完全没问题。但是,通过 DaemonSet 运行此类进程有几个优点
- 能够像监控和管理应用程序一样,监控和管理守护进程的日志。
- 守护进程和应用程序使用相同的配置语言和工具(例如,Pod 模板、
kubectl
)。 - 在容器中使用资源限制运行守护进程,可以增强守护进程与应用程序容器之间的隔离。 然而,也可以通过在容器中运行守护进程,但不将其放在 Pod 中来实现这一点。
裸 Pod
可以直接创建 Pod,指定在哪个特定节点上运行。 但是,DaemonSet 会替换因任何原因被删除或终止的 Pod,例如节点故障或破坏性节点维护(如内核升级)。 因此,你应该使用 DaemonSet,而不是创建单独的 Pod。
静态 Pod
可以通过将文件写入 Kubelet 监控的特定目录来创建 Pod。 这些称为静态 Pod。与 DaemonSet 不同,静态 Pod 不能通过 kubectl 或其他 Kubernetes API 客户端进行管理。 静态 Pod 不依赖于 apiserver,这使得它们在集群引导场景中很有用。 此外,静态 Pod 将来可能会被弃用。
Deployment
DaemonSet 与 Deployment 类似,它们都会创建 Pod,并且这些 Pod 运行的进程不应终止(例如,Web 服务器、存储服务器)。
对于无状态服务(如前端),使用 Deployment,因为扩展和缩减副本数量以及滚动更新比精确控制 Pod 在哪个主机上运行更重要。 当必须确保 Pod 的副本始终在所有或某些主机上运行时,请使用 DaemonSet,如果 DaemonSet 提供节点级功能,允许其他 Pod 在特定节点上正确运行。
例如,网络插件通常包含一个以 DaemonSet 形式运行的组件。 DaemonSet 组件确保其运行所在的节点具有正常工作的集群网络。
下一步
- 了解关于 Pod 的信息。
- 了解如何使用 DaemonSet
- 对 DaemonSet 执行滚动更新
- 在 DaemonSet 上执行回滚(例如,如果滚动更新未按预期工作)。
- 了解 Kubernetes 如何将 Pod 分配给节点。
- 了解 设备插件和 插件,它们通常以 DaemonSet 的形式运行。
DaemonSet
是 Kubernetes REST API 中的顶级资源。阅读 DaemonSet 对象定义,了解守护进程集的 API。