nodeSelectors are the works the opposite way as taints. Instead of repelling the Pods, nodeselectors attracts the Pods to specific nodes. A nodeSelector is a list of labels included in a Pod’s spec.
As an example, let’s say we set a label onto one node. Pods with the matching labels will then be assigned to the node that has the same label.
Another way of attracting Pods to specific ndoes is through the use of Node Affinity. Instead of allowing only the exact matches of labels, Node Affinity can use other set of criterias known as Supported Operators:
There are two types of node affinity:
requiredDuringSchedulingIgnoredDuringExecution: The scheduler can’t schedule the Pod unless the rule is met. This functions like nodeSelector, but with a more expressive syntax.
preferredDuringSchedulingIgnoredDuringExecution: The scheduler tries to find a node that meets the rule. If a matching node is not available, the scheduler still schedules the Pod on any available node.
requiredDuringSchedulingIgnoredDuringExecution: This is a new option introduced which will evict any pods that are running on nodes that do not meet the affinity rules.
“DuringScheduling” means the Pod doesn’t exist and is created for the first time, while “DuringExecution” is a state where the Pod is already running and a change is introduced in the environment which affects the node affinity.
Type | DuringScheduling | DuringExecution |
---|---|---|
Type 1 | Required | Ignored |
Type 2 | Preferred | Ignored |
Type 3 | Required | Required |
“IgnoredDuringExecution” means the pods will continue to run and any changes in node affinity will not impact them once the Pods are already scheduled.
We’ll use the manifest below to create a Kubernetes cluster in Amazon EKS. You can also use this to create the clsuter in your preferred environment.
## eksops.yml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
version: "1.23"
name: eksops
region: ap-southeast-1
nodeGroups:
- name: ng-dover
instanceType: t3.large
minSize: 0
maxSize: 5
desiredCapacity: 3
ssh:
publicKeyName: "k8s-kp"
Create the cluster and check the nodes.
kubectl apply -f eksops.yml
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-192-168-11-247.ap-southeast-1.compute.internal Ready <none> 8h v1.23.13-eks-fb459a0
ip-192-168-56-187.ap-southeast-1.compute.internal Ready <none> 8h v1.23.13-eks-fb459a0
ip-192-168-81-3.ap-southeast-1.compute.internal Ready <none> 8h v1.23.13-eks-fb459a0
Add the “disktype=ssd” label to the first node and verify.
kubectl label nodes ip-192-168-11-247.ap-southeast-1.compute.internal disktype=ssd
$ kubectl get nodes --show-labels | grep ssd
ip-192-168-11-247.ap-southeast-1.compute.internal Ready <none> 8h v1.23.13-eks-fb459a0 ....disktype=ssd...
Next, we’ll use the manifest below to launch a Pod that has a requiredDuringSchedulingIgnoredDuringExecution node affinity,disktype: ssd. This means that the pod will get scheduled only on a node that has a disktype=ssd label.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Apply the manifest.
kubectl apply -f https://k8s.io/examples/pods/pod-nginx-required-affinity.yaml
The Pod should now be launched on the node with the matching label which in this case is the “192-168-11-247” node.
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 3s 192.168.8.176 ip-192-168-11-247.ap-southeast-1.compute.internal <none> <none>
To delete the Pod:
kubectl delete -f https://k8s.io/examples/pods/pod-nginx-required-affinity.yaml
In this second example, we’ll use the manifest below to launch a Pod that has preferredDuringSchedulingIgnoredDuringExecution node affinity,disktype: ssd. This means that the pod will prefer a node that has a disktype=ssd label.
This works almost the same way as required affinity, but the key difference is that we can specify a weight to each instance beforehand which is also considered by the scheduler when making scheduling decision for the Pod.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Apply.
kubectl apply -f https://k8s.io/examples/pods/pod-nginx-preferred-affinity.yaml