Skip to main content

1.5 Scheduling in Kubernetes

What is Scheduling in Kubernetes?

Scheduling in Kubernetes refers to the process of assigning Pods to Nodes in the cluster. The Kubernetes scheduler is responsible for placing Pods on Nodes based on the available resources and constraints specified by the user. Scheduling is critical for optimizing resource utilization and ensuring that workloads are efficiently distributed across the cluster.

How the Kubernetes Scheduler Works

When a new Pod is created, the Kubernetes scheduler decides which Node in the cluster should run that Pod. This decision is based on various factors such as resource requirements, policies, and Node health. The scheduler's goal is to ensure that Pods are placed on Nodes that have sufficient resources and meet the defined constraints.

Scheduler Workflow:

  1. Pod Creation: A new Pod is created without being assigned to a specific Node.
  2. Node Filtering: The scheduler filters Nodes to find those that meet the Pod's resource requirements and other constraints.
  3. Node Scoring: The remaining Nodes are scored based on criteria like resource utilization and affinity rules.
  4. Pod Binding: The scheduler binds the Pod to the best-fit Node.

Key Scheduling Concepts

1. Resource Requests and Limits

Each container in a Pod can specify the amount of CPU and memory it requests and the maximum amount it can use. The scheduler uses these requests to determine where to place the Pod.

  • Requests: The minimum amount of CPU and memory guaranteed to the container.

  • Limits: The maximum amount of CPU and memory a container can use.

    Example of resource requests and limits:

    apiVersion: v1
    kind: Pod
    metadata:
    name: my-pod
    spec:
    containers:
    - name: nginx
    image: nginx
    resources:
    requests:
    memory: "64Mi"
    cpu: "250m"
    limits:
    memory: "128Mi"
    cpu: "500m"

2. Node Affinity and Anti-Affinity

Node affinity allows you to specify constraints on where Pods are scheduled based on Node labels. Anti-affinity ensures that Pods are not placed on certain Nodes.

Example of Node affinity:

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "disktype"
operator: In
values:
- ssd

In this example, the Pod will only be scheduled on Nodes labeled with disktype=ssd.

3. Pod Affinity and Anti-Affinity

Pod affinity and anti-affinity control the placement of Pods relative to other Pods. This is useful for ensuring that Pods are placed together or distributed across different Nodes for availability.

Example of Pod anti-affinity:

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: "kubernetes.io/hostname"

In this example, the Pod will not be scheduled on the same Node as other Pods with the label app=nginx.

4. Taints and Tolerations

Taints allow Nodes to repel certain Pods, while tolerations allow Pods to tolerate specific taints. This mechanism is useful for controlling which Pods can run on specific Nodes.

Example of applying a taint to a Node:

kubectl taint nodes node1 key=value:NoSchedule

In this example, no Pods will be scheduled on node1 unless they have a matching toleration.

Example of Pod toleration:

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"

This Pod will be allowed to run on Nodes that have the key=value:NoSchedule taint.

Advanced Scheduling Features

1. Priority and Preemption

Pods can be assigned priorities, and higher-priority Pods can preempt (evict) lower-priority Pods if necessary. This ensures that critical workloads get the resources they need.

Example of assigning priority to a Pod:

apiVersion: v1
kind: Pod
metadata:
name: high-priority-pod
spec:
priorityClassName: high-priority

2. DaemonSets

A DaemonSet ensures that a copy of a Pod is running on every Node (or a subset of Nodes). This is useful for system-level services like logging or monitoring.

Example of a DaemonSet:

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: my-daemonset
spec:
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-image

3. Job and CronJob Scheduling

Jobs and CronJobs allow you to run Pods that perform specific tasks. Jobs run once until completion, while CronJobs run on a schedule.

Example of a CronJob:

apiVersion: batch/v1
kind: CronJob
metadata:
name: my-cronjob
spec:
schedule: "*/5 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: my-container
image: my-image
restartPolicy: OnFailure

In this example, the CronJob will run every 5 minutes.

Conclusion

Scheduling in Kubernetes is a key component that ensures efficient placement of workloads across the cluster. By leveraging resource requests, limits, affinity rules, and other advanced scheduling features, you can optimize the performance and reliability of your applications in Kubernetes. Understanding how the scheduler works is essential for ensuring that your workloads are placed on the most suitable Nodes while maintaining high availability and efficient resource usage.

In the next section, we will explore more advanced features of Kubernetes orchestration and management.