×

节点选择器指定一个键值对映射,这些键值对使用节点上的自定义标签和Pod中指定的选择器进行定义。

为了使Pod能够在节点上运行,Pod必须与节点上的标签具有相同的键值节点选择器。

关于节点选择器

您可以使用Pod上的节点选择器和节点上的标签来控制Pod的调度位置。使用节点选择器,OpenShift Container Platform 将Pod调度到包含匹配标签的节点上。

您可以使用节点选择器将特定Pod放置在特定节点上,使用集群范围节点选择器将新的Pod放置在集群中任何位置的特定节点上,以及使用项目节点选择器将项目中的新的Pod放置在特定节点上。

例如,作为集群管理员,您可以创建一个基础架构,让应用程序开发人员只能将Pod部署到最接近其地理位置的节点上,方法是在他们创建的每个Pod中包含一个节点选择器。在这个示例中,集群包含五个分布在两个区域的数据中心。在美国,将节点标记为us-eastus-centralus-west。在亚太地区(APAC),将节点标记为apac-eastapac-west。开发人员可以向他们创建的Pod添加节点选择器,以确保Pod被调度到这些节点上。

如果Pod对象包含节点选择器,但没有节点具有匹配的标签,则不会调度Pod。

如果您在同一个Pod配置中同时使用节点选择器和节点亲和性,则以下规则控制Pod放置到节点上

  • 如果您同时配置nodeSelectornodeAffinity,则必须满足这两个条件才能将Pod调度到候选节点上。

  • 如果您指定与nodeAffinity类型关联的多个nodeSelectorTerms,则如果满足其中一个nodeSelectorTerms,则可以将Pod调度到节点上。

  • 如果您指定与nodeSelectorTerms关联的多个matchExpressions,则只有在满足所有matchExpressions时,才能将Pod调度到节点上。

特定Pod和节点上的节点选择器

您可以使用节点选择器和标签来控制调度特定Pod的节点。

要使用节点选择器和标签,首先标记节点以避免Pod被取消调度,然后将节点选择器添加到Pod。

您不能直接将节点选择器添加到现有已调度的Pod。您必须标记控制Pod的对象,例如部署配置。

例如,以下Node对象具有region: east标签

带有标签的示例Node对象
kind: Node
apiVersion: v1
metadata:
  name: ip-10-0-131-14.ec2.internal
  selfLink: /api/v1/nodes/ip-10-0-131-14.ec2.internal
  uid: 7bc2580a-8b8e-11e9-8e01-021ab4174c74
  resourceVersion: '478704'
  creationTimestamp: '2019-06-10T14:46:08Z'
  labels:
    kubernetes.io/os: linux
    topology.kubernetes.io/zone: us-east-1a
    node.openshift.io/os_version: '4.5'
    node-role.kubernetes.io/worker: ''
    topology.kubernetes.io/region: us-east-1
    node.openshift.io/os_id: rhcos
    node.kubernetes.io/instance-type: m4.large
    kubernetes.io/hostname: ip-10-0-131-14
    kubernetes.io/arch: amd64
    region: east (1)
    type: user-node
#...
1 与Pod节点选择器匹配的标签。

一个Pod具有type: user-node,region: east节点选择器

带有节点选择器的示例Pod对象
apiVersion: v1
kind: Pod
metadata:
  name: s1
#...
spec:
  nodeSelector: (1)
    region: east
    type: user-node
#...
1 与节点标签匹配的节点选择器。节点必须为每个节点选择器都有一个标签。

当您使用示例Pod规范创建Pod时,它可以调度到示例节点上。

默认集群范围节点选择器

使用默认集群范围节点选择器,当您在该集群中创建Pod时,OpenShift Container Platform 会将默认节点选择器添加到Pod,并将Pod调度到具有匹配标签的节点上。

例如,以下Scheduler对象具有默认集群范围的region=easttype=user-node节点选择器

示例调度程序操作符自定义资源
apiVersion: config.openshift.io/v1
kind: Scheduler
metadata:
  name: cluster
#...
spec:
  defaultNodeSelector: type=user-node,region=east
#...

该集群中的一个节点具有type=user-node,region=east标签

示例Node对象
apiVersion: v1
kind: Node
metadata:
  name: ci-ln-qg1il3k-f76d1-hlmhl-worker-b-df2s4
