守护进程集
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 模板必须具有 RestartPolicy
等于 Always
,或者未指定,默认为 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
设置为具有更高优先级的 优先级类,以确保发生此驱逐操作。用户可以通过设置 DaemonSet 的 .spec.template.spec.schedulerName
字段来为 DaemonSet 的 Pod 指定不同的调度程序。
在 .spec.template.spec.affinity.nodeAffinity
字段(如果指定)中指定的原始节点亲和性会在 DaemonSet 控制器评估符合条件的节点时被考虑,但在创建的 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 可能在将来被弃用。
部署
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。