第 5 章 使用作业和 DaemonSet

5.1. 使用 daemonset 在节点上自动运行后台任务

作为管理员,您可以创建并使用守护进程集在 OpenShift Container Platform 集群的特定节点或所有节点上运行 pod 副本。

守护进程集确保所有(或部分)节点都运行 pod 的副本。当节点添加到集群中时,pod 也会添加到集群中。当节点从集群中移除时,这些 pod 也会通过垃圾回收而被移除。删除守护进程集会清理它创建的 pod。

您可以使用 daemonset 创建共享存储,在集群的每一节点上运行日志 pod,或者在每个节点上部署监控代理。

为安全起见,集群管理员和项目管理员可以创建守护进程集。

如需有关守护进程集的更多信息,请参阅 Kubernetes 文档

重要

守护进程集调度与项目的默认节点选择器不兼容。如果您没有禁用它,守护进程集会与默认节点选择器合并,从而受到限制。这会造成在合并后节点选择器没有选中的节点上频繁地重新创建 pod,进而给集群带来意外的负载。

5.1.1. 通过默认调度程序调度

守护进程集确保所有有资格的节点都运行 pod 的副本。通常,Kubernetes 调度程序会选择要在其上运行 pod 的节点。但是,守护进程集 pod 由守护进程集控制器创建并调度。这会引发以下问题:

  • pod 行为不一致:等待调度的普通 pod 被创建好并处于待处理状态,但守护进程集 pod 没有以待处理的状态创建。这会给用户造成混淆。
  • Pod 抢占由默认调度程序处理。启用抢占后,守护进程集控制器将在不考虑 pod 优先级和抢占的前提下做出调度决策。

OpenShift Container Platform 中默认启用 ScheduleDaemonSetPods 功能允许您使用默认调度程序而不是守护进程集控制器来调度守护进程集,具体方法是添加 NodeAffinity 术语到守护进程集 pod,而不是 .spec.nodeName 术语。然后,默认调度程序用于将 pod 绑定到目标主机。如果守护进程集的节点关联性已经存在,它会被替换掉。守护进程设置控制器仅在创建或修改守护进程集 pod 时执行这些操作,且不会对守护进程集的 spec.template 进行任何更改。

kind: Pod
apiVersion: v1
metadata:
  name: hello-node-6fbccf8d9-9tmzr
#...
spec:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchFields:
        - key: metadata.name
          operator: In
          values:
          - target-host-name
#...

另外,node.kubernetes.io/unschedulable:NoSchedule 容限会自动添加到守护进程设置 Pod 中。在调度守护进程设置 pod 时,默认调度程序会忽略不可调度的节点。

5.1.2. 创建 daemonset

在创建守护进程集时,使用 nodeSelector 字段来指示守护进程集应在其上部署副本的节点。

先决条件

  • 在开始使用守护进程集之前,通过将命名空间注解 openshift.io/node-selector 设置为空字符串来禁用命名空间中的默认项目范围节点选择器:

    $ oc patch namespace myproject -p \
        '{"metadata": {"annotations": {"openshift.io/node-selector": ""}}}'
    提示

    您还可以应用以下 YAML 来为命名空间禁用默认的项目范围节点选择器:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: <namespace>
      annotations:
        openshift.io/node-selector: ''
    #...
  • 如果您要创建新项目,请覆盖默认节点选择器:

    $ oc adm new-project <name> --node-selector=""

流程

创建守护进程集:

  1. 定义守护进程集 yaml 文件:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: hello-daemonset
    spec:
      selector:
          matchLabels:
            name: hello-daemonset 1
      template:
        metadata:
          labels:
            name: hello-daemonset 2
        spec:
          nodeSelector: 3
            role: worker
          containers:
          - image: openshift/hello-openshift
            imagePullPolicy: Always
            name: registry
            ports:
            - containerPort: 80
              protocol: TCP
            resources: {}
            terminationMessagePath: /dev/termination-log
          serviceAccount: default
          terminationGracePeriodSeconds: 10
    #...
    1
    决定哪些 pod 属于守护进程集的标签选择器。
    2
    pod 模板的标签选择器。必须与上述标签选择器匹配。
    3
    决定应该在哪些节点上部署 pod 副本的节点选择器。节点上必须存在匹配的标签。
  2. 创建守护进程集对象:

    $ oc create -f daemonset.yaml
  3. 验证 pod 是否已创建好,并且每个节点都有 pod 副本:

    1. 查找 daemonset pod:

      $ oc get pods

      输出示例

      hello-daemonset-cx6md   1/1       Running   0          2m
      hello-daemonset-e3md9   1/1       Running   0          2m

    2. 查看 pod 以验证 pod 已放置到节点上:

      $ oc describe pod/hello-daemonset-cx6md|grep Node

      输出示例

      Node:        openshift-node01.hostname.com/10.14.20.134

      $ oc describe pod/hello-daemonset-e3md9|grep Node

      输出示例

      Node:        openshift-node02.hostname.com/10.14.20.137

重要
  • 如果更新守护进程设置的 pod 模板,现有的 pod 副本不会受到影响。
  • 如果您删除了守护进程集,然后在创建新守护进程集时使用不同的模板和相同的标签选择器,它会将现有 pod 副本识别为具有匹配的标签,因而不更新它们,也不会创建新的副本,尽管 pod 模板中存在不匹配。
  • 如果您更改了节点标签,守护进程集会把 pod 添加到与新标签匹配的节点,并从不匹配新标签的节点中删除 pod。

要更新守护进程集,请通过删除旧副本或节点来强制创建新的 pod 副本。