taints
와 tolerations
는 pod를 어떤 node에 스케줄링한 것인지에 대한 개념이다. taints
는 node에 적용하고 tolerations
은 pod에 적용하는 field라고 생각하면된다.
------ ------ ------
|pod1| |pod2| |pod3|
------ ------ ------
--Node1-- --Node2-- --Node3--
| | | | | |
--------- --------- ---------
다음과 같이 pod 3개가 있고, node 3개가 있다고 하자. pod들은 각 node에 스케줄링될텐데 스케줄링 알고리즘에 따라 다음과 같이 할당이 가능하다.
--Node1-- --Node2-- --Node3--
|pod1 | | pod2 | | pod3 |
--------- --------- ---------
그런데 만약 Node1
은 특정 pod들만 스케줄링되도록 막고싶을 수가 있다. 이럴 때 taints
를 사용하는 것이다. Node1
은 taint=blue
를 적용시켜보도록 하자. 그렇게되면 pod들은 다음과 같이 스케줄링된다.
(taint=blue)
--Node1-- --Node2-- --Node3--
| | | pod1 | | pod3 |
| | | pod2 | | |
--------- --------- ---------
Node1
에는 pod들이 스케줄링되지 못하고 다른 곳으로 나가떨어져 스케줄링되는 것이다.
그럼 어떤 pod들이 taint된 Node1
에 할당될 수 있을까?? 그것이 바로 tolerations
이다. pod3
을 taint=blue
에 대해서 tolerations
하도록 설정하는 것이다.
(toleration)
------ ------ ------
|pod1| |pod2| |pod3|
------ ------ ------
(taint=blue)
--Node1-- --Node2-- --Node3--
| | | | | |
--------- --------- ---------
이제 다음과 같이 pod3
이 Node1
에 스케줄링될 수 있다.
(taint=blue)
----Node1---- --Node2-- --Node3--
|(toleration)| | pod1 | | pod2 |
| pod3 | | | | |
------------- --------- ---------
이처럼 taints
를 node에 부여하여 특정 pod만이 해당 node에 스케줄링될 수 있도록 할 수 있으며, toleration
을 부여하고 pod
를 taint가 적용된 node에 할당할 수 있도록 할 수 있다.
한 가지 오해하지말 것은 taints
와 tolerations
는 절대 security에 관한 목적이 아니다. 오직 특정 node에 특정 pod가 스케줄링되게 하기위함인 것이다.
그럼 어떻게 taints
를 적용하는가? taints
는 key-value
쌍으로 이루어져 있다. 다음과 같이 taint
를 적용시킬 수 있다.
kubectl taint nodes node-name key=value:taint-effect
만약 app=blue
라는 taint를 적용시키고 싶다면 key=value
를 app=blue
로 쓰면 된다. 그럼 taint-effect
는 무엇인가??
taint-effect
는 pod들이 만약 taint된 node에 대한 toleration이 없을 때 어떻게 동작시킬 것인지 동작을 나타낸다.
여기에는 3가지 taint-effect
가 있다.
1. NoSchedule
: 해당 pod가 taint node에 스케줄링되지 않는다.
2. PreferNoSchedule
: 최대한 taint node에 해당 pod를 배정하지 않으려고 한다. 즉, 우선순위가 낮아지는 것이다.
3. NoExecute
: 첫번째인 NoSchedule
과 같이 해당 pod가 taint node에 스케줄링되지 않으며, 만약 해당 node에 실행되고 있었지만 taint
에 대한 toleration
이 없는 pod들은 실행도 멈추어 evicted
가 된다.
즉, 이전에 해당 node에서 동작 중이던 pod
가 있었는데, node
에 taint
를 걸어버리고 NoExecute
로 설정해주면 해당 pod는 evicted가 된다.
------Node1-------
|pod1(toleration)|
|pod2 |
------------------
다음의 예는 taint가 적용되지 않은 Node1
에서 pod1
, pod2
가 스케줄링된 상황이다. 그런데 pod1
은 미래에서 Node1
에 부여될 taint
에 대한 toleration
을 가지고 있는 상태이다.
이제 Node1
에 taint
를 부여하되 taint-effect
를 NoExecute
로 적용했다고 하자.
(taint)
------Node1-------
|pod1(toleration)|
|pod2(evicted) |
------------------
pod1
은 Node1
의 taint
에 대한 toleration
이 있기 때문에 문제없이 계속 구동되지만, pod2
의 경우는 다르다. 만약 taint-effect
가 NoSchedule
였다면 pod2
도 계속 구동되었겠지만 NoExecute
상태이기 때문에 pod2
는 evicted
상태로 들어가게 되어 Node1
에서 빠져나온다.
그래서 최종 모습은 다음과 같이 된다.
---pod2---
|Pending|
----------
(taint)
------Node1-------
|pod1(toleration)|
------------------
위의 내용을 토대로 node1
에 app=blue
taint를 걸고 NoSchedule
로 taint-effect
를 설정하면 다음과 같다.
kubectl taint nodes node1 app=blue:NoSchedule
taints
는 재밌게도 기본적으로 적용되어 있는 node가 하나 있는데, 바로 master node
이다. master node
는 kubernetes control plane를 담당하는 pod들이 스케줄링되지만, worker node들이 관리하는 사용자 pod들도 스케줄링되어 실행될 수 있다.
그러나, 관행상 master node
에 일반 사용자 pod들이 배포되지 않도록 taints
가 걸려있다. 이는 mastert node
에 대한 시스템 부하를 관리하기 위함이다.
kubectl describe node kubemaster | grep Taint
Taints: node-role.kubernetes.io/master:NoScheduler
만약, 단일 node로 clustet를 구성했다면 master node에서 user pod가 구동되어야 하기 때문에 user pod에 toleration을 추가하든 master node의 taint를 삭제해야한다.
taints
가 무조건 key=value
형식으로 될 필요는 없다. 위의 master node
의 taint
처럼 key
만 있어도 된다. 위에서는 key
가 node-role.kubernetes.io/control-plane
인 것이다.
삭제할 때는 taint
의 마지막에 -
만 붙이면 된다.
kubectl taint node kubemaster node-role.kubernetes.io/master:NoScheduler-
untainted
되었다는 결과를 받을 수 있을 것이다.
toleration은 pod에 적용시키는 것인데, 기본적으로 yaml파일을 통해 pod에 toleration을 추가할 수 있다.
만약, node1
taint를 뚫는 toleration을 만들어야 한다면 다음과 같다.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: nginx-container
image: nginx
tolerations:
- key: "app"
value: "blue"
effect: "NoSchedule"
operator: "Equal"
이는 잘보면 taint
를 node
에 추가할 때의 요소들이 사용된 것을 알 수 있다.
kubectl taint nodes node1 app=blue:NoSchedule
key
는 app=blue
에서 app
이고 value
는 blue
, effector
는 NoSchedule
에 딱 일치하는 것이다. 참고로 operator
부분은 생략해도 된다.
여기서 재밌는 것은 toleration
을 가지고 있다고 해서 무조건 taint
를 가지고 있는 node에 스케줄링되는 것은 아니다. 즉, taints
와 tolerations
으로 스케줄링을 직접 설정하는 것이 아니라는 것이다.
가령 다음과 같은 경우가 있다.
(toleration)
------ ------ ------
|pod1| |pod2| |pod3|
------ ------ ------
(taint=blue)
--Node1-- --Node2-- --Node3--
| | | | | |
--------- --------- ---------
pod3
은 Node1
에 대한 toleration을 가지고 있지만, 다음과 같이 스케줄링될 수 있다.
(taint=blue)
--Node1--- --Node2-- --Node3--
| | | pod1 | | pod2 |
| | | pod3 | | |
----------- --------- ---------
pod3
이 toleration이 있다고 해서 반드시 taint가 있는 Node1
에 스케줄링되는 것이 아니라는 것이다.
만약 특정 pod를 특정 node에 스케줄링되도록 제한하고 싶다면, 추후에 나올 node affinity
를 사용하면 된다.
taints와 toleration은 특정 node에 taint를 걸어 toleration을 가진 pod만이 해당 node에 스케줄링되는 것을 허용한다. 단, 이는 반드시 특정 taint에 대한 toleration을 가진 pod가 해당 node로 스케줄링된다는 것을 의미하는 건 아니다.
반면에 node affinitiy는 특정 pod를 특정 node에 스케줄링되도록 할 수 있다. 단, 이외의 pod들이 해당 node에 스케줄링되는 것을 막을 수는 없다.
따라서, taints와 tolerations, node affinity를 적절히 섞어 사용하는 것이 좋다. 특정 pod를 특정 node에 배정하는 것은 node affinity를 사용하고, 특정 node에 다른 pod들이 배정되지 못하게 하기위해서는 taint를 사용하도록 하는 것이다.