쿠버네티스 스케줄러 (Kube-Scheduler, Scheduler Framework)

온프레미스 K8s 클러스터 구축하기 - 이론 및 검증 4
이민석's avatar
Apr 08, 2025
쿠버네티스 스케줄러 (Kube-Scheduler, Scheduler Framework)

A. Kube-Scheduler

A.1. Kube-Shceduler란 무엇인가

Scheduling[A-1]은 파드가 node[A-2]에 적합한지를 확인하는 과정이며,
해당 node에서 실행된 kubelet[A-3]이 파드를 실행할 수 있도록 조치해줍니다.

Kube-Scheduler[A-1]는 아래의 책임을 가지고 있습니다.

  1. 노드에 할당되지 않은 새로 생성된 파드들을 감시합니다.

  2. 감시한 모든 파드가 실행될 최적의 노드를 갖는 책임을 가집니다.

[명령어 1] Kube Scheduler

1. kube-scheduler 파드 조회하기

kubectl get pods -n kube-system | grep kube-scheduler
kube-scheduler-cp-k8s 1/1 Running 224 (13d ago) 39d

1. kube-scheduler 파드 Manifest 조회하기

kubectl get pod kube-scheduler-cp-k8s -n kube-system -o yaml | grep image
image: registry.k8s.io/kube-scheduler:v1.31.6 imagePullPolicy: IfNotPresent image: registry.k8s.io/kube-scheduler:v1.31.6 imageID: registry.k8s.io/kube-scheduler@sha256:8a64af33c57346355dc3cc6f9225dbe771da30e2f427e802ce2340ec3b5dd9b5

즉, Scheduling을 간단하게 말하면,
파드[A-2]가 노드[A-3]에 적합한지 확인하는 과정이며,
해당 노드에서 실행된 Kubelet[A-3]이 파드를 실행할 수 있게 조치해줍니다.

A.2. Kube-Scheduler 추상적으로 이해하기

Kube-Shceduler는 추상적으로 보면 3단계로 구성되어 있습니다.

  1. Filtering : 파드 요구사항과 노드 상태를 취합해 사용 가능한 노드 목록 추출

  2. Scoring : 노드 목록 중에서 가장 최적의 노드를 고르기 위한 점수 계산

  3. Binding : 파드를 실제로 해당 노드에서 실행하는 단계

Kube-Scheduler 작동 순서 추상화 (1단계)
[그림 1] Kube-Scheduler 작동 순서 추상화 (1단계)

즉, Filtering과 Scoring을 통해서 스케줄링 대상 노드를 1개로 특정하게 됩니다.

Kube-Scheduler 작동 순서 추상화 (2단계)
[그림 2] Kube-Scheduler 작동 순서 추상화 (2단계)

이 과정을 Scheduling Context라고 부르며 작업 특성에 따라 2종류로 구분합니다.

  1. Scheduling Cycle : 파드를 배치할 노드를 탐색

  2. Binding Cycle : 파드를 노드에 배치, 낙관적 바인딩*(Optimistic Binding)[A.2-1]

💡

[낙관적 바인딩*] Binding이 성공할 것이라고 낙관적으로 예측하여, Kube-Scheduler는 Binding의 완료를 기다리지 않고 다음 대상을 탐색한다.

[그림 3] Kube-Scheduler 작동 순서 추상화 (3단계)

이런 구조는 Scheduler Framework[A.2-2]에서 더 자세히 볼 수 있었습니다.
(Kube-Scheduler가 사용하는 프레임워크가 Scheduler Framework이다.)

A.3. Scheduler Framework 기본

Scheduler Framework의 실행 과정을 큰 범위에서부터 2, 3단계로 분류하였습니다.
하지만 실제로는 복잡하고 체계적으로 작동하며 몇 가지 이슈 포인트*가 있습니다.

  1. Scheduling 대상을 찾고 지정하는 Queueing mechanism이 별도로 존재한다.

  2. Scheduling 대상에 대한 11단계의 Scheduling 과정이 존재한다.

💡

[이슈 포인트*] 1. Scheduling 과정 중의 Race Condition 발생 가능성 2. Optimistic Binding 으로 인한 Resource Leak 발생 가능성

A.4. 파드 Queueing Mechanism

Queueing Mechanism[A.4-1]에서는 3가지 포인트를 이해하면 좋습니다.

  1. 3종류의 큐(Q, Queue)의 목적

  2. 각 큐 간에 메세지를 옮기는 고루틴(Goroutine)와 고함수(GoFunction)

  3. 활성 큐(ActiveQ)에서 선택(추출, pop)되는 대상

기본적으로 Queueing Mechanism에서는 3종류의 큐(Q)가 있습니다.

  1. 활성 큐(ActiveQ) : 즉각적인 스케줄링을 위한 파드

  2. 실패 큐(BackoOffQ) : 예약에 실패한 포드로 일반적으로 재시도함

  3. 스케쥴 불가 큐(UnschedulableQ) : 특정 조건의 발생하기를 기다리는 대기(parking) 파드용