#...
  labels:
    region: east
    type: user-node
#...
带有节点选择器的示例Pod对象
apiVersion: v1
kind: Pod
metadata:
  name: s1
#...
spec:
  nodeSelector:
    region: east
#...

在示例集群中使用示例 Pod 规范创建 Pod 时,该 Pod 将使用集群范围的节点选择器创建,并调度到标记的节点上

带有标记节点上 Pod 的示例 Pod 列表
NAME     READY   STATUS    RESTARTS   AGE   IP           NODE                                       NOMINATED NODE   READINESS GATES
pod-s1   1/1     Running   0          20s   10.131.2.6   ci-ln-qg1il3k-f76d1-hlmhl-worker-b-df2s4   <none>           <none>

如果您创建 Pod 的项目具有项目节点选择器,则该选择器优先于集群范围的节点选择器。如果 Pod 不具有项目节点选择器,则不会创建或调度您的 Pod。

项目节点选择器

使用项目节点选择器,当您在此项目中创建 Pod 时,OpenShift Container Platform 会将节点选择器添加到 Pod 并将 Pod 调度到具有匹配标签的节点上。如果存在集群范围的默认节点选择器,则项目节点选择器优先。

例如,以下项目具有region=east节点选择器

示例Namespace对象
apiVersion: v1
kind: Namespace
metadata:
  name: east-region
  annotations:
    openshift.io/node-selector: "region=east"
#...

以下节点具有type=user-node,region=east标签

示例Node对象
apiVersion: v1
kind: Node
metadata:
  name: ci-ln-qg1il3k-f76d1-hlmhl-worker-b-df2s4
#...
  labels:
    region: east
    type: user-node
#...

在此示例项目中使用示例 Pod 规范创建 Pod 时,该 Pod 将使用项目节点选择器创建,并调度到标记的节点上

示例Pod对象
apiVersion: v1
kind: Pod
metadata:
  namespace: east-region
#...
spec:
  nodeSelector:
    region: east
    type: user-node
#...
带有标记节点上 Pod 的示例 Pod 列表
NAME     READY   STATUS    RESTARTS   AGE   IP           NODE                                       NOMINATED NODE   READINESS GATES
pod-s1   1/1     Running   0          20s   10.131.2.6   ci-ln-qg1il3k-f76d1-hlmhl-worker-b-df2s4   <none>           <none>

如果 Pod 包含不同的节点选择器,则不会创建或调度项目中的 Pod。例如,如果您将以下 Pod 部署到示例项目中,则不会创建它

具有无效节点选择器的示例Pod对象
apiVersion: v1
kind: Pod
metadata:
  name: west-region
#...
spec:
  nodeSelector:
    region: west
#...

使用节点选择器控制 Pod 位置

您可以使用Pod上的节点选择器和节点上的标签来控制Pod的调度位置。使用节点选择器,OpenShift Container Platform 将Pod调度到包含匹配标签的节点上。

您可以将标签添加到节点、计算机器集或机器配置。将标签添加到计算机器集可确保如果节点或机器出现故障,新节点将具有该标签。如果节点或机器出现故障,则添加到节点或机器配置的标签不会持久存在。

要将节点选择器添加到现有 Pod,请将节点选择器添加到该 Pod 的控制对象,例如ReplicaSet对象、DaemonSet对象、StatefulSet对象、Deployment对象或DeploymentConfig对象。该控制对象下的任何现有 Pod 都会在具有匹配标签的节点上重新创建。如果您正在创建新的 Pod,则可以直接将节点选择器添加到 Pod 规范中。如果 Pod 没有控制对象,则必须删除 Pod,编辑 Pod 规范,然后重新创建 Pod。

您不能直接将节点选择器添加到现有的已调度 Pod。

先决条件

要将节点选择器添加到现有 Pod,请确定该 Pod 的控制对象。例如,router-default-66d5cf9464-m2g75 Pod 受router-default-66d5cf9464副本集控制

$ oc describe pod router-default-66d5cf9464-7pwkc
示例输出
kind: Pod
apiVersion: v1
metadata:
# ...
Name:               router-default-66d5cf9464-7pwkc
Namespace:          openshift-ingress
# ...
Controlled By:      ReplicaSet/router-default-66d5cf9464
# ...

Web 控制台在 Pod YAML 中的ownerReferences下列出控制对象

apiVersion: v1
kind: Pod
metadata:
  name: router-default-66d5cf9464-7pwkc
# ...
  ownerReferences:
    - apiVersion: apps/v1
      kind: ReplicaSet
      name: router-default-66d5cf9464
      uid: d81dd094-da26-11e9-a48a-128e7edf0312
      controller: true
      blockOwnerDeletion: true
# ...
步骤
  1. 使用计算机器集或直接编辑节点来将标签添加到节点

    • 使用MachineSet对象在创建节点时将标签添加到计算机器集管理的节点

      1. 运行以下命令将标签添加到MachineSet对象

        $ oc patch MachineSet <name> --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"<key>"="<value>","<key>"="<value>"}}]'  -n openshift-machine-api

        例如

        $ oc patch MachineSet abc612-msrtw-worker-us-east-1c  --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"type":"user-node","region":"east"}}]'  -n openshift-machine-api

        或者,您可以应用以下 YAML 将标签添加到计算机器集

        apiVersion: machine.openshift.io/v1beta1
        kind: MachineSet
        metadata:
          name: xf2bd-infra-us-east-2a
          namespace: openshift-machine-api
        spec:
          template:
            spec:
              metadata:
                labels:
                  region: "east"
                  type: "user-node"
        # ...
      2. 使用oc edit命令验证标签是否已添加到MachineSet对象

        例如

        $ oc edit MachineSet abc612-msrtw-worker-us-east-1c -n openshift-machine-api
        示例MachineSet对象
        apiVersion: machine.openshift.io/v1beta1
        kind: MachineSet
        
        # ...
        
        spec:
        # ...
          template:
            metadata:
        # ...
            spec:
              metadata:
                labels:
                  region: east
                  type: user-node
        # ...
    • 直接将标签添加到节点

      1. 编辑节点的Node对象

        $ oc label nodes <name> <key>=<value>

        例如,要标记节点

        $ oc label nodes ip-10-0-142-25.ec2.internal type=user-node region=east

        或者,您可以应用以下 YAML 将标签添加到节点

        kind: Node
        apiVersion: v1
        metadata:
          name: hello-node-6fbccf8d9
          labels:
            type: "user-node"
            region: "east"
        # ...
      2. 验证标签是否已添加到节点

        $ oc get nodes -l type=user-node,region=east
        示例输出
        NAME                          STATUS   ROLES    AGE   VERSION
        ip-10-0-142-25.ec2.internal   Ready    worker   17m   v1.30.3
  2. 将匹配的节点选择器添加到 Pod

    • 要将节点选择器添加到现有和将来的 Pod,请将节点选择器添加到 Pod 的控制对象

      带有标签的示例ReplicaSet对象
      kind: ReplicaSet
      apiVersion: apps/v1
      metadata:
        name: hello-node-6fbccf8d9
      # ...
      spec:
      # ...
        template:
          metadata:
            creationTimestamp: null
            labels:
              ingresscontroller.operator.openshift.io/deployment-ingresscontroller: default
              pod-template-hash: 66d5cf9464
          spec:
            nodeSelector:
              kubernetes.io/os: linux
              node-role.kubernetes.io/worker: ''
              type: user-node (1)
      # ...
      1 添加节点选择器。
    • 要将节点选择器添加到特定的新 Pod,请直接将选择器添加到Pod对象

      带有节点选择器的示例Pod对象
      apiVersion: v1
      kind: Pod
      metadata:
        name: hello-node-6fbccf8d9
      # ...
      spec:
        nodeSelector:
          region: east
          type: user-node
      # ...

      您不能直接将节点选择器添加到现有的已调度 Pod。

创建默认集群范围的节点选择器

您可以将 Pod 上的默认集群范围节点选择器与节点上的标签一起使用,以将集群中创建的所有 Pod 限制到特定节点。

使用集群范围的节点选择器,当您在该集群中创建 Pod 时,OpenShift Container Platform 会将默认节点选择器添加到 Pod 并将 Pod 调度到具有匹配标签的节点上。

