Introduction

Labels are a useful way to select which nodes that an application will run on. These nodes are created by machines which are defined by the MachineSets we worked with in previous sections of this workshop. An example of this would be running a memory intensive application only on a specific node type.

While you can directly add a label to a node, it is not recommended because nodes can be recreated, which would cause the label to disappear. Therefore we need to label the MachineSet itself. An important caveat to this process is that only new machines created by the MachineSet will get the label. This means you will need to either scale the MachineSet down to zero then back up to create new machines with the label, or you can label the existing machines directly.

Set a label for the MachineSet

  1. Just like the last section, let’s pick a MachineSet to add our label. To do so, run the following command:

    MACHINESET=$(oc -n openshift-machine-api get machinesets -o name | head -1)
    
    echo ${MACHINESET}
    Sample Output
    machineset.machine.openshift.io/aro-cluster-lwqq8-8mkmr-worker-eastus1
  2. Now, let’s patch the MachineSet with our new label. To do so, run the following command:

    oc -n openshift-machine-api patch ${MACHINESET} \
      --type=merge \
      --patch '{"spec":{"template":{"spec":{"metadata":{"labels":{"tier":"frontend"}}}}}}'
    Sample Output
    machineset.machine.openshift.io/aro-cluster-lwqq8-8mkmr-worker-eastus1 patched
  3. As you’ll remember, the existing machines won’t get this label, but all new machines will. While we could just scale this MachineSet down to zero and back up again, that could disrupt our workloads. Instead, let’s just loop through and add the label to all of our nodes in that MachineSet. To do so, run the following command:

    MACHINES=$(oc -n openshift-machine-api get machines -o name -l "machine.openshift.io/cluster-api-machineset=$(echo $MACHINESET | cut -d / -f2 )" | cut -d / -f2 | xargs)
    
    for MACHINE in $(echo ${MACHINES}); do
      oc label -n openshift-machine-api machine ${MACHINE} tier=frontend
      oc label node ${MACHINE} tier=frontend
    done
    Sample Output
    machine.machine.openshift.io/aro-cluster-lwqq8-8mkmr-worker-eastus1-6qt5v labeled
    node/aro-cluster-lwqq8-8mkmr-worker-eastus1-6qt5v labeled
    machine.machine.openshift.io/aro-cluster-lwqq8-8mkmr-worker-eastus1-8vzrw labeled
    node/aro-cluster-lwqq8-8mkmr-worker-eastus1-8vzrw labeled
    machine.machine.openshift.io/aro-cluster-lwqq8-8mkmr-worker-eastus1-vgmng labeled
    node/aro-cluster-lwqq8-8mkmr-worker-eastus1-vgmng labeled

    Depending when (or if) you did the Autoscaling lab you may have 1, 2 or 3 Machines and Nodes that get the label.

  4. Now, let’s verify the nodes are properly labeled. To do so, run the following command:

    oc get nodes --selector='tier=frontend' -o name
    Sample Output
    node/aro-cluster-lwqq8-8mkmr-worker-eastus1-6qt5v
    node/aro-cluster-lwqq8-8mkmr-worker-eastus1-8vzrw
    node/aro-cluster-lwqq8-8mkmr-worker-eastus1-vgmng

    Pending that your output shows one or more node(s), this demonstrates that our MachineSet and associated nodes are properly annotated!

Deploy an app to the labeled nodes

Now that we’ve successfully labeled our nodes, let’s deploy a workload to demonstrate app placement using nodeSelector. This should force our app to deploy only on labeled nodes.

  1. First, let’s create a namespace (also known as a project in OpenShift). To do so, run the following command:

    oc new-project nodeselector-ex
    Sample Output
    Now using project "nodeselector-ex" on server "https://api.rbrlitrg.westeurope.aroapp.io:6443".
    
    You can add applications to this project with the 'new-app' command. For example, try:
    
        oc new-app rails-postgresql-example
    
    to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:
    
        kubectl create deployment hello-node --image=k8s.gcr.io/e2e-test-images/agnhost:2.33 -- /agnhost serve-hostname
  2. Next, let’s deploy our application and associated resources that will target our labeled nodes. Notice how we added the nodeSelector to the specification of our Deployment to do this. Run the following command:

    cat << EOF | oc create -f -
    ---
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: nodeselector-app
      namespace: nodeselector-ex
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nodeselector-app
      template:
        metadata:
          labels:
            app: nodeselector-app
        spec:
          nodeSelector:
            tier: frontend
          containers:
            - name: hello-openshift
              image: "docker.io/openshift/hello-openshift"
              ports:
                - containerPort: 8080
                  protocol: TCP
                - containerPort: 8888
                  protocol: TCP
    EOF
    Sample Output
    deployment.apps/nodeselector-app created
  3. Now, let’s validate that the application has been deployed to one of the labeled nodes. To do so, run the following command:

    oc -n nodeselector-ex get pod -l app=nodeselector-app \
       -o jsonpath='{.items[0].spec.nodeName}'; echo
    Sample Output
    aro-cluster-lwqq8-8mkmr-worker-eastus1-6qt5v
  4. Double check the name of the node to compare it to the output above to ensure the node selector worked to put the pod on the correct node:

    oc get nodes --selector='tier=frontend' -o name
    Sample Output
    node/aro-cluster-lwqq8-8mkmr-worker-eastus1-6qt5v
    node/aro-cluster-lwqq8-8mkmr-worker-eastus1-8vzrw
    node/aro-cluster-lwqq8-8mkmr-worker-eastus1-vgmng

    In the list of nodes look for the final string to match, in this example shj9g)

  5. Next create a service using the oc expose command:

    oc expose deployment nodeselector-app -n nodeselector-ex
    Sample Output
    service/nodeselector-app exposed
  6. Expose the newly created service with a route:

    oc create route edge --service=nodeselector-app --insecure-policy=Redirect -n nodeselector-ex
    Sample Output
    route.route.openshift.io/nodeselector-app created
  7. Fetch the URL for the newly created route:

    oc get routes/nodeselector-app -n nodeselector-ex -o jsonpath='https://{.spec.host}{"\n"}'
    Sample Output
    https://nodeselector-app-nodeselector-ex.apps.nbybk9f3.eastus.aroapp.io

    Then visit the URL presented in a new tab in your web browser (using HTTPS).

    The application is exposed over the default ingress using a predetermined URL and trusted TLS certificate. This is done using the OpenShift Route resource which is an extension to the Kubernetes Ingress resource.

Congratulations!

You’ve successfully demonstrated the ability to label nodes and target those nodes using a nodeSelector.

Summary

Here you learned how to:

  • Set labels on new nodes in a MachineSet

  • Set labels on existing nodes in a MachineSet

  • Deploy an application on nodes with a certain label