第 3 章 使用作业和 DaemonSet

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

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

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

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

为安全起见,只有集群管理员才能创建 daemonset。

如需有关 daemonset 的更多信息,请参阅 Kubernetes 文档

重要

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

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

DaemonSet 可确保符合条件的所有节点都运行 Pod 的副本。通常,Kubernetes 调度程序会选择要在其上运行 Pod 的节点。然而,DaemonSet 控制器创建并调度了前面的 daemonSet pod。这会引发以下问题:

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

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

nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchFields: - key: metadata.name operator: In values: - target-host-name

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

3.1.2. 创建 daemonset

在创建 daemonset 时,请使用 nodeSelector 字段来指示 daemonset 应该在其上部署副本的节点。

先决条件

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

    $ oc patch namespace myproject -p \
        '{"metadata": {"annotations": {"openshift.io/node-selector": ""}}}'
  • 如果要创建新项目,请使用 oc adm new-project <name> --node-selector="" 覆盖默认节点选择器。

流程

创建 daemonset:

  1. 定义 daemonset yaml 文件:

    apiVersion: extensions/v1beta1
    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 属于 daemonset 的标签选择器。
    2
    pod 模板的标签选择器。必须与上述标签选择器匹配。
    3
    决定应该在哪些节点上部署 pod 副本的节点选择器。节点上必须存在匹配的标签。
  2. 创建 daemonset 对象:

    $ 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
重要
  • 如果更新 daemonset 的 pod 模板,现有的 pod 副本不受影响。
  • 如果您删除了 daemonSet,然后在创建新 daemonset 时使用不同的模板和相同的标签选择器,它会将现有 pod 副本识别为具有匹配的标签,因而不更新它们,也不会创建新的副本,尽管 pod 模板中存在不匹配。
  • 如果您更改了节点标签,daemonset 会把 pod 添加到与新标签匹配的节点,并从不匹配新标签的节点中删除 pod。

要更新 daemonset,请通过删除旧副本或旧节点来强制创建新的 pod 副本。