[그림 4] Queueing Mechanism 시각화 (1단계)

또한 Queueing Mecahnism에는 메세지를 옮기는 2종류의 고루틴이 있습니다.
(정확한 명칭으로는 주기적 플러싱 고루틴(Periodic Flushing Goroutine)입니다.)

고루틴 이름

flushUnschedulableQLeftover [A.4-2]

flushBackoffQCompleted [A.4-3]

주기 (최악)

30초 (60초)

1초

최소 시간*

  1. UnschedulableQ에 30초 이상 존재할 것

  2. 특정 이벤트에 의해 이동하지 못한 파드들을 이동

  1. Backoff 시간이 충분히 지난 파드를 ActiveQ로 이동

또한 특수한 경우에 이벤트 기반으로 호출되는 2종류의 고함수가 존재합니다.

물론 노드 추가, 업데이트, 기존 파드 삭제 등의 경우에는 아래 고함수를 호출합니다.

고루틴 이름

MoveAllToActiveOrBackoffQueue [A.4-4]

movePodsToActiveOrBackkoffQueue (==moveRequest) [A.4-5]

이벤트

노드 추가 및 업데이트
기존 파드 삭제

Pod, Node, Service, PV, PVC, StorageClass, CSI Node 변경

이유

환경이 변경된 이후에는
파드가 스케줄 가능할 수 있음

특정 설정이 변경된 이후에는
파드가 스케줄 가능할 수도 있음

[그림 5] Queueing Mechanism 시각화 (2단계)

마지막으로 활성 큐(ActiveQ) [A.4-6]에서는 2가지 기준으로 파드를 선택합니다.

  1. .spec.priority와 같은 우선순위*값

  2. 우선순위값이 동일한 경우에는 큐에 먼저 들어온 시간부터

시리즈 문서 중 PriorityClass란? [A.4-7]의 일부

파드의 우선순위(.spec.priority)는 기본적으로 0이며,
우선순위 클래스 이름(.spec.priorityClassName)이 할당된 경우,
우선순위 클래스(PriorityClass)의 값(.value)를 참조하게 됩니다.
-21억 ~ 10억은 사용자가 우선순위 클래스에서 할당할 수 있는 범위이며
10억 ~ 21억은 시스템에서 우선적으로 점유하고 있는 범위입니다.

따라서 시스템에서 사용되는 파드가 먼저 배포되는 현상을 이해할 수 있을 것입니다.
(노드가 새로 뜨면 반드시 aws-vpc-cni, coredns 등이 먼저 스케줄되는 현상)

A.5. 파드 Scheduling 11단계

[그림 3] 에서는 2, 3단계로 표현한 kube-scheduler는 실제로는 11단계입니다.
각 단계는 플러그인 API인지 내부 API인지에 따라서 2가지로 구분됩니다.

  1. 살구색 실선 박스(Extensible API)

  2. 회색 점선 박스(Internal API)

[그림 4] Scheduling Framework 추상화 (1단계)

각 단계의 대략적인 목적(역할)을 이해하는 것을 우선으로 합니다.
이 과정에서 다양한 플러그인들 [A.5-1]들이 활용됩니다.

  1. Filtering

    1. PreFilter : 전제 조건 확인 또는 전처리

    2. Filter : 조건에 맞는 노드 필터링

    3. PostFilter(생략) : 조건에 맞는 노드가 없을 경우 호출 (DefaultPreemption)

  2. Scoring

    1. PreScore : Score 계산을 위한 전처리

    2. Score : 여러 기준에 따라서 Score 계산

    3. NomalizeScore : 다양한 Score의 합산을 100으로 만들기 위한 정규화

    4. Reserve : 자원 경합을 방지하기 위한 Cache 업데이트 기능

    5. Premit : Bind 시작을 의도적으로 지연 시킬 수 있음

  3. Binding

    1. WaitonPremit : Premit에서 건 Bind 지연을 위한 트리거가 풀릴 때까지 대기

    2. PreBind : Bind 전에 필요한 리소스 준비

    3. Bind : 파드를 노드에 Bind (Default Bind plugin)

    4. PostBind : Bind 완료 후 처리 단계 (리소스 정리, 로깅 등)

A.6. 더 공부할 부분

작성일(25.04.09) 시점,
PriorityClass 공부를 위한 최소한의 수준을 배우는 목적을 달성했다고 생각합니다.

만약 이 글을 이어서 작성하게 된다면 아래 부분을 작성할 예정입니다.

  1. Scheduler Framework default plugins 들의 코드 분석

  2. Scheduler Framework 성능 튜닝과 관련된 테크닉

  3. Scheduler Framework 실습

참고 자료

  1. Docs (Kubernetes) - Kubernetes Scheduler

  2. Docs (Kubernetes) - Scheduling Frmawork

  3. T Story (ENFJ.dev) - Kubernetes Scheduler, 제대로 이해하기

  4. Blog (Deepdivers.dev) - (1) 스케줄러 동작 원리와 Scheduling Framework 이해

  5. Blog (NETPPLE) - 6편. kube-scheduler

Share article

Unchaptered