---
tags: k8s-fundamentals, CKA
---
# Scheduling Workloads
This page contains some experiments on K8S workload scheduling.
* NodeAffinity
* PodAffinity
* PodAntiAffinity
* Pod topologySpreadConstraints
## Experiments
### Setup kind cluster
```
// kind.yaml
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
```
```
kind create cluster --config ./kind.yaml --image kindest/node:v1.18.0
```
### Label a node and Unlabel a node
```
kubectl label node kind-worker node-role.kubernetes.io/worker=
~/tech-explore/pod-scheduling kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready master 109m v1.18.0
kind-worker Ready worker 108m v1.18.0
kind-worker2 Ready <none> 108m v1.18.0
kind-worker3 Ready <none> 108m v1.18.0
kubectl label node kind-worker node-role.kubernetes.io/worker=
~/tech-explore/pod-scheduling kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready master 109m v1.18.0
kind-worker Ready <none> 108m v1.18.0
kind-worker2 Ready <none> 108m v1.18.0
kind-worker3 Ready <none> 108m v1.18.0
```
### Create a pod on a random node
```
kubectl run nginx --image=nginx --restart=Never -o yaml --dry-run=client > nginx-pod.yaml
~/tech-explore/pod-scheduling kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 11s 10.244.3.2 kind-worker3 <none> <none>
```
### Create a pod on a particular node with nodeName
```
// For testing purpose, I am going to shutdown the controller manager, sheduler in kind and, the pod still can be created
docker exec -it kind-control-plane bash
root@kind-control-plane:/etc/kubernetes/manifests# crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
a7f4b8a0562e3 db10073a6f829 2 hours ago Running local-path-provisioner 0 65923e0030098
d77d86c094e02 67da37a9a360e 2 hours ago Running coredns 0 c95ed97ccbcaa
06383b940ee74 67da37a9a360e 2 hours ago Running coredns 0 a2b961215cdf7
e00a7f3c4405d 8aff47b2a8d8d 2 hours ago Running kube-proxy 0 84136aa6c7724
3862a3d86abae 2186a1a396deb 2 hours ago Running kindnet-cni 0 8c37f628331c6
0c598f608ea02 303ce5db0e90d 2 hours ago Running etcd 0 80871c79ca7a9
390dac1bf7f26 06898432911e4 2 hours ago Running kube-apiserver 0 ea71ce42bd71b
f2b9bce63b40d 0086f582d6f07 2 hours ago Running kube-controller-manager 0 e79df33546948
4a73613bd6f64 e7ef4082901cb 2 hours ago Running kube-scheduler 0 0fb43feda0941
cd /etc/kubernetes/manifests
root@kind-control-plane:/etc/kubernetes/manifests# mv kube-controller-manager.yaml ../
root@kind-control-plane:/etc/kubernetes/manifests# mv kube-scheduler.yaml ../
root@kind-control-plane:/etc/kubernetes/manifests# crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
a7f4b8a0562e3 db10073a6f829 2 hours ago Running local-path-provisioner 0 65923e0030098
d77d86c094e02 67da37a9a360e 2 hours ago Running coredns 0 c95ed97ccbcaa
06383b940ee74 67da37a9a360e 2 hours ago Running coredns 0 a2b961215cdf7
e00a7f3c4405d 8aff47b2a8d8d 2 hours ago Running kube-proxy 0 84136aa6c7724
3862a3d86abae 2186a1a396deb 2 hours ago Running kindnet-cni 0 8c37f628331c6
0c598f608ea02 303ce5db0e90d 2 hours ago Running etcd 0 80871c79ca7a9
390dac1bf7f26 06898432911e4 2 hours ago Running kube-apiserver 0 ea71ce42bd71b
cat > nginx-pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx
name: nginx
spec:
nodeName: kind-worker
containers:
- image: nginx
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
EOF
kubectl apply -f nginx-pod.yaml
~/tech-explore/pod-scheduling kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 6s 10.244.1.3 kind-worker <none> <none>
```
### Create a deployment with nodeName
In order to make it work, you might want to enable the kube-controller-manager and kube-scheduler in kind
```
cat > nginx-deploy.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
nodeName: kind-worker3
containers:
- image: nginx
name: nginx
resources: {}
status: {}
EOF
kubectl apply -f nginx-deploy.yaml
```
### Create a deployment with nodeSelector
```
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
nodeSelector:
pickme: "" // You have to have one of the node labeled with pickme first
containers:
- image: nginx
name: nginx
resources: {}
status: {}
kubectl apply -f nginx-deploy.yaml
```
### Pod Topology Spread Constraints
* Label nodes: two nodes are labeled with zone=A, one node is labeled with zone=B
```
~/tech-explore/pod-scheduling kubectl get nodes -o wide --show-labels
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME LABELS
kind-control-plane Ready master 5h27m v1.18.0 172.17.0.5 <none> Ubuntu 19.10 4.19.76-linuxkit containerd://1.3.3-14-g449e9269 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kind-control-plane,kubernetes.io/os=linux,node-role.kubernetes.io/master=
kind-worker Ready <none> 5h26m v1.18.0 172.17.0.4 <none> Ubuntu 19.10 4.19.76-linuxkit containerd://1.3.3-14-g449e9269 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kind-worker,kubernetes.io/os=linux,zone=A
kind-worker2 Ready <none> 5h26m v1.18.0 172.17.0.2 <none> Ubuntu 19.10 4.19.76-linuxkit containerd://1.3.3-14-g449e9269 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kind-worker2,kubernetes.io/os=linux,zone=A
kind-worker3 Ready <none> 5h26m v1.18.0 172.17.0.3 <none> Ubuntu 19.10 4.19.76-linuxkit containerd://1.3.3-14-g449e9269 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kind-worker3,kubernetes.io/os=linux,zone=B
```
* Create a deployment
```
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
labels:
app: nginx
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: nginx
containers:
- image: nginx
name: nginx
resources: {}
status: {}
kubectl apply -f <filename.yaml>
```
### Scale replicas to 3
```
kubectl scale deploy nginx --replicas=3
~/tech-explore/pod-scheduling kubectl get pods -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx-7b8dd6c565-6tc6g 1/1 Running 0 3m34s 10.244.3.6 kind-worker3 <none> <none> app=nginx,pod-template-hash=7b8dd6c565
nginx-7b8dd6c565-8z4rc 1/1 Running 0 4m5s 10.244.2.6 kind-worker2 <none> <none> app=nginx,pod-template-hash=7b8dd6c565
nginx-7b8dd6c565-njkbs 1/1 Running 0 2m42s 10.244.1.6 kind-worker <none> <none> app=nginx,pod-template-hash=7b8dd6c565
```
### Scale replicas to 4
```
kubectl scale deploy nginx --replicas=4
~/tech-explore/pod-scheduling kubectl get pods -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx-7b8dd6c565-6tc6g 1/1 Running 0 4m32s 10.244.3.6 kind-worker3 <none> <none> app=nginx,pod-template-hash=7b8dd6c565
nginx-7b8dd6c565-8z4rc 1/1 Running 0 5m3s 10.244.2.6 kind-worker2 <none> <none> app=nginx,pod-template-hash=7b8dd6c565
nginx-7b8dd6c565-kmmb5 1/1 Running 0 16s 10.244.3.7 kind-worker3 <none> <none> app=nginx,pod-template-hash=7b8dd6c565
nginx-7b8dd6c565-njkbs 1/1 Running 0 3m40s 10.244.1.6 kind-worker <none> <none> app=nginx,pod-template-hash=7b8dd6c565
```
## References
* https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
* https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
* https://www.youtube.com/watch?v=o_gT_LfFn4s