- Published on
Assign workloads to specific nodes in kubernetes using labels and nodeselector
- Authors
- Name
- Peter Peerdeman
- @peterpeerdeman
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.