Kubernetes Day 15 : Understanding Node Affinity in Kubernetes
Node affinity is a feature in Kubernetes that allows you to influence the scheduling of pods on nodes based on specific rules. By using node affinity, you can ensure that certain pods run on particular nodes, enhancing your control over the placement of workloads in your Kubernetes cluster. This blog will delve into the basics of node affinity, its types, rules, and how to configure it using a YAML file.
What is Node Affinity?
Node affinity is a set of rules used to constrain which nodes your pod is eligible to be scheduled on, based on node labels. It's a more flexible way to define scheduling constraints compared to nodeSelector, providing greater control over pod placement.
Types of Node Affinity
There are two types of node affinity:
RequiredDuringSchedulingIgnoredDuringExecution: This type of node affinity is a hard requirement. The pod will only be scheduled on nodes that meet the specified affinity rules. If no such node is available, the pod will not be scheduled.
PreferredDuringSchedulingIgnoredDuringExecution: This type of node affinity is a soft preference. The pod will prefer to be scheduled on nodes that meet the specified affinity rules, but it can still be scheduled on nodes that do not meet these rules if no preferred nodes are available.
Node Affinity Rules
Node affinity rules are defined using nodeAffinity
within the pod specification. These rules use node labels to determine where the pod should be scheduled. There are three main components to these rules:
nodeSelectorTerms: A list of node selector terms, each containing a list of match expressions.
matchExpressions: These are the actual conditions that need to be met. Each expression consists of three parts:
key
: The label key that the rule applies to.operator
: The relationship between the key and values. Common operators includeIn
,NotIn
,Exists
, andDoesNotExist
.values
: The list of values associated with the key (only used withIn
andNotIn
operators).
Example of Node Affinity in YAML
Below is an example of a pod configuration with node affinity defined in the YAML file:
apiVersion: v1
kind: Pod
metadata:
name: affinity-example
spec:
containers:
- name: nginx
image: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
Task
Step 1: Create the Nginx Pod with Node Affinity
First, create a YAML file (nginx-pod.yaml
) for the nginx pod with the specified node affinity.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
Apply the YAML file to create the pod:
kubectl apply -f nginx-pod.yaml
Step 2: Check the Status of the Nginx Pod
Check the status of the nginx pod to see why it is not scheduled:
kubectl get pod nginx-pod -o wide
kubectl describe pod nginx-pod
The describe
command will show events indicating why the pod is not scheduled, likely because no nodes currently have the disktype=ssd
label.
Step 3: Add Label to worker01 Node
Add the disktype=ssd
label to your worker01
node:
kubectl label nodes worker01 disktype=ssd
Step 4: Check the Status of the Nginx Pod Again
After adding the label, check the status of the nginx pod again to ensure it is scheduled:
kubectl get pod nginx-pod -o wide
You should see that the pod is now scheduled on worker01
.
Step 5: Create the Redis Pod with Node Affinity
Now, create a YAML file (redis-pod.yaml
) for the redis pod with the specified node affinity:
apiVersion: v1
kind: Pod
metadata:
name: redis-pod
spec:
containers:
- name: redis
image: redis
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: Exists
Apply the YAML file to create the pod:
kubectl apply -f redis-pod.yaml
Step 6: Check the Status of the Redis Pod
Check the status of the redis pod to see why it is not scheduled:
kubectl get pod redis-pod -o wide
kubectl describe pod redis-pod
The describe
command will show events indicating why the pod is not scheduled, likely because no nodes currently have the disktype
label.
Step 7: Add Label to worker02 Node
Add the disktype
label (without any value) to your worker02
node:
kubectl label nodes worker02 disktype-
Step 8: Check the Status of the Redis Pod Again
After adding the label, check the status of the redis pod again to ensure it is scheduled:
kubectl get pod redis-pod -o wide
You should see that the pod is now scheduled on worker02
.
Conclusion
Node affinity in Kubernetes provides powerful scheduling capabilities, allowing you to control where your pods are placed based on node labels. By understanding and configuring node affinity rules, you can ensure optimal workload distribution and resource utilization in your Kubernetes cluster. The example YAML configuration above serves as a starting point for defining node affinity in your own Kubernetes deployments.
Reference