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:

  1. 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.

  2. 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:

  1. nodeSelectorTerms: A list of node selector terms, each containing a list of match expressions.

  2. 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 include In, NotIn, Exists, and DoesNotExist.

    • values: The list of values associated with the key (only used with In and NotIn 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

Video

Documentation