Featured image of post 유연한 고급 스케줄링

유연한 고급 스케줄링

유연한 고급 스케줄링

유연한 고급 스케줄링

필터링과 스코어링

  • 필터링: 파드 스케줄시 충분한 리소스가 있는지, 필수 조건으로 지정한 레이블을 가진 노드인지 등을 체크
  • 스코어링: 필터링 후 노드 목록에 순위를 매겨 가장 적합한 노드를 계산
  • 필터링과 스코어링 이후 우선순위가 같은 스케줄링 대상 노드가 여러개 존재 시 무작위 선택

매니페스트에서 지정하는 스케줄링

  • 사용자가 배치하고 싶은 노드를 선택하는 방법과 관리자가 배치하고 싶지 않은 노드를 지정하는 방법이 있음
  • 쿠버네티스 사용자가 배치하고 싶은 노드를 선택하는 방법
종류 개요
nodeSelector(가장 단순한 노드 어피니티) 단순한 노드 어피니티 기능
노드 어피니티 특정 노드상에서만 실행
노드 안티어피니티 특정 노드 이외에서 실행
인터파트 어피니티 특정 파드가 존재하는 도메인(노드, 존)에서 실행
인터파트 안티어피니티 특정 파드가 존재하지 않는 도메인에서 실행

빌트인 노드 레이블과 레이블 추가

  • 빌트인 노드 레이블: 노드에 미리 지정되어 있는 레이블
1
2
## 노드에 할당된 레이블 정보
$ kubectl get nodes -o json | jq ".items[] | .metadata.labels"
1
2
3
4
5
6
## kubectl get nodes에서 확인한 노드명을 지정하여 레이블 부여
$ kubectl label node NODE_NAME disktype=hdd cpuspec=low cpugen=3

$ kubectl label node NODE_NAME disktype=ssd cpuspec=low cpugen=2

$ kubectl label node NODE_NAME disktype=hdd cpuspec=high cpugen=4
1
2
## 노드 목록과 disktype 레이블 표시
$ kubectl -L=disktype,cpuspec,cpugen get node

nodeSelector(가장 단순한 노드 어피니티)

  • 단순한 노드 어피니티만을 실행하는 경우
  • equality-based는 단일 조건만 지정할 수 있음
1
2
## 반드시 disktype=ssd인 레이블을 가진 노드에서 기동
$ kubectl get pods sample-nodeselector -o wide

노드 어피니티

  • 파드를 특정 노드에 스케줄링하는 정책
  • spec.affinity.nodeAffinity에 작성

노드 어피티니의 필수 스케줄링 정책과 우선 스케줄링 정책

설정 항목 개요
requiredDuringSchedulingIgnoredDuringExecution 필수 스케줄링 정책
preferredDuringSchedulingIgnoredDuringExecution 우선적으로 고려되는 스케줄링 정책
  • 필수 조건 requiredDuringSchedulingIgnoredDuringExecution이 만족되지 않은 스케줄링을 수행시 스케줄링에 실패

    • preferredDuringSchedulingIgnoredDuringExecution는 어디까지나 우선적으로 스케줄링을 하는 것
  • 필수 조건의 스케줄링 정책

    • nodeSelectorTerms: 어떤 조건의 노드가 스케줄링 가능한 노드인지 정의
      • 복수 지정 가능, OR 조건
      • matchExpressions: AND 조건이 되도록 여러 조건 지정
1
2
3
4
5
6
7
8
## (A and B) or (C and D)
nodeSelectorTerms:
- matchExpressions:
  - A
  - B
- matchExpressions:
  - C
  - D
  • 우선 조건의 스케줄링 정책에서도 복수 조건 지정 가능
    • 우선순위의 가중치(weight)와 조건 쌍 여러개
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
## (A and B)가 가중치 X, (C and D)가 가중치 Y의 우선순위로 스케줄링 실시
preferredDuringSchedulingIgnoredDuringExecution:
- weight: X
  preference:
    matchExpressions:
      - A
      - B
- weight: Y
  preference:
    matchExpressions:
      - C
      - D

matchExpressions 오퍼레이터와 집합성 기준 조건

  • matchExpressions는 key 레이블, 오퍼레이터, values 레이블이라는 세 가지 요소로 구성
    • values 레이블은 배열로 취급
  • 레플리카셋/디플로이먼트/데몬셋/스테이트풀셀/잡의 셀렉터에서 사용 가능
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
- matchExpressions:
  - key: disktype
    operator: In
    values:
    - ssd
    - hdd

## 한 줄로 정의한 경우
- matchExpressions:
  - {key: disktype, operator: In, values: [ssd, hdd]}

matchExpressions에서 사용 가능한 오퍼레이터