您可以通过编辑调度程序操作符自定义资源 (CR) 来配置集群范围的节点选择器。您可以将标签添加到节点、计算机器集或机器配置。将标签添加到计算机器集可确保如果节点或机器出现故障,新节点将具有该标签。如果节点或机器出现故障,则添加到节点或机器配置的标签不会持久存在。

您可以向 Pod 添加其他键/值对。但是,您不能为默认键添加不同的值。

步骤

要添加默认集群范围的节点选择器

  1. 编辑调度程序操作符 CR 以添加默认集群范围的节点选择器

    $ oc edit scheduler cluster
    带有节点选择器的示例调度程序操作符 CR
    apiVersion: config.openshift.io/v1
    kind: Scheduler
    metadata:
      name: cluster
    ...
    spec:
      defaultNodeSelector: type=user-node,region=east (1)
      mastersSchedulable: false
    1 添加具有适当<key>:<value>对的节点选择器。

    进行此更改后,等待openshift-kube-apiserver项目中的 Pod 重新部署。这可能需要几分钟时间。默认集群范围的节点选择器只有在 Pod 重新部署后才会生效。

  2. 使用计算机器集或直接编辑节点来将标签添加到节点

    • 使用计算机器集在创建节点时将标签添加到计算机器集管理的节点

      1. 运行以下命令将标签添加到MachineSet对象

        $ oc patch MachineSet <name> --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"<key>"="<value>","<key>"="<value>"}}]'  -n openshift-machine-api (1)
        1 为每个标签添加<key>/<value>对。

        例如

        $ oc patch MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"type":"user-node","region":"east"}}]'  -n openshift-machine-api

        或者,您可以应用以下 YAML 将标签添加到计算机器集

        apiVersion: machine.openshift.io/v1beta1
        kind: MachineSet
        metadata:
          name: <machineset>
          namespace: openshift-machine-api
        spec:
          template:
            spec:
              metadata:
                labels:
                  region: "east"
                  type: "user-node"
      2. 使用oc edit命令验证标签是否已添加到MachineSet对象

        例如

        $ oc edit MachineSet abc612-msrtw-worker-us-east-1c -n openshift-machine-api
        示例MachineSet对象
        apiVersion: machine.openshift.io/v1beta1
        kind: MachineSet
          ...
        spec:
          ...
          template:
            metadata:
          ...
            spec:
              metadata:
                labels:
                  region: east
                  type: user-node
          ...
      3. 通过缩减到0然后扩展节点来重新部署与该计算机器集关联的节点

        例如

        $ oc scale --replicas=0 MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
        $ oc scale --replicas=1 MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
      4. 当节点准备就绪并可用后,使用oc get命令验证标签是否已添加到节点

        $ oc get nodes -l <key>=<value>

        例如

        $ oc get nodes -l type=user-node
        示例输出
        NAME                                       STATUS   ROLES    AGE   VERSION
        ci-ln-l8nry52-f76d1-hl7m7-worker-c-vmqzp   Ready    worker   61s   v1.30.3
    • 直接将标签添加到节点

      1. 编辑节点的Node对象

        $ oc label nodes <name> <key>=<value>

        例如,要标记节点

        $ oc label nodes ci-ln-l8nry52-f76d1-hl7m7-worker-b-tgq49 type=user-node region=east

        或者,您可以应用以下 YAML 将标签添加到节点

        kind: Node
        apiVersion: v1
        metadata:
          name: <node_name>
          labels:
            type: "user-node"
            region: "east"
      2. 使用oc get命令验证标签是否已添加到节点

        $ oc get nodes -l <key>=<value>,<key>=<value>

        例如

        $ oc get nodes -l type=user-node,region=east
        示例输出
        NAME                                       STATUS   ROLES    AGE   VERSION
        ci-ln-l8nry52-f76d1-hl7m7-worker-b-tgq49   Ready    worker   17m   v1.30.3

创建项目范围的节点选择器

您可以将项目中的节点选择器与节点上的标签一起使用,以将该项目中创建的所有 Pod 限制到标记的节点。

当您在此项目中创建 Pod 时,OpenShift Container Platform 会将节点选择器添加到项目中的 Pod 并将 Pod 调度到项目中具有匹配标签的节点上。如果存在集群范围的默认节点选择器,则项目节点选择器优先。

您可以通过编辑Namespace对象以添加openshift.io/node-selector参数来将节点选择器添加到项目。您可以将标签添加到节点、计算机器集或机器配置。将标签添加到计算机器集可确保如果节点或机器出现故障,新节点将具有该标签。如果节点或机器出现故障,则添加到节点或机器配置的标签不会持久存在。

如果Pod对象包含节点选择器,但没有项目具有匹配的节点选择器,则不会调度 Pod。当您从该规范创建 Pod 时,您会收到类似于以下消息的错误

示例错误消息
Error from server (Forbidden): error when creating "pod.yaml": pods "pod-4" is forbidden: pod node label selector conflicts with its project node label selector

您可以向 Pod 添加其他键/值对。但是,您不能为项目键添加不同的值。

步骤

要添加默认项目节点选择器

  1. 创建命名空间或编辑现有命名空间以添加openshift.io/node-selector参数

    $ oc edit namespace <name>
    示例输出
    apiVersion: v1
    kind: Namespace
    metadata:
      annotations:
        openshift.io/node-selector: "type=user-node,region=east" (1)
        openshift.io/description: ""
        openshift.io/display-name: ""
        openshift.io/requester: kube:admin
        openshift.io/sa.scc.mcs: s0:c30,c5
        openshift.io/sa.scc.supplemental-groups: 1000880000/10000
        openshift.io/sa.scc.uid-range: 1000880000/10000
      creationTimestamp: "2021-05-10T12:35:04Z"
      labels:
        kubernetes.io/metadata.name: demo
      name: demo
      resourceVersion: "145537"
      uid: 3f8786e3-1fcb-42e3-a0e3-e2ac54d15001
    spec:
      finalizers:
      - kubernetes
    1 添加openshift.io/node-selector及其相应的<键>:<值>对。
  2. 使用计算机器集或直接编辑节点来将标签添加到节点

    • 使用MachineSet对象在创建节点时将标签添加到计算机器集管理的节点

      1. 运行以下命令将标签添加到MachineSet对象

        $ oc patch MachineSet <name> --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"<key>"="<value>","<key>"="<value>"}}]'  -n openshift-machine-api

        例如

        $ oc patch MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"type":"user-node","region":"east"}}]'  -n openshift-machine-api

        或者,您可以应用以下 YAML 将标签添加到计算机器集

        apiVersion: machine.openshift.io/v1beta1
        kind: MachineSet
        metadata:
          name: <machineset>
          namespace: openshift-machine-api
        spec:
          template:
            spec:
              metadata:
                labels:
                  region: "east"
                  type: "user-node"
      2. 使用oc edit命令验证标签是否已添加到MachineSet对象

        例如

        $ oc edit MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
        示例输出
        apiVersion: machine.openshift.io/v1beta1
        kind: MachineSet
        metadata:
        ...
        spec:
        ...
          template:
            metadata:
        ...
            spec:
              metadata:
                labels:
                  region: east
                  type: user-node
      3. 重新部署与该计算机器集关联的节点

        例如

        $ oc scale --replicas=0 MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
        $ oc scale --replicas=1 MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
      4. 当节点准备就绪并可用后,使用oc get命令验证标签是否已添加到节点

        $ oc get nodes -l <key>=<value>

        例如

        $ oc get nodes -l type=user-node,region=east
        示例输出
        NAME                                       STATUS   ROLES    AGE   VERSION
        ci-ln-l8nry52-f76d1-hl7m7-worker-c-vmqzp   Ready    worker   61s   v1.30.3
    • 直接将标签添加到节点

      1. 编辑Node对象以添加标签

        $ oc label <resource> <name> <key>=<value>

        例如,要标记节点

        $ oc label nodes ci-ln-l8nry52-f76d1-hl7m7-worker-c-tgq49 type=user-node region=east

        或者,您可以应用以下 YAML 将标签添加到节点

        kind: Node
        apiVersion: v1
        metadata:
          name: <node_name>
          labels:
            type: "user-node"
            region: "east"
      2. 使用oc get命令验证标签是否已添加到Node对象

        $ oc get nodes -l <key>=<value>

        例如

        $ oc get nodes -l type=user-node,region=east
        示例输出
        NAME                                       STATUS   ROLES    AGE   VERSION
        ci-ln-l8nry52-f76d1-hl7m7-worker-b-tgq49   Ready    worker   17m   v1.30.3