파드를 노드에 지정해서 스케줄링하는 방법을 알아보자!
https://kubernetes.io/ko/docs/concepts/scheduling-eviction/assign-pod-node/
노드에 파드를 지정해서 스케줄링을 하는 방법은 3가지가 있다.
Tip!
kube-scheduler는 파드를 노드에 할당한다. 따라서 이 kube-scheduler가 있어야지 스케줄링이 가능하다.
첫번째 방식은 간단히 nodeName 이라는 필드를 사용하는 것이다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: kube-01
여기 간단한 예시 yaml 파일이 있다. 살펴보면 nodeName
이라는 필드가 있다. 이 필드는 kube-01이라는 노드에 해당 파드를 할당하라는 의미이다
이 방법은 간단하지만 클라우드 환경에서 노드 이름이 항상 고정적인 것은 아니고, 따라서 해당 노드이름이 없을 경우 파드가 자동으로 실행되지 않고 삭제될 수 있다. 따라서 뒤에 소개할 방식을 더 사용한다.
노드 셀랙터는 노드가 해당 레이블을 가지고 있고, 파드에 nodeSelector 필드를 사용해서 스케줄링 되기 원하는 노드가 가지고 있는 레이블을 넣어주어 스케줄링하는 것이다.
kubectl label node <노드이름> <레이블 키>=<레이블 벨류>
kubectl get node --show-labels
라는 명령어로 노드에 레이블을 추가하고, 레이블을 확인한다.
그리고 다음과 같이 파드 yaml 에 nodeSelector 옵션을 추가하면된다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: k8s.gcr.io/pause:2.0
샘플예시를 확인해보면 requiredDuringSchedulingIgnoredDuringExecution
같은 경우
matchExpressions
에 해당되는 키를 가지고 있는 노드에 할당된다.
특이한 것은 preferredDuringSchedulingIgnoredDuringExecution
인데 weight
라는 필드가 눈에 띄인다.
weight
는 가중치로 1-100까지 할당 될 수 있으며 가중치가 높을수록 우선순위가 높아진다.
위에 두 케이스를 보면 labels
을 사용하고 있다. 이 label에 대해 알아보자!
레이블은 오브젝트에 첨부된 키벨류 값이다. 보통은 오브젝트 특성을 나타낸다. 따라서 사용자는 레이블을 통해 오브젝트를 구별하거나, 스케줄링이 가능하지만 레이블이 딱히 오브젝트에 핵심적인 변환를 주는 것은 아니다.
레이블을 오브젝트에 적용하는 명령어는 다음과 같다
kubectl label node node01 env=prod
변경하고 싶다면
kubectl label node node01 env=stg --overwrite
레이블은 고유하지 않다. 따라서 여러 오브젝트가 같은 레이블을 가질 수 있다.
쿠버네티스 오브젝트를 조회할 때 해당 레이블을 기준으로 타겟을 잡을 수 있는데 예시는 다음과 같다.
# 전체 레이블 보기
kubectl get po --show-labels
# 레이블 하나 조회
kubectl get po --selector env=prod
# environment=production,tier=frontend 있는 파드 조회
kubectl get pods -l environment=production,tier=frontend
# 키 environment 중 벨류가 production, qa 중 하나인 파드 조회
kubectl get pods -l 'environment in (production, qa)'
# 키 environment 중 벨류가 frontend 파드
kubectl get pods -l 'environment,environment notin (frontend)'
셀랙터는 특정 레이블을 선택하는 필드이다.
selector:
matchLabels:
component: redis
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operator: NotIn, values: [dev]}
위와 같은 예제에서
matchLabels는 해당 레이블을 선택하기 위해
matchExpressions은 레이블을 선택하거나 거부하기 위해 사용된다.
https://kubernetes.io/ko/docs/concepts/scheduling-eviction/taint-and-toleration/
taints는 노드가 특정 파드를 스케줄링에서 제외할 수 있는 옵션이다.
노드에 taints를 지정할 때는 다음과 같이 지정한다.
kubectl taint nodes node1 key1=value1:NoSchedule
이 의미는 node1에 key1=value1 톨러레이션을 가지고 있는 파드가 아니면 스케줄링 할 수 없다는 의미이다.
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
key와 effect가 동일한 경우, 테인트와 톨러레이션을 일치한다고 생각하면 된다.
operator가 Exists이여도, operator가 Equal이고 value가 같다면도 마찬가지이다.
테인트를 제거하기 위해서는 다음 옵션을 사용한다.
kubectl taint nodes node1 key1=value1:NoSchedule-
만약 특정 노드가 테인트 옵션을 가지고 있는 것은 어떻게 알 수 있을까?
kubectl describe node {노드명} | grep -i taints
로 알 수 있다.