Published on

Assign workloads to specific nodes in kubernetes using labels and nodeselector

Authors

After adding a virtualised intel node to imy ARM k8s cluster I quickly found that I wanted some more control over what pods would be deployed on which nodes.

This is where the nodeselector keyword comes in play. With nodeselector we can specify what labels we want to be present at the node before it gets chosen to perform the specified workload.

We can view the labels our nodes currently have with kubectl get nodes --show-labels:

...     VERSION        LABELS
...   v1.28.6+k3s2   beta.kubernetes.io/arch=arm64,beta.kubernetes.io/instance-type=k3s,beta.kubernetes.io/os=linux,k3s.io/hostname=raspcontrol,k3s.io/internal-ip=192.168.117.11,kubernetes.io/arch=arm64,kubernetes.io/hostname=raspcontrol,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=true,node-role.kubernetes.io/master=true,node.kubernetes.io/instance-type=k3s
...   v1.28.6+k3s2   beta.kubernetes.io/arch=arm64,beta.kubernetes.io/instance-type=k3s,beta.kubernetes.io/os=linux,kubernetes.io/arch=arm64,kubernetes.io/hostname=raspalpha,kubernetes.io/os=linux,node-role.kubernetes.io/worker=worker,node.kubernetes.io/instance-type=k3s,storage=true
...   v1.28.6+k3s2   beta.kubernetes.io/arch=arm64,beta.kubernetes.io/instance-type=k3s,beta.kubernetes.io/os=linux,kubernetes.io/arch=arm64,kubernetes.io/hostname=raspbravo,kubernetes.io/os=linux,node-role.kubernetes.io/worker=worker,node.kubernetes.io/instance-type=k3s,storage=true
...   v1.29.6+k3s2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=k3s,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=nucalpha,kubernetes.io/os=linux,node-role.kubernetes.io/worker=worker,node.kubernetes.io/instance-type=k3s

As you can see, k3s already supplied the nodes with a bunch of default tags on installation, including the architecture beta.kubernetes.io/arch=arm64 and the os kubernetes.io/os=linux, but also the hostname kubernetes.io/hostname=raspbravo, which would enable you to pin a workflow to a specific machine. We can use the nodeselector in any kubernetes file holds a spec, in this example ensuring this deployment to only run on arm64 architecture:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: recordfairs-deployment
  namespace: recordfairs
spec:
  replicas: 1
  template:
    spec:
      nodeSelector:
        beta.kubernetes.io/arch: arm64
      containers:
        - name: recordfairs
          image: peterpeerdeman/recordfairs:1.0.6

Using nodeselector creates a very binary selection process for kubernetes: either the node has or has not got a label. You can also influence the selection of nodes a little more subtly by using Affinity and Anti-affinity. This allows you to create rules that are 'soft' or more like a 'preference', but will still run the workload on a specific node if the preference could not be met. If you are into that, definitely check out the docs on assigning pod nodes.

Support Hashbang, keep in touch 💌