쿠버네티스 노드에 어떤 파드도 배포하지 않는 방법
in Devops on Kubernetes
How to prevent?
이번 시간에는 쿠버네티스 노드에 그 어떤 파드도 배포하지 않는 방법에 대해서 알아보겠습니다.
이를 위해서는 Node-Affinity와 Taints와 Toleration에 대해서 알아야합니다.
Taints는 Node-Affinity와 반대되는 옵션입니다.
Node-Affinity가 Pod가 특정 Node에 배포될 수 있게 하는 옵션이라면,
Taints는 Node가 특정 Pod를 쫓아내는 옵션입니다.
Node-Affinity


Node-Affinity에서 주목할 옵션은 아래입니다.
requiredDuringSchedulingIgnoredDuringExecution 인데요.
막상 보면 길어보이지만 잘라서 보면 이해하기 쉽습니다.
Node-Affinity의 옵션은 크게 가장 앞 부분인 required와 preferred 조건으로 나누어집니다.
required는 반드시 이 파드가 해당 노드에 배포가 되어야한다는 점이고 preferred는 가급적이면~ 이라는 옵션입니다.
그리고 꼬리에 해당하는 IgnoredDuringExecution의 경우 런타임에 노드의 Label이 바뀌더라도 무시할 것인지, 즉시 eviction할 것인지에 대한 옵션입니다.
반대 옵션으로는 RequiredDuringExecution가 있습니다.
이를 종합해보면,
requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecutionrequiredDuringSchedulingRequiredDuringExecutionpreferredDuringSchedulingRequiredDuringExecution
총 네 개의 조합이 가능해집니다.
Node의 입장에서
Node-Affinity는 특정 파드가 특정 노드로 배포할 것을 설정하는 옵션입니다.
그러나 A Pod가 Node01로의 배포를 반드시 보장해주지만,
Node01에서 B,C 파드가 배포될 것을 보장해주지는 않습니다.

Node-Affinity VS Node-Selector
우리는 이전에, Node-Selector를 이용해서도 Node-Affinity와 비슷한 기능을 구현할 수 있는 것을 알고 있습니다.
---
apiVersion: v1
kind: Pod
metadata:
name: A
spec:
containers:
- name: with-node-affinity
image: k8s.gcr.io/pause:2.0
nodeSelector:
nodeName: node01
얼핏 봐서는 이 옵션이 Node-Affinity 보다 더 명확하고 직관적이라는 생각도 듭니다.
하지만 k8s에서는 이 Node-Selector보다 Node-Affinity를 권장하고 있으며, 추후에 Node-Selector를 Deprecate하고 Node-Affinity만을 사용할 것이라고 밝혔습니다.
그 이유는 Node-Affinity에서는 조금 더 다양한 표현식으로 선택이 가능하며, 제약조건의 주체가 노드에 있는 것이 아닌 파드에 부여함으로써 서로 같이 배치될 수 있는 파드와 아닌 파드를 정의하는게 가능해지기 때문인데요.
Node-Selector에서는 반드시 해당 노드에 배포가 된다는 식의 설정이지만, Node-Affinity의 경우 가급적이면 그렇게 해줘라는 옵션도 설정이 가능하므로 조금 더 유연하게 사용할 수 있다는 장점도 있습니다.
Taints와 Toleration
그러면 Node-Affinity에 반대되는 옵션인 Taints는 무엇일까요?
Taints의 사전적 의미는 오염, 감염이라는 뜻을 갖고 있는데요.
노드에 Taints를 하면, Toleration을 가진 Pod만 해당 노드에 배포될 수 있게 하는 옵션입니다.





노드에 Taints를 추가하는 명령어는 다음과 같습니다.
kubectl taints node 노드_이름 key=value:effect
여기서 key와 value는 임의로 줄 수 있으나 effect는 정해진 것을 사용해야합니다.
노드에 추가된 Taints를 제거하는 명령은 다음과 같습니다.
kubectl taints node 노드_이름 key=value:effect-
Taints effect에는 NoSchedule, NoExecute, PreferNoSchedule 세 가지 effect가 존재합니다.
NoSchedule은 일치하는 Toleration이 없으면 해당 노드에 파드를 배치할 수 없음을 의미합니다.
PreferNoSchedule은 toleration이 없으면 포드를 스케쥴링 하지 않으려고 하지만, 이는 필수는 아닙니다. 클러스터 내의 자원이 부족하다면 taint가 있는 노드에도 파드가 스케쥴 될 수 있습니다.
NoExecute의 경우 새롭게 생성된 파드가 toleration이 없으면 배치되지 않게 하고, 기존에 존재하던 파드도 taint에 맞는 toleration이 없다면 즉시 종료시킵니다.
Node01에 다음과 같이 taints를 주고, A Pod에 Toleration을 부여해보겠습니다.
kubectl taints node node01 color=white:NoSchedule
---
apiVersion: v1
kind: Pod
metadata:
name: A
spec:
containers:
- name: with-node-affinity
image: k8s.gcr.io/pause:2.0
tolerations:
- key: 'color'
operator: 'Equal'
value: 'white'
effect: 'NoSchedule'
참고로 operator의 경우 Equal 외에도 Exists도 사용가능합니다만, 이 경우 value를 따로 명시하지않아야 합니다.
만약 다음과 같이 effect가 NoExecute인 경우 특정 시간 이후에 노드 내에 있는 Toleration의 파드들을 제거하고 싶다면 다음과 같은 옵션을 줄 수도 있습니다.
---
apiVersion: v1
kind: Pod
metadata:
name: A
spec:
containers:
- name: with-node-affinity
image: k8s.gcr.io/pause:2.0
tolerations:
- key: 'color'
operator: 'Equal'
value: 'white'
effect: 'NoExecute'
tolerationSeconds: 3600
이렇게 하면 5분 뒤에 노드 내에 Toleration이 없는 파드들은 모두 제거될 것입니다.
Pod의 입장에서

그러나 특정 노드의 Taints의 Toleration을 가진 파드가 반드시 해당 노드에 배포되는 것은 아닙니다.
해당 파드는 얼마든지 다른 노드로도 배포될 수 있습니다.
Node-Affinity + Taints And Toleration
그렇다면 앞서 배운 Node-Affinity와 Taints And Toleration를 모두 사용해보겠습니다.
kubectl taints node node01 color=white:NoSchedule

두 기능을 조합하면 특정 파드가 반드시 특정 노드에 배포되는 것을,
특정 노드는 반드시 특정 파드만 배포되게 허락하는 것을 설정할 수 있습니다.
한 줄 요약
Node-Affinity + Taints And Toleration를 사용하면 특정 노드와 특정 파드가 서로 반드시 배치하고 배치되어지는 것을 보장할 수 있다.