오퍼레이터 종류 사용 방법 의미
In A In [B, …] 레이블 A의 값이 [B, …] 중 어느 하나 이상과 일치
NotIn A NotIn [B, …] 레이블 A의 값이 [B, …] 중 어느 것에도 일치하지 않음
Exists A Exists [] 레이블 A가 존재
DoesNotExist A DoesNotExist [] 레이블 A가 존재하지 않음
Gt A Gt [B] 레이블 A의 값이 B보다 큼
Lt A Lt [B] 레이블 A의 값이 B보다 작음
  • Exists는 values 지정 불가 (key가 존재하는지 여부만이 조건)
  • DoesNotExist는 key가 존재하지 않는 것이 조건
  • Gt/Lt는 values에 하나의 정수 값만 지정

노드 안티어피니티

  • 파드를 특정 노드 이외의 다른 노드에 스케줄링하는 정책
  • spec.affinity.nodeAffinity 조건에 부정형 오퍼레이터를 지정(엄밀히 말하면 노드 안티어피니티는 존재하지 않음)

인터파드 어피니티

  • 특정 파드가 실행되는 도메인에 파드를 스케줄링 하는 정책
  • spec.affinity.podAffinity에 조건 지정
  • 가까이 있는 파드끼리는 통신 레이턴시가 적음
  • 노드들간 기능 차이가 적을 경우 노드를 의식하지 않고 파드 기반의 스케줄링만으로 제어 가능
  • topology는 어느 범위(도메인)를 스케줄링 대상으로 할지를 지정
  • requiredDuringSchedulingIgnoredDuringExecution은 배열로 여러 조건 지정 가능
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
## (A and B)의 파드와 같은 X에 있는 노드 or (C and D)의 파드와 같은 Y에 있는 노드
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
    matchExpressions:
    - A
    - B
  topologyKey: X
- labelSelector:
    matchExpressions:
    - C
    - D
  topologyKey: Y

인터파드 안티어피니티

  • 특정 파드가 없는 도메인에서 동작시키는 정책
  • spec.affinity.PodAntiAffinity 지정 가능

여러 조건을 조합한 파드 스케줄링

  • 노드 어피니티/노드 안티어피니티/인터파드 어피니티/인터파드 안티어피니티 조합하여 사용 가능

테인트와 톨러레이션

  • 쿠버네티스 관리자가 배치하고 싶지 않은 노드를 지정하는 방법
  • 노드에 대한 테인트를 설정해 두고 그것을 허용할 수 있는 파드만 스케줄링 허가
  • 조건에 맞지 않는 파드를 노드에서 축출 가

테인트 부여

  • 세 가지 파라미터를 사용한 Key=Value:Effect 형식으로 구성
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
## 특정한 한 대의 노드에 env=prd:Noschedule 테인트 부여
$ kubectl taint node NODE_NAME env:prd=NoSchedule

## 특정 레이블을 가진 모든 노드에 env=prd:NoSchedule 테인트 부여
$ kubectl taint node -l kubernetes.io/os=linux env=prd:NoSchedule

## env를 키로 하는 테인트 삭제
$ kubectl taint node NODE_NAME env-

## env를 키로 하는 NoSchedule 테인트 삭제
$ kubectl taint node NODE_NAME env:NoSchedule-

## 부여된 테인트 확인
$ kubectl describe node NODE_NAME
  • Key, Value는 임의의 값으로 지정하고 노드 어피니티와 동일하게 일치 여부를 조건으로 사용
  • Effect는 테인트와 톨러레이션이 일치하지 않을 경우의 동작

Effect 종류

Effect 종류 개요
PreferNoSchedule 가능한 한 스케줄링하지 않음
NoSchedule 스케줄링하지 않음(이미 스케줄링된 파드는 유지)
NoExecute 실행을 허가하지 않음(이미 스케줄링된 파드는 정지
PreferNoSchedule
  • 파드에 톨러레이션 설정이 없는 경우나 테인트에 일치하지 않아도 스케줄링 대상 노드가 됨
NoSchedule
  • 파드에 톨러레이션 설정이 없는 경우나 테인트에 일치하지 않으면 스케줄링 허가하지 않음
NoExecute
  • 일반적인 파드 정지처럼 terminationGracePeriodSeconds로 유예 기간 설정

톨러레이션을 지정한 파드 기동

  • Key/Value/Effect 지정 후 테인트에서 부여된 Key/Value/Effect가 같은 경우 허용
  • 완전 일치뿐만 아니라 Key/Value/Effect중 하나를 미지정한 경우 와일드카드로 처리
  • spec.tolerations로 지정

톨러레이션에서 지정 가능한 오퍼레이터

오퍼레이터 개요
Equal Key = Value
Exists Key 존재
  • NoSchedule과 NoExecute의 경우 조건과 Effect 모두 일치할 경우 스케줄링
  • PreferNoSchedule은 조건이 일치하지 않아도 스케줄링 되지만 우선순위 하락
  • 어떤 테인트가 부여되든 관계엾이 스케줄링하는 경우 Exists 오퍼레이터만 지정하면 모든 조건에 일치 가능
1
2
tolerations:
  - operator: Exists

NoExecute 일정 시간 허용

  • 조건이 일치하는 파드는 일정 기간만 가동을 허용하는 스케줄링을 할 때 사용

여러 개의 테인트와 톨러레이션

  • 여러 테인트가 부여된 경우 파드의 톨러레이션은 모든 테인트 조건을 만족해야 해당 노드에 스케줄링 가능

장애 시 부여되는 테인트와 축출

  • 노드 장애 발생 시 자동으로 NoExecute의 테인트 부여하여 자동으로 파드 축출

노드 장애시 부여되는 테인트

Effect Key 개요
NoSchedule node.kubernetes.io/not-ready 노드 상태가 NotReady
NoSchedule node.kubernetes.io/unreachable 노드와의 네트워크 접속이 되지 않는 경우 (Unknown)
  • 장애가 발생해도 계속 기동하고 싶은 경우 위 테인트에 대응하는 톨러레이션을 설정해야 함
  • 기본적으로 tolerationsSecond=300으로 부여되며 300초 이내에 노드 문제를 해결하지 않으면 파드가 축출됨
1
2
3
4
5
6
7
8
9
tolerations:
- effect: NoExecute
  key: node.kubernetes.io/not-ready
  operators: Exists
  tolerationSeconds: 300
- effect: NoExecute
  key: node.kubernetes.io/unreachable
  operators: Exists
  tolerationSeconds: 300

쿠버네티스가 부여하는 그 외 테인트

Effect Key 개요
NoSchedule node.kubernetes.io/memory-pressure 노드에 메모리 부족
NoSchedule node.kubernetes.io/disk-pressure 노드에 디스크 뷰족
NoSchedule node.kubernetes.io/pid-pressure 노드에 PID 고갈
NoSchedule node.kubernetes.io/network-unavailable 노드의 네트워크가 연결되지 않음
NoSchedule node.kubernetes.io/unschedulable kubectl cordon에 의해 스케줄링에서 제외됨
  • 문제가 발생해도 스케줄링하고 실행해야 하는 중요도가 높은 파드는 톨러레이션 설정
  • 클라우드 환경에서 노드가 생성되고 삭제될 때 부여되는 테인트도 있음

PriorityClass를 이용한 파드 우선순위와 축출

  • 파드가 이미 리소스의 한계까지 스케줄링된 상태에서 우선순위가 높은 파드를 생성하는 경우 기존 파드 축출 가능
  • 여러 파드가 스케줄링 대기 상태일 경우 스케줄링 순서는 수시로 정렬되어 우선순위가 높은 파드부터 스케줄링

PriorityClass 생성

  • system-으로 시작하는 이름은 예약어로 등록되어 있으 붙일 수 없음
  • 우선순위(value)와 설명(description)으로 구성됨
  • globalDefault 옵션을 true로 설정시 PriorityClass가 지정되지 않은 파드에 기본 우선순위 설정으로 PriorityClass 부여
  • globalDafault: true의 PriorityClass가 여러 개 존재할 경우 가장 우선순위가 낮은 PriorityClass가 기본 우선순위 설정으로 부여
  • PriorityClass가 전혀 연결되지 않는 경우 priority는 0
  • PriorityClass를 파드의 spec.podPriorityClass에 지정
    • 해당 podPriorityClass를 가지고 spec.Priority를 자동 업데이트
    • 수동으로 spec.Priority 지정한 경우 파드 생성 불가
1
2
## 파드에 지정된 우선순위 확인
$ kubectl get pods sample-high-priority -o jsonpath='{.spec.priority}'
  • 파드 축출시 노드상에 원순위가 낮은 파드를 제외한 상태에서 어피니티 등의 조건을 만족하는지 판단
  • 우선순위가 낮은 파드에 인터파드 어피니티를 설정하면 스케줄링이 수행되지 않는 경우 있음
    • 인터파드 어피니티는 우선순위가 높거나 같은 파드에 스케줄링 해야함

우선순위 축출 비활성화

  • 우선순위를 설정하고 싶지만 다른 파드를 축출하고 싶지 않은 경우 사용
  • 스케줄링시 우선순위가 높은 파드부터 스케줄링됨
  • preemtionPolicy를 Never로 설정

PriorityClass와 PodDisruptionBudget의 경합

  • PriorityClass에 의한 축출은 podDisruptionBudget을 고려하여 스케줄링

기타 스케줄링

  • 커스텀 스케줄러 생성 가능
    • 기존 쿠버네티스 스케줄러에 할당되지 않도록 파드에 spec.schedulerName 지정해야 함
  • 스캐줄러를 구현하지 않은 경우 Pending 상태 유지
Hugo로 만듦
JimmyStack 테마 사용 중