// Module included in the following assemblies:
//
// * nodes/nodes-scheduler-node-selector.adoc

:_mod-docs-content-type: PROCEDURE
[id="nodes-scheduler-node-selectors-project_{context}"]
= Creating project-wide node selectors

[role="_abstract"]
You can use node selectors in a project together with labels on nodes to constrain all pods created in that project to the labeled nodes.

When you create a pod in this project, {product-title} adds the node selectors to the pods in the project and schedules the pods on a node with matching labels in the project. If there is a cluster-wide default node selector, a project node selector takes preference.

You add node selectors to a project by editing the `Namespace` object to add the `openshift.io/node-selector` parameter. You add labels to a node, a compute machine set, or a machine config. Adding the label to the compute machine set ensures that if the node or machine goes down, new nodes have the label. Labels added to a node or machine config do not persist if the node or machine goes down.

A pod is not scheduled if the `Pod` object contains a node selector, but no project has a matching node selector. When you create a pod from that spec, you receive an error similar to the following message:

[source,terminal]
----
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
----

[NOTE]
====
You can add additional key/value pairs to a pod. But you cannot add a different value for a project key.
====

The following procedure adds a default project node selector.

.Procedure

. Create a namespace or edit an existing namespace to add the `openshift.io/node-selector` parameter:
+
[source,terminal]
----
$ oc edit namespace <name>
----
+
.Example output
[source,yaml]
----
apiVersion: v1
kind: Namespace
metadata:
  annotations:
    openshift.io/node-selector: "type=user-node,region=east"
    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
----
+
Add the `openshift.io/node-selector` annotation with the appropriate `<key>:<value>` pairs.

. Add labels to a node by using a compute machine set or editing the node directly:

* Use a `MachineSet` object to add labels to nodes managed by the compute machine set when a node is created:

.. Run the following command to add labels to a `MachineSet` object:
+
[source,terminal]
----
$ oc patch MachineSet <name> --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"<key>"="<value>","<key>"="<value>"}}]'  -n openshift-machine-api
----
+
For example:
+
[source,terminal]
----
$ 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
----
+
[TIP]
====
You can alternatively apply the following YAML to add labels to a compute machine set:

[source,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"
----
====

.. Verify that the labels are added to the `MachineSet` object by using the `oc edit` command:
+
For example:
+
[source,terminal]
----
$ oc edit MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
----
+
.Example output
[source,yaml]
----
apiVersion: machine.openshift.io/v1beta1
kind: MachineSet
metadata:
...
spec:
...
  template:
    metadata:
...
    spec:
      metadata:
        labels:
          region: east
          type: user-node
----

.. Redeploy the nodes associated with that compute machine set:
+
For example:
+
[source,terminal]
----
$ oc scale --replicas=0 MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
----
+
[source,terminal]
----
$ oc scale --replicas=1 MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
----

.. When the nodes are ready and available, verify that the label is added to the nodes by using the `oc get` command:
+
[source,terminal]
----
$ oc get nodes -l <key>=<value>
----
+
For example:
+
[source,terminal]
----
$ oc get nodes -l type=user-node
----
+
.Example output
[source,terminal]
----
NAME                                       STATUS   ROLES    AGE   VERSION
ci-ln-l8nry52-f76d1-hl7m7-worker-c-vmqzp   Ready    worker   61s   v1.35.4
----

* Add labels directly to a node:

.. Edit the `Node` object to add labels:
+
[source,terminal]
----
$ oc label <resource> <name> <key>=<value>
----
+
For example, to label a node:
+
[source,terminal]
----
$ oc label nodes ci-ln-l8nry52-f76d1-hl7m7-worker-c-tgq49 type=user-node region=east
----
+
[TIP]
====
You can alternatively apply the following YAML to add labels to a node:

[source,yaml]
----
kind: Node
apiVersion: v1
metadata:
  name: <node_name>
  labels:
    type: "user-node"
    region: "east"
----
====

.. Verify that the labels are added to the `Node` object using the `oc get` command:
+
[source,terminal]
----
$ oc get nodes -l <key>=<value>
----
+
For example:
+
[source,terminal]
----
$ oc get nodes -l type=user-node,region=east
----
+
.Example output
[source,terminal]
----
NAME                                       STATUS   ROLES    AGE   VERSION
ci-ln-l8nry52-f76d1-hl7m7-worker-b-tgq49   Ready    worker   17m   v1.35.4
----
