DaemonSet

    DaemonSet 的一些典型用法:

    • 在每个节点上运行集群守护进程
    • 在每个节点上运行日志收集守护进程
    • 在每个节点上运行监控守护进程

    一种简单的用法是为每种类型的守护进程在所有的节点上都启动一个 DaemonSet。 一个稍微复杂的用法是为同一种守护进程部署多个 DaemonSet;每个具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求。

    你可以在 YAML 文件中描述 DaemonSet。 例如,下面的 daemonset.yaml 文件描述了一个运行 fluentd-elasticsearch Docker 镜像的 DaemonSet:

    基于 YAML 文件创建 DaemonSet:

    必需字段

    和所有其他 Kubernetes 配置一样,DaemonSet 需要 apiVersionkindmetadata 字段。 有关配置文件的基本信息,参见 部署应用、 和 使用 kubectl 进行对象管理 文档。

    DaemonSet 对象的名称必须是一个合法的 。

    DaemonSet 也需要一个 .spec 配置段。

    Pod 模板

    .spec 中唯一必需的字段是 .spec.template

    .spec.template 是一个 。 除了它是嵌套的,因而不具有 apiVersionkind 字段之外,它与 Pod 具有相同的 schema。

    除了 Pod 必需字段外,在 DaemonSet 中的 Pod 模板必须指定合理的标签(查看 )。

    在 DaemonSet 中的 Pod 模板必须具有一个值为 AlwaysRestartPolicy。 当该值未指定时,默认是 Always

    从 Kubernetes 1.8 开始,您必须指定与 .spec.template 的标签匹配的 Pod 选择算符。 用户不指定 Pod 选择算符时,该字段不再有默认值。 选择算符的默认值生成结果与 kubectl apply 不兼容。 此外,一旦创建了 DaemonSet,它的 .spec.selector 就不能修改。 修改 Pod 选择算符可能导致 Pod 意外悬浮,并且这对用户来说是费解的。

    是一个对象,如下两个字段组成:

    • matchExpressions - 允许构建更加复杂的选择器,可以通过指定 key、value 列表以及将 key 和 value 列表关联起来的 operator。

    当上述两个字段都指定时,结果会按逻辑与(AND)操作处理。

    如果指定了 .spec.selector,必须与 .spec.template.metadata.labels 相匹配。 如果与后者不匹配,则 DeamonSet 会被 API 拒绝。

    仅在某些节点上运行 Pod

    如果指定了 .spec.template.spec.nodeSelector,DaemonSet 控制器将在能够与 匹配的节点上创建 Pod。 类似这种情况,可以指定 .spec.template.spec.affinity,之后 DaemonSet 控制器 将在能够与节点亲和性 匹配的节点上创建 Pod。 如果根本就没有指定,则 DaemonSet Controller 将在所有节点上创建 Pod。

    通过默认调度器调度

    FEATURE STATE: Kubernetes v1.20 [stable]

    DaemonSet 确保所有符合条件的节点都运行该 Pod 的一个副本。 通常,运行 Pod 的节点由 Kubernetes 调度器选择。 不过,DaemonSet Pods 由 DaemonSet 控制器创建和调度。这就带来了以下问题:

    • Pod 行为的不一致性:正常 Pod 在被创建后等待调度时处于 Pending 状态, DaemonSet Pods 创建后不会处于 Pending 状态下。这使用户感到困惑。
    • 由默认调度器处理。启用抢占后,DaemonSet 控制器将在不考虑 Pod 优先级和抢占 的情况下制定调度决策。

    ScheduleDaemonSetPods 允许您使用默认调度器而不是 DaemonSet 控制器来调度 DaemonSets, 方法是将 NodeAffinity 条件而不是 .spec.nodeName 条件添加到 DaemonSet Pods。 默认调度器接下来将 Pod 绑定到目标主机。 如果 DaemonSet Pod 的节点亲和性配置已存在,则被替换。 DaemonSet 控制器仅在创建或修改 DaemonSet Pod 时执行这些操作, 并且不会更改 DaemonSet 的 spec.template

    此外,系统会自动添加 node.kubernetes.io/unschedulable:NoSchedule 容忍度到 DaemonSet Pods。在调度 DaemonSet Pod 时,默认调度器会忽略 unschedulable 节点。

    尽管 Daemon Pods 遵循污点和容忍度 规则,根据相关特性,控制器会自动将以下容忍度添加到 DaemonSet Pod:

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

    • 推送(Push):配置 DaemonSet 中的 Pod,将更新发送到另一个服务,例如统计数据库。 这些服务没有客户端。

    • DNS:创建具有相同 Pod 选择算符的 , 通过使用 endpoints 资源或从 DNS 中检索到多个 A 记录来发现 DaemonSet。

    • Service:创建具有相同 Pod 选择算符的服务,并使用该服务随机访问到某个节点上的 守护进程(没有办法访问到特定节点)。

    如果节点的标签被修改,DaemonSet 将立刻向新匹配上的节点添加 Pod, 同时删除不匹配的节点上的 Pod。

    你可以修改 DaemonSet 创建的 Pod。不过并非 Pod 的所有字段都可更新。 下次当某节点(即使具有相同的名称)被创建时,DaemonSet 控制器还会使用最初的模板。

    您可以删除一个 DaemonSet。如果使用 kubectl 并指定 --cascade=false 选项, 则 Pod 将被保留在节点上。接下来如果创建使用相同选择算符的新 DaemonSet, 新的 DaemonSet 会收养已有的 Pod。 如果有 Pod 需要被替换,DaemonSet 会根据其 updateStrategy 来替换。

    你可以对 DaemonSet 执行滚动更新操作。

    init 脚本

    直接在节点上启动守护进程(例如使用 initupstartdsystemd)的做法当然是可行的。 不过,基于 DaemonSet 来运行这些进程有如下一些好处:

    • 像所运行的其他应用一样,DaemonSet 具备为守护进程提供监控和日志管理的能力。

    • 为守护进程和应用所使用的配置语言和工具(如 Pod 模板、kubectl)是相同的。

    裸 Pod

    直接创建 Pod并指定其运行在特定的节点上也是可以的。 然而,DaemonSet 能够替换由于任何原因(例如节点失败、例行节点维护、内核升级) 而被删除或终止的 Pod。 由于这个原因,你应该使用 DaemonSet 而不是单独创建 Pod。

    通过在一个指定的、受 kubelet 监视的目录下编写文件来创建 Pod 也是可行的。 这类 Pod 被称为。 不像 DaemonSet,静态 Pod 不受 kubectl 和其它 Kubernetes API 客户端管理。 静态 Pod 不依赖于 API 服务器,这使得它们在启动引导新集群的情况下非常有用。 此外,静态 Pod 在将来可能会被废弃。

    Deployments