From f925d502f4b87aae1cb94a92f30349d27b29a259 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Tue, 10 Oct 2023 16:34:06 +1100 Subject: [PATCH 1/4] affinity notes --- kubernetes/affinity/README.md | 63 ++++++++++++++++++++++++++ kubernetes/affinity/kind.yaml | 18 ++++++++ kubernetes/affinity/node-affinity.yaml | 37 +++++++++++++++ kubernetes/affinity/pod-affinity.yaml | 30 ++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 kubernetes/affinity/README.md create mode 100644 kubernetes/affinity/kind.yaml create mode 100644 kubernetes/affinity/node-affinity.yaml create mode 100644 kubernetes/affinity/pod-affinity.yaml diff --git a/kubernetes/affinity/README.md b/kubernetes/affinity/README.md new file mode 100644 index 0000000..55d9fdc --- /dev/null +++ b/kubernetes/affinity/README.md @@ -0,0 +1,63 @@ +# Kubernetes Concept: Affinity \ Anti-Affinity + +## Create a kubernetes cluster + +In this guide we we''ll need a Kubernetes cluster for testing. Let's create one using [kind](https://kind.sigs.k8s.io/)
+ +``` +cd kubernetes/affinity +kind create cluster --name demo --image kindest/node:v1.28.0 --config kind.yaml +``` + +Test the cluster: +``` +kubectl get nodes +NAME STATUS ROLES AGE VERSION +demo-control-plane Ready control-plane 59s v1.28.0 +demo-worker Ready 36s v1.28.0 +demo-worker2 Ready 35s v1.28.0 +demo-worker3 Ready 35s v1.28.0 + +``` + +## Node Affinity + +[Node Affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity) is similar to `nodeSelector` however you can define more complex expressions + +For example: +* Node selector is a hard and fast rule meaning a pod will not be scheduled if the selection is not satisfied +* For example, when using `os` selector as `linux` , a pod can only be scheduled if there is a node available where `os` label is `linux` + +Node Affinity allows an expression. + +``` +kubectl apply -f node-affinity.yaml +``` + +We can see our pods are prefering SSD and are always going to `us-east` + +``` +kubectl get pods -owide + +#introduce more pods +kubectl scale deploy app-disk --replicas 10 + +#observe all pods on demo-worker +``` + +If there is some trouble with our `ssd` disk, `kubectl taint nodes demo-worker type=ssd:NoSchedule`, we can see pods going to the non-ssd disk nodes in `us-east`
+ +This is because our pods prefer SSD, however there is no SSD available, so would still go to non-SSD nodes as long as there are nodes available in `us-east`
+ +If something goes wrong in our last `us-east` node: `kubectl taint nodes demo-worker3 type=ssd:NoSchedule` and we roll out more pods `kubectl scale deploy app-disk --replicas 20`, +notice that our new pods are now in `Pending` status because no nodes satisfy our node affinity rules
+ + +Fix our nodes. +``` +kubectl taint nodes demo-worker type=ssd:NoSchedule- +kubectl taint nodes demo-worker3 type=ssd:NoSchedule- +``` + + + diff --git a/kubernetes/affinity/kind.yaml b/kubernetes/affinity/kind.yaml new file mode 100644 index 0000000..d0b17f8 --- /dev/null +++ b/kubernetes/affinity/kind.yaml @@ -0,0 +1,18 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane +- role: worker + labels: + zone: us-east + type: ssd +- role: worker + labels: + zone: us-west + type: ssd +- role: worker + labels: + zone: us-east +- role: worker + labels: + zone: us-west diff --git a/kubernetes/affinity/node-affinity.yaml b/kubernetes/affinity/node-affinity.yaml new file mode 100644 index 0000000..6870f6a --- /dev/null +++ b/kubernetes/affinity/node-affinity.yaml @@ -0,0 +1,37 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: app-disk + labels: + app: app-disk +spec: + selector: + matchLabels: + app: app-disk + replicas: 1 + template: + metadata: + labels: + app: app-disk + spec: + containers: + - name: app-disk + image: nginx:latest + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: zone + operator: In + values: + - us-east + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: type + operator: In + values: + - ssd diff --git a/kubernetes/affinity/pod-affinity.yaml b/kubernetes/affinity/pod-affinity.yaml new file mode 100644 index 0000000..9a8abfc --- /dev/null +++ b/kubernetes/affinity/pod-affinity.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: app-disk2 + labels: + app: app-disk2 +spec: + selector: + matchLabels: + app: app-disk2 + replicas: 1 + template: + metadata: + labels: + app: app-disk2 + spec: + containers: + - name: app-disk2 + image: nginx:latest + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: zone + operator: In + values: + - us-east + topologyKey: zone \ No newline at end of file From f5a6234ef4cbc2896e09100c7f0662dcb2117374 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Wed, 11 Oct 2023 16:40:42 +1100 Subject: [PATCH 2/4] affinity updates --- kubernetes/affinity/README.md | 31 +++++++++++++++++++++++++- kubernetes/affinity/kind.yaml | 8 +++---- kubernetes/affinity/node-affinity.yaml | 9 ++++++++ kubernetes/affinity/pod-affinity.yaml | 16 ++++++------- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/kubernetes/affinity/README.md b/kubernetes/affinity/README.md index 55d9fdc..5a2b08e 100644 --- a/kubernetes/affinity/README.md +++ b/kubernetes/affinity/README.md @@ -22,7 +22,7 @@ demo-worker3 Ready 35s v1.28.0 ## Node Affinity -[Node Affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity) is similar to `nodeSelector` however you can define more complex expressions +[Node Affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity) is similar to `nodeSelector` however you can define more complex expressions. "Like my pods must run on SSD nodes or preffer SSD nodes" For example: * Node selector is a hard and fast rule meaning a pod will not be scheduled if the selection is not satisfied @@ -59,5 +59,34 @@ kubectl taint nodes demo-worker type=ssd:NoSchedule- kubectl taint nodes demo-worker3 type=ssd:NoSchedule- ``` +## Pod Affinity +``` +kubectl apply -f app-disk --replicas 3 +kubectl apply -f web-disk --replicas 3 +``` + +## Pod Anti-Affinity + +Let's say we observe our `app-disk` application disk usage is quite intense, and we would like to prevent `app-disk` pods from running together.
+This is where anti-affinity comes in: + +``` +podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - app-disk + topologyKey: "kubernetes.io/hostname" +``` + +After applying the above, we can roll it out: + +``` +kubectl apply -f node-affinity.yaml +``` + diff --git a/kubernetes/affinity/kind.yaml b/kubernetes/affinity/kind.yaml index d0b17f8..c1306d4 100644 --- a/kubernetes/affinity/kind.yaml +++ b/kubernetes/affinity/kind.yaml @@ -2,17 +2,17 @@ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane -- role: worker +- role: worker #demo-worker labels: zone: us-east type: ssd -- role: worker +- role: worker #demo-worker2 labels: zone: us-west type: ssd -- role: worker +- role: worker #demo-worker3 labels: zone: us-east -- role: worker +- role: worker #demo-worker4 labels: zone: us-west diff --git a/kubernetes/affinity/node-affinity.yaml b/kubernetes/affinity/node-affinity.yaml index 6870f6a..037ce9d 100644 --- a/kubernetes/affinity/node-affinity.yaml +++ b/kubernetes/affinity/node-affinity.yaml @@ -19,6 +19,15 @@ spec: - name: app-disk image: nginx:latest affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - app-disk + topologyKey: "kubernetes.io/hostname" nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: diff --git a/kubernetes/affinity/pod-affinity.yaml b/kubernetes/affinity/pod-affinity.yaml index 9a8abfc..1bccf3d 100644 --- a/kubernetes/affinity/pod-affinity.yaml +++ b/kubernetes/affinity/pod-affinity.yaml @@ -2,29 +2,29 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: app-disk2 + name: web-disk labels: - app: app-disk2 + app: web-disk spec: selector: matchLabels: - app: app-disk2 + app: web-disk replicas: 1 template: metadata: labels: - app: app-disk2 + app: web-disk spec: containers: - - name: app-disk2 + - name: web-disk image: nginx:latest affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - - key: zone + - key: app operator: In values: - - us-east - topologyKey: zone \ No newline at end of file + - app-disk + topologyKey: "kubernetes.io/hostname" \ No newline at end of file From 5b36f19e53d379087ebce05769b7152e91f9053a Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Sat, 14 Oct 2023 18:45:10 +1100 Subject: [PATCH 3/4] affinity updates --- kubernetes/affinity/README.md | 29 +++++++++++++++++++++++--- kubernetes/affinity/node-affinity.yaml | 9 -------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/kubernetes/affinity/README.md b/kubernetes/affinity/README.md index 5a2b08e..aa9de87 100644 --- a/kubernetes/affinity/README.md +++ b/kubernetes/affinity/README.md @@ -58,13 +58,27 @@ Fix our nodes. kubectl taint nodes demo-worker type=ssd:NoSchedule- kubectl taint nodes demo-worker3 type=ssd:NoSchedule- ``` +Scale back down to 0 +``` +kubectl scale deploy app-disk --replicas 0 +kubectl scale deploy app-disk --replicas 1 + +# pod should go back to demo-worker , node 1 +kubectl get pods -owide +``` ## Pod Affinity +Now [Pod Affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity) is an expression to allow us to state that pods should gravitate towards other pods ``` -kubectl apply -f app-disk --replicas 3 -kubectl apply -f web-disk --replicas 3 +kubectl apply -f pod-affinity.yaml + +# observe where pods get deployed +kubectl get pods -owide + +kubectl scale deploy app-disk --replicas 3 +kubectl scale deploy web-disk --replicas 3 ``` ## Pod Anti-Affinity @@ -84,9 +98,18 @@ podAntiAffinity: topologyKey: "kubernetes.io/hostname" ``` -After applying the above, we can roll it out: +After applying the above, we can roll it out and observe scheduling: ``` +kubectl scale deploy app-disk --replicas 0 +kubectl scale deploy web-disk --replicas 0 kubectl apply -f node-affinity.yaml +kubectl get pods -owide + +kubectl scale deploy app-disk --replicas 2 #notice pending pods when scaling to 3 +kubectl get pods -owide +kubectl scale deploy web-disk --replicas 2 +kubectl get pods -owide + ``` diff --git a/kubernetes/affinity/node-affinity.yaml b/kubernetes/affinity/node-affinity.yaml index 037ce9d..6870f6a 100644 --- a/kubernetes/affinity/node-affinity.yaml +++ b/kubernetes/affinity/node-affinity.yaml @@ -19,15 +19,6 @@ spec: - name: app-disk image: nginx:latest affinity: - podAntiAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - app-disk - topologyKey: "kubernetes.io/hostname" nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: From 8d7b27508b7517521a072b6c5b2977ec042b63c3 Mon Sep 17 00:00:00 2001 From: marcel-dempers Date: Mon, 16 Oct 2023 16:58:53 +1100 Subject: [PATCH 4/4] affinity updates --- kubernetes/affinity/node-affinity.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kubernetes/affinity/node-affinity.yaml b/kubernetes/affinity/node-affinity.yaml index 6870f6a..037ce9d 100644 --- a/kubernetes/affinity/node-affinity.yaml +++ b/kubernetes/affinity/node-affinity.yaml @@ -19,6 +19,15 @@ spec: - name: app-disk image: nginx:latest affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - app-disk + topologyKey: "kubernetes.io/hostname" nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: