Node Selector 와 Node Affinity를 사용하여 파드가 특정 노드에만 실행되도록 제한을 설정할 수 있습니다.
특정한 노드들에서만 동작하거나 특정한 노드 집합에서 동작하는 것을 선호하도록 제한 설정이 가능합니다.
1. Node Selector
파드의 spec 섹션에 node selector라는 새 필드를 추가하여 간단하고 쉽게 설정이 가능합니다.
node selector에서 레이블을 사용하므로 파드 생성 전에 우선 노드에 레이블을 지정해 줘야 한다.
설정한 노드 이름을 key-value 형식으로 사용하여 node selector에서 설정할 수 있습니다.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: data-processor
image: data-processor
nodeSelector:
size: Large
2. Node Affinity
node selector와 비슷하게 노드의 레이블을 기반으로 파드를 스케쥴링합니다.
node selector와 함께 설정할 수 있으며, 이 때는 둘 모두의 조건을 만족하는 노드에 파드를 스케쥴링합니다.
쿠버네티스에서 affinity는 일반적으로 파드가 특정 유형의 노드와 더 많이 조우하도록 만드는 데 사용되는 메커니즘을 나타냄.
Node Affinity 는 더 세세하게 노드에 제한을 설정해 줄 수 있습니다.
파드가 어떤 노드에 배치되기를 선호하는지를 정의하는 데 사용되며 특정 노드에 스케쥴링 되도록 도와줍니다.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: data-processor
image: data-processor
affinity:
nodeAffinity:
requireDuringSchedulingIgnoreDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: size
operator: In
values:
- Large
Affinity type - 두 가지 필드 존재
Availbale
Pod 가 처음 만들어질 때를 생각해 봅시다.
matching label의 노드가 존재하지 않을 때, required/preferred 에 따라 동작이 달라집니다.
- requiredDuringSchedulingIgnoredDuringExecution
- 스케쥴링하는 동안 꼭 필요한 조건입니다.
- 해당 조건에 만족하지 못하면 파드 배정이 되지 않고 pending 상태에 머무릅니다.
- 파드의 위치가 중요한 경우에 사용합니다.
...중략... affinity: nodeAffinity: **requiredDuringSchedulingIgnoredDuringExecution:** nodeSelectorTerms: - matchExpressions: - key: disktype operator: In values: - ssd
preferredDuringSchedulingIgnoredDuringExecution
- 지정한 조건을 가장 잘 만족시키는 노드에 스케쥴링을 시도합니다.
- 조건을 만족하지 않은 노드에도 스케쥴링 가능합니다.
- 이런 경우 스케쥴러는 node affinity rule을 무시하고 가능한 아무 노드에 파드를 배정하므로, 파드의 위치가 별로 중요하지 않은 경우에 사용한다.
...생략
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 10
preference:
- matchExpressions:
- key: disktype
operator: In
values:
- hdd
requiredDuringSchedulingIgnoredDuringExecution 필드와 설정이 비슷합니다.
다른 점은 weight 필드가 있다는 점과 nodeSelectorTerms 대신 preference 필드를 사용한다는 점.
- weight 필드는 1 - 100 까지의 값 설정 가능. 여러 개 matchExpressions 필드 안 설정 각각이 노드의 설정과 맞을 때마다 weight 필드 값을 더한다. 그리고 모든 노드 중에서 weight 필드 값의 합계가 가장 큰 노드를 선택함.
- preference 필드의 조건에 따라 맞는 노드를 우선해서 선택하지만 없다면 없는 대로 조건에 맞지 않는 노드에 파드를 스케쥴링하여 실행함.
ignored during execution : 파드가 배정되어서 running 중일 때 변경사항이 생겨도 영향을 받지 않음.
Planned
- requiredDuringScheduliingRequiredDuringExecution
만약 running 중에 변경이 생기면 해당 pod는 terminated 혹은 evicted(제거) 됩니다.
Operator
operator는 key가 만족할 조건입니다.
node selector나 noce affinity 등에서 사용되는 비교 연산자를 나타냅니다.
이 연산자를 사용하여 라벨 또는 필드의 값을 비교하여 해당 조건이 참인지 여부를 결정합니다.
- Equal: 값이 정확하게 일치하는지 확인합니다.
- NotEqual: 값이 일치하지 않는지 확인합니다.
- Exists: 지정된 키 또는 필드가 존재하는지 확인합니다. 존재하는 경우에만 파드가 스케쥴링됩니다.
- DoesNotExist: 지정된 키 또는 필드가 존재하지 않는지 확인합니다.
- Gt (Greater Than): 값이 지정된 값보다 큰지 확인합니다.
- Lt (Less Than): 값이 지정된 값보다 작은지 확인합니다.
- In: 값이 지정된 값 목록 중 하나와 일치하는지 확인합니다.
- NotIn: 값이 지정된 값 목록 중 어느 것과도 일치하지 않는지 확인합니다.
예시
Node Affinity 예시 - requiredDuringSchedulingIgnoredDuringExecution
[k8s] 파드 스케쥴링 - Node Affinity(노드 어피니티) (tistory.com)
1) 노드의 레이블 확인
kubectl get nodes --show-labels
2) 노드에 레이블 추가
kubectl label nodes k8s-node1 disktype==ssd
3) 노드에 레이블 추가 확인
kubectl get nodes --show-labels
4) 노드 어피니티를 사용하여 파드 스케쥴링
nginx 이미지를 disktype==ssd 라는 label을 가진 노드에 스케쥴링하도록 하는 manifest 파일 정의
# pod-nginx-required-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
# affinity
affinity:
nodeAffinity:
# required
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
# disktype이 ssd인 node에 파드 생성
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
kubectl apply -f pod-nginx-required-affinity.yaml
k8s-node1에 disktype=ssd라는 레이블을 추가하였기 때문에 nginx pod가 k8x-node1에 할당됩니다.
5) 만약 disktype=hdd라는 레이블이 있는 노드에 추가하도록 변경한다면?
affinity:
nodeAffinity:
# required
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
# disktype이 ssd인 node에 파드 생성
- matchExpressions:
- key: disktype
operator: In
values:
- hdd
pod가 pending 상태에서 시작되지 못하는 것을 확인할 수 있습니다.
describe명령어로 파드의 상태를 출력하면,
FailedScheduling 이라는 reason으로 파드가 스케쥴링되지 못했다는 것을 알 수 있다.
오류 메세지: 0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector
해석하자면 노드가 3개 있는데 1개는 taint로 허용되지 않는 노드(master node) 2개는 pod의 affinity selector와 일치하지 않아서 파드가 생성되지 않았다는 뜻입니다.
6) requiredDuringSchedulingIgnoredDuringExecution 필드에서 preferredDuringSchedulingIgnoredDuringExecution으로 변경
# pod-nginx-required-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx2
spec:
# affinity
affinity:
nodeAffinity:
# preferred
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 10
preference:
matchExpressions:
- key: disktype
operator: In
values:
- hdd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
적용 후 확인하면 두 개의 파드 모두 생성되는 것을 확인할 수 있습니다.
Set Node Affinity to the deployment to place the pods on node01 only.
edit 명령어로 deployment 에 node affinity 필드를 추가합니다.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: blue
spec:
replicas: 3
selector:
matchLabels:
run: nginx
template:
metadata:
labels:
run: nginx
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: color
operator: In
values:
- blue
중요) spec.template.spec 에 존재해야합니다.
어떤 리소스 던지 affinity는 pod의 스펙 정의하는 곳에 넣어야 함.
apiVersion: apps/v1
kind: Deployment
metadata:
name: red
spec:
replicas: 2
selector:
matchLabels:
run: nginx
template:
metadata:
labels:
run: nginx
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: **Exists**
여기서 operator가 equal이 아니고 Exists 인 이유:
해당 노드에 다양한 라벨이 있을 수 있기 때문입니다.
Taints and Tolerations VS Node Affinity ⭐⭐⭐
Taints and Toleration만 사용하여 각각의 색깔에 맞는 노드에 파드를 배정하려고 했을 때 Toleration을 가진 파드는 taints 가 없는 노드에도 배정될 수 있는 위험이 존재하고,
Node Affinity 만을 사용할 때는 노드에 원하지 않는 파드가 배정될 수 있는 위험이 존재합니다.
이 때 두 가지 방법을 모두 사용하여 원하는 노드에 원하는 파드만 배정할 수 있습니다.
먼저 노드에 taint 를 부여하여 해당하는 색(레이블)만 배정될 수 있게 하고 파드에 node affinity를 정해주면 해당하는 색의 노드에 해당하는 색의 파드만 배정할 수 있을 것이다.
참고
Certified Kubernetes Adiminstrtor(CKA) with Practice Tests by Mumshad Mannambeth, KodeKloud Training
'K8S > Scheduling' 카테고리의 다른 글
Daemon Sets (0) | 2024.01.19 |
---|---|
[Scheduling] Resource Requirements and Limits (0) | 2024.01.19 |
Taints and Tolerations⭐⭐⭐ (0) | 2024.01.18 |
[Scheduling] Pod Scheduling Process, nodeName (0) | 2024.01.18 |
Labels & Selectors (1) | 2024.01.18 |