Commit 96fbadc2 authored by Berk Yavuz's avatar Berk Yavuz
Browse files

Affinity and anti-affinity

parent 06576214
Showing with 368 additions and 1 deletion
+368 -1
# scheduling
# Scheduling
Affinity/Anti-Affinity Rules, Taints and Tolerations
## Index
* [Affinity/Anti-Affinity Rules](#troubleshooting-and-debugging)
* [Exercise: Node Selector](#exercise-debugging-pods)
* [Exercise: Node Affinity](#exercise-events)
* [Exercise: Node Anti-Affinity](#exercise-debugging-services)
* [Taints and Tolerations](#monitoring)
* [Exercise: Taints](#exercise-kubernetes-dashboard)
* [Exercise: Tolerations](#exercise-weave-scope)
---
## Affinity/Anti-Affinity Rules
It is one way to set rules on which nodes are selected by the scheduler. This feature is a generalization of the nodeSelector feature. The rules are defined using the familiar concepts of custom labels on nodes and selectors specified in pods, and they can be either required or preferred, depending on how strictly you want the scheduler to enforce them.
### Exercise: Node Selector
1. First show your node labels.
```
$ kubectl get node --output=jsonpath={.items..metadata.labels}
```
> Output may different for each environments or cluster setup. This is how it look like in minikube
__output__
```
map[beta.kubernetes.io/arch:amd64 beta.kubernetes.io/os:linux kubernetes.io/arch:amd64 kubernetes.io/hostname:minikube kubernetes.io/os:linux node-role.kubernetes.io/master:]
```
2. Create a pod with `nodeSelector` or use the `yaml` below.
```yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
```
__Command__
```
$ kubectl apply -f yaml/node-selector.yaml
```
3. List the pods
```
$ kubectl get pods
```
__Output__
```
NAME READY STATUS RESTARTS AGE
nginx 0/1 Pending 0 59s
```
4. Pod is in `Pending` state. Describe the pod for more information about the status.
```
$ kubectl describe pod nginx
```
__Output__
```
Name: nginx
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: <none>
Labels: env=test
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"env":"test"},"name":"nginx","namespace":"default"},"spec":{"contai...
Status: Pending
IP:
Containers:
nginx:
Image: nginx:latest
Port: <none>
Host Port: <none>
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-6zm5t (ro)
Conditions:
Type Status
PodScheduled False
Volumes:
default-token-6zm5t:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-6zm5t
Optional: false
QoS Class: BestEffort
Node-Selectors: disktype=ssd
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 64s (x3 over 2m26s) default-scheduler 0/1 nodes are available: 1 node(s) didn't match node selector.
```
5. When you look the events, it cant be scheduled to the node because the node's labels does not match with `nodeSelector`. Label the node `disktype=ssd` and describe it again.
>Your nodename can be different.
```
$ kubectl label node minikube disktype=ssd
```
6. List the pods.
```
$ kubectl get pods
```
__Expected output__
```
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 6m13s
```
7. Clean up
```
$ kubectl delete pod nginx
```
---
### Exercise: Node Affinity
Node affinity is a set of rules used by the scheduler to determine where a pod can be placed.
1. Create a pod with NodeAffinity for doing previous exercise with node affinity. Use the yaml below or `yaml/node-affinity-1.yaml`
```yaml
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "disktype"
operator: In
values: ["ssd"]
containers:
- name: with-node-affinity
image: nginx:latest
```
__Command__
```
$ kubectl apply -f yaml/node-affinity-1.yaml
```
> The operator represents the relationship between the label on the node and the set of values in the `matchExpression` parameters in the pod specification.
This value can be `In`, `NotIn`, `Exists`, or `DoesNotExist`, `Lt`, or `Gt`.
2. The label will be found by the NodeAffinity because we labeled the our node in the previous exercise. List the pods.
```
$ kubectl get pods
```
__Expected Output__
```
NAME READY STATUS RESTARTS AGE
with-node-affinity 1/1 Running 0 4m40s
```
3. Lets delete the pod.
```
$ kubectl delete pod with-node-affinity
```
4. Create a pod with the yaml below or use `yaml/node-affinity-2.yaml`
```yaml
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: "disktype"
operator: In
values:
- hdd
containers:
- name: with-node-affinity
image: nginx:latest
```
> As you realized the node affnity has `preferredDuringSchedulingIgnoredDuringExecution` field at this time. Preferred Rules mean that if nodes match the rules, they will be chosen first, and only if no preferred nodes are available will non-preferred nodes be chosen.
5. The other difference is the affinity looking for label `disktype=hdd` but as you remember we label the node with `disktype=ssd`. However, this affinity has a type `prefered` so the pod will e scheduled. Apply the yaml.
```
$ kubectl apply -f yaml/node-affinity-2.yaml
```
6. List the pods
```
$ kubectl get pods
```
__Expected output__
```
NAME READY STATUS RESTARTS AGE
with-node-affinity-prefered 1/1 Running 0 28s
```
> The behaviour of the affinity types;
| AFFINITY SELECTOR | REQUIREMENTS MET | REQUIREMENTS NOT MET | REQUIREMENTS LOST |
|-------------------------------------------------|------------------|----------------------|-------------------|
| requiredDuringSchedulingIgnoredDuringExecution | RUNS | FAILS | KEEPS RUNNING |
| preferredDuringSchedulingIgnoredDuringExecution | RUNS | RUNS | KEEPS RUNNING |
> .
---
### Exercise: Node Anti-Affinity
You can use `NotIn` and `DoesNotExist` to achieve node anti-affinity behavior.
1. Create yaml file from the yalm below or use `yaml/node-anti-affinity.yaml`
```yaml
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "disktype"
operator: NotIn
values: ["hdd"]
containers:
- name: with-node-affinity
image: nginx:latest
```
__Command__
```
$ kubectl apply -f yaml/node-anti-affinity.yaml
```
> This pod is looking for a node that does not have `disktype` key equals to `hdd` value. Our node is still labeled with `disktype=ssd` so there will not be a problem.
2. List the pods
```
$ kubectl get pods
```
__Expected Output__
```
NAME READY STATUS RESTARTS AGE
anti-affinity 1/1 Running 0 7m1s
```
---
## Taints and Tolerations
You apply taints to a node through the node specification (NodeSpec) and apply tolerations to a pod through the pod specification (PodSpec). A taint on a node instructs the node to repel all pods that do not tolerate the taint.
### Exercise: Taints
### Exercise: Tolerations
\ No newline at end of file
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "disktype"
operator: In
values: ["ssd"]
containers:
- name: with-node-affinity
image: nginx:latest
\ No newline at end of file
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity-prefered
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: "disktype"
operator: In
values:
- hdd
containers:
- name: with-node-affinity
image: nginx:latest
apiVersion: v1
kind: Pod
metadata:
name: anti-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "disktype"
operator: NotIn
values: ["hdd"]
containers:
- name: with-node-affinity
image: nginx:latest
\ No newline at end of file
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment