본문 바로가기
CICD

[Kubernetes] Node Scheduling(Pod)

by 장중앙 2022. 1. 20.

Kubernetes의 Node Scheduling

  • Pod를 생성할 경우, 생성할 Pod가 어떤 노드에 할당되어야 할지 유저가 지정하거나 쿠버네티스에서 자동적으로 할당가능 또는 운영자가 특정 노드를 사용하지 못하도록 관리 가능
  • 이를 Scheduling이라고 부르며 쿠버네티스는 다양한 기능으로 이러한 Scheduling을 지원

 

Node Scheduling을 지원하는 다양한 기능

1. 특정 Node를 선택하는 방법

  • NodeName
    • Pod를 생성하면서 특정 Node를 지정 Scheduler와 상관없이 Node에 할당됨 
    • 명시적으로 사용할 수 있어 좋아보이지만, 실사용에서는 Node의 이름이 계속해서 변경되기 때문에 자주 사용하지는 않음
  • NodeSelector
    • Node의 Label(Key, Value)을 지정하여 해당 Node에 할당됨
    • 같은 Label을 가진 Node 중에서는 Scheduler에 의해 자원이 많은 Node에 할당
    • 매칭이 되는 Label(Node)가 없다면 어떠한 Node에도 할당이 안됨
  • NodeAffinity
    • NodeSelector를 보완하여 사용할 수 있는 기능
      • Node Affinity는 matchExpressions와 Required, Preferred의 옵션을 이용하여 복잡/세부적인 조건 구성 가능
  • Node Affinity의 2가지 옵션
    • Required : 해당 조건에 반드시 부합하는 Node에만 할당
    • Preferred : Required에 비해 유연한 선택이 가능
      • 해당 조건에 부합하지 않더라도 preferred Weight(가중치)에 의해 결정
        • Preferred Weight : Preferred 옵션에서 조건에 따른 가중치를 부여함

2. Pod간 집중/분산

  • Node가 아닌 Pod를 기준으로 할당하는 방법

  • Pod Affinity
    • 같은 PV 호스트패스를 사용한다면 Master Pod가 최초 할당된 Node에 Slave도 함께 생성
    • 다수의 Pod가 네트워크와 같은 리소스 효율을 위해 동일한 Node에 동작하는 것이 효율적일 때 사용
  • Anti-Affinity
    • Master와 Slave를 서로 다른 Node에 생성
    • Pod들이 같이 있으면 해당 Node가 다운될 때, 서비스가 다운될 수도 있는 경우에 사용

 

 

3. 특정 Node에 대해 할당 제한

  • Toleration/Taint
    • 일반적인 경우에는 Node할당을 컨트롤하여, 해당 Node에는 Pod 생성이 되지 않게 함
    • Pod가 해당 Node를 직접 지정해도 할당 불가능
    • Toleration옵션이 있어야만 할당가능
    • GPU와 같이 특별한 하드웨어 옵션을 가진 Node를 이용하는 특정 Pod 배치에 유용하게 사용가능
    •  
    • Taint / Toleration의 옵션
    •  

 


실습


1. Node Affinity

console에서 각 Node에 Label 설정

# kubectl label nodes "node name" "key=value"
kubectl label nodes k8s-node1 kr=az-1
kubectl label nodes k8s-node2 us=az-1

 

Match Expressions를 설정하여 Pod 생성

apiVersion: v1
kind: Pod
metadata:
 name: pod-match-expressions1
spec:
 affinity:
  nodeAffinity:
   requiredDuringSchedulingIgnoredDuringExecution:   
    nodeSelectorTerms:
    - matchExpressions:
      -  {key: kr, operator: Exists}
 containers:
 - name: container
   image: kubetm/app
 terminationGracePeriodSeconds: 0

생성된 Pod확인

kr label을 지정한 Node 1에 Pod가 생성됨

key : ch를 지정한 Required 옵션의 Pod 생성

apiVersion: v1
kind: Pod
metadata:
 name: pod-required
spec:
 affinity:
  nodeAffinity:
   requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
    - matchExpressions:
      - {key: ch, operator: Exists}
 containers:
 - name: container
   image: kubetm/app
 terminationGracePeriodSeconds: 0

Pod 생성 확인

시간이 지나도 Pod가 생성되지 않음

Key : ch로 지정했는데 이러한 Key를 가진 Node는 존재하지 않기 때문

    Required 옵션은 해당 조건에 부합하는 Node가 존재해야만 할당가능

 

key : ch를 지정한 Preferred옵션의 Pod 생성

apiVersion: v1
kind: Pod
metadata:
 name: pod-preferred
spec:
 affinity:
  nodeAffinity:
   preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 1
      preference:
       matchExpressions:
       - {key: ch, operator: Exists}
 containers:
 - name: container
   image: kubetm/app
 terminationGracePeriodSeconds: 0

Pod 생성 확인

Required와 다르게 Preferred옵션은 해당 조건에 맞는 Node가 존재하지 않아도 자원의 여유가 큰 Node에 할당


2. Pod Affinity

console에 Node에 Label을 설정

kubectl label nodes k8s-node1 a-team=1
kubectl label nodes k8s-node2 a-team=2

 

web Pod를 생성

a-team-1에 할당되도록 Node Selector를 이용

apiVersion: v1
kind: Pod
metadata:
 name: web1
 labels:
  type: web1
spec:
 nodeSelector:
  a-team: '1'
 containers:
 - name: container
   image: kubetm/app
 terminationGracePeriodSeconds: 0

Pod 생성 확인

a-team : 1의 label을 가지는 Node1에 생성됨

 

Affinity Pod인 server1 Pod 생성

Affinity속성의 Pod Affinity를 이용

    Topology key를  a-team으로 설정

    web1 Pod와 같은 Node에 생성해야하므로 MatchExpresion을 이용

apiVersion: v1
kind: Pod
metadata:
 name: server1
spec:
 affinity:
  podAffinity:
   requiredDuringSchedulingIgnoredDuringExecution:   
   - topologyKey: a-team
     labelSelector:
      matchExpressions:
      -  {key: type, operator: In, values: [web1]}
 containers:
 - name: container
   image: kubetm/app
 terminationGracePeriodSeconds: 0

생성된 Pod확인

web1와 같은 Node인 Node1에 생성됨


 

3. Anti-Affinity

Pod Affinity와 동일한 Node Label을 이용하여 진행

kubectl label nodes k8s-node1 a-team=1
kubectl label nodes k8s-node2 a-team=2

Master Pod생성

a-team : 1의 Label을 가지는 Node에 할당되도록 생성

apiVersion: v1
kind: Pod
metadata:
  name: master
  labels:
     type: master
spec:
  nodeSelector:
    a-team: '1'
  containers:
  - name: container
    image: kubetm/app
  terminationGracePeriodSeconds: 0

 

생성된 Pod 확인

a-team : 1의 label을 가지는 Node1에 생성됨

 

slave Pod 생성

PodAntiAffinity 속성을 이용하여 생성

  topologyKey를 a-team으로 설정

  Master와 다른 Node에 생성해야하므로 Master에 대한 MatchExpression을 설정

apiVersion: v1
kind: Pod
metadata:
 name: slave
spec:
 affinity:
  podAntiAffinity:
   requiredDuringSchedulingIgnoredDuringExecution:   
   - topologyKey: a-team
     labelSelector:
      matchExpressions:
      -  {key: type, operator: In, values: [master]}
 containers:
 - name: container
   image: kubetm/app
 terminationGracePeriodSeconds: 0

4. Taint / Toleration

하나의 Node에 label 설정

kubectl label nodes k8s-node1 gpu=no1

특정 Node에 Taint 설정

kubectl taint nodes k8s-node1 hw=gpu:NoSchedule

 

Toleraion옵션을 활용하여 Pod 생성

Taint에 지정한 값과 동일하게 Toleration을 설정

apiVersion: v1
kind: Pod
metadata:
 name: pod-with-toleration
spec:
 nodeSelector:
  gpu: no1
 tolerations:
 - effect: NoSchedule
   key: hw
   operator: Equal
   value: gpu
 containers:
 - name: container
   image: kubetm/app
 terminationGracePeriodSeconds: 0

생성된 Pod 확인

지정한 Node1(Taint) 로 Pod가 생성되는 것을 확인

 

Pod 생성

Toleration 옵션없이 gpu : no1인 Node를 지정하여 생성

apiVersion: v1
kind: Pod
metadata:
 name: pod-without-toleration
spec:
 nodeSelector:
  gpu: no1
 containers:
 - name: container
   image: kubetm/app
 terminationGracePeriodSeconds: 0

 

생성된 Pod 확인

Taint가 있는 Node1에 Toleration으로 조건을 부합하지 못했기 때문에 생성 실패

 

 

Toleration옵션에 NoExecute를 설정하여 Pod1 생성

    TolerationSec : 30으로 지정

apiVersion: v1
kind: Pod
metadata:
 name: pod1-with-no-execute
spec:
 tolerations:
 - effect: NoExecute
   key: out-of-disk
   operator: Exists
   tolerationSeconds: 30
 containers:
 - name: container
   image: kubetm/app
 terminationGracePeriodSeconds: 0

일반적인 Pod2 생성

apiVersion: v1
kind: Pod
metadata:
 name: pod2-without-no-execute
spec:
 containers:
 - name: container
   image: kubetm/app
 terminationGracePeriodSeconds: 0

생성된 Pod1,2 확인

Pod 1와 2 모두 Node1의 Taint에 대해 부합하지 않기 때문에 Node2에 생성됨

 

Node 1, Node 2에 Taint 수정 및 설정

Node 1의 Taint옵션인 NoSchedule을 제거

    -> 해당 Taint를 가지지 않아도 할당 가능

Node 2의 Taint에 NoExecute를 설정

    -> NoExecute 옵션을 설정하여 key와 value에 부합하지 않은 기존 Pod를 제거

kubectl taint nodes k8s-node1 hw=gpu:NoSchedule-
kubectl taint nodes k8s-node2 out-of-disk=True:NoExecute

 

 

두 Pod 모두 Node2에서 삭제되고 Node1에 재생성됨

단, TolerationSec : 30을 설정한 Pod1의 경우 Node1에서 30초 뒤에 삭제됨

댓글