Affinity is a great feature in Kubernetes to assign pods to nodes based on labels. In my case, I have a hybrid Kubernetes cluster with half nodes are of X86 architecture and other half of ARM architecture, and I need to deploy the X86 only containers to the X86 nodes. Of course I can build multi-arch containers to get rid of this restriction too, but let’s see how Affinity works first.
All the nodes have labels of their architecture, and those labels can be printed out like this
# the key in jsonpath is to escape the dot "." and slash "/" in the key names, in this example, kubernetes.io/arch
k get node -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.kubernetes\.io\/arch}{"\n"}{end}'
kmaster arm
knode1 arm
knode2 arm
knode3 amd64
knode4 amd64
knode5 amd64
To deploy a Pod or Deployment, StatefulSet, etc, the Affinity should be put into the pod’s spec, eg.
# this is only a partial example of a deployment with affinity
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
The Deployment above will be scheduled onto a node running on X86 architecture.
Note: requiredDuringSchedulingIgnoredDuringExecution
is a hard requirement and if it’s not met the pod won’t be deployed. If it’s a soft requirement, preferredDuringSchedulingIgnoredDuringExecution
should be used instead.
🙂