Kubernetes - Scheduling and Node Selector
Lab assignment for understanding scheduling in Kubernetes
Kubernetes - Scheduling and Node Selector
Prerequisites
- Kubernetes
- kubectl
Assignment
- Create an nginx pod template that we’ll later target with a custom scheduler:
1
2
3
4
5
6
7
kubectl run nginx --image=nginx -o yaml --dry-run=client | tee nginx_scheduler.yaml
```sh
- Review the pod.spec option known as schedulerName:
```sh
kubectl explain pod.spec | more
- Update the
nginx_scheduler.yaml
file to include a schedulerName for a scheduler calledmy-scheduler
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cat <<EOF > nginx_scheduler.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
schedulerName: my-scheduler
containers:
- image: nginx
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
EOF
- Create the nginx pod with the defined scheduler:
1
kubectl apply -f nginx_scheduler.yaml
- Review the pods status - Pod will be stuck in
pending
state as there is no scheduler calledmy-scheduler
running:
1
kubectl get pods -o wide
- We’re going to make use of a convenient code example that mimicks the functionality of a scheduler as a bash script, firstly install git and jq if required -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
cat <<EOF> my-scheduler.sh
#!/bin/bash
echo "🚀 Starting the custom scheduler..."
while true; do
# Get names of all nodes
nodes=( $(kubectl get nodes -o jsonpath='{.items[*].metadata.name}') )
# Get unscheduled pods
unscheduled_pods=$(kubectl get pods --all-namespaces -o json | jq -r '.items[] | select(.spec.schedulerName=="my-scheduler" and .spec.nodeName==null) | .metadata.namespace + "/" + .metadata.name')
# Loop over unscheduled pods
for pod in $unscheduled_pods; do
# Select a random node
node=${nodes[$RANDOM % ${#nodes[@]}]}
# Split the pod into namespace and name
IFS='/' read -r -a pod_parts <<< "$pod"
namespace=${pod_parts[0]}
name=${pod_parts[1]}
# Create the binding YAML
binding=$(cat <<EOF
apiVersion: v1
kind: Binding
metadata:
name: $name
namespace: $namespace
target:
apiVersion: v1
kind: Node
name: $node
EOF
)
echo "🎯 Attempting to bind the pod $name in namespace $namespace to node $node"
# Bind the pod to the node using kubectl create, n.b. it is important that
# create is used vs apply as the Binding resource is a special resource that
# is typically not created or managed directly by users
echo "$binding" | kubectl create -f - > /dev/null
echo "🎉 Successfully bound the pod $name to node $node"
done
# Sleep before next iteration
sleep 1
done
EOF
- Run the script to schedule the pending pod (Use Ctrl+C to exit the script):
1
./my-scheduler.sh
- Review the pod status to confirm that the pods is scheduled on a node and is in running state:
1
kubectl get pods -o wide
- Clean Up the pod
1
kubectl delete pod/nginx --now
Schedule using nodeName
An alternative way of scheduling is by directly specifying the nodeName in which to schedule the pod.
Review the options for nodeName under pod.spec:
1
kubectl explain pod.spec | more
- Update the yaml so that it directly specifies a nodeName of worker-2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cat <<EOF > nginx_scheduler.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
nodeName: worker-2
containers:
- image: nginx
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
EOF
- Create the Pod and confirm the node on which it is scheduled:
1
kubectl apply -f nginx_scheduler.yaml
1
kubectl get pods -o wide
- Clean up the pod
1
kubectl delete pod/nginx --now
nodeSelector
- An alternative approach is the use of
nodeSelector
which makes use of known labels, to select a node. - Describe the node to check the labels assigned to the node:
1
kubectl describe node/worker-1 | more
- Use the label
kubernetes.io/hostname=worker-1
to target a node, update the yaml as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
cat <<EOF > nginx_scheduler.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
nodeSelector:
kubernetes.io/hostname: worker-1
containers:
- image: nginx
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
EOF
```sh
- Create the pod and view the node on which the pod is scheduled:
```sh
kubectl apply -f nginx_scheduler.yaml
1
kubectl get pods -o wide
- Cleanup
1
kubectl delete pod/nginx --now; rm -rf simple-kubernetes-scheduler-example; rm -rf nginx_scheduler.yaml
This post is licensed under CC BY 4.0 by the author.