스케줄러 성능 튜닝

스케줄러 성능 튜닝 (Scheduler Performance Tuning)

커다란 쿠버네티스 클러스터에서 스케줄러가 모든 노드를 다 검사하면 성능이 느려질 수 있어요. 이 페이지에서는 대규모 클러스터에 관련된 스케줄러 성능 튜닝 최적화를 설명합니다.

출처: 쿠버네티스 공식 문서 — Scheduler Performance Tuning

기능 상태: Kubernetes v1.14 [beta]

kube-scheduler는 쿠버네티스 기본 스케줄러입니다. 클러스터의 노드에 Pod를 배치하는 역할을 해요.

Pod의 스케줄링 요구사항을 충족하는 노드를 적합한(feasible) 노드라고 합니다. 스케줄러는 Pod를 위한 적합한 노드를 찾고, 그 노드들을 점수화하는 일련의 함수를 실행해 그중 점수가 가장 높은 노드를 골라 Pod를 실행합니다. 그런 다음 스케줄러는 바인딩(Binding) 이라는 과정에서 이 결정을 API 서버에 알립니다.

대규모 클러스터에서는 대기 시간(새 Pod가 빨리 배치되는지)정확도(스케줄러가 잘못된 배치를 거의 하지 않는지) 사이에서 스케줄러 성능을 균형 잡도록 튜닝할 수 있어요.

이 튜닝 설정은 percentageOfNodesToScore를 통해 구성합니다. 이 KubeSchedulerConfiguration 설정은 클러스터에서 스케줄링할 노드의 임계값을 결정합니다.

임계값 설정 (Setting the threshold)

percentageOfNodesToScore 옵션은 0~100 사이의 정수 값을 받아요. 값 0은 kube-scheduler가 컴파일된 기본값을 사용해야 함을 나타내는 특수 숫자입니다. 100 이상으로 설정하면 kube-scheduler는 100을 설정한 것처럼 동작해요.

값을 바꾸려면 kube-scheduler 설정 파일을 편집하고 스케줄러를 재시작하세요. 많은 경우 설정 파일은 /etc/kubernetes/config/kube-scheduler.yaml에 있습니다.

변경 후 다음을 실행해 kube-scheduler 컴포넌트가 건강한지 확인할 수 있어요:

kubectl get pods -n kube-system | grep kube-scheduler

노드 점수화 임계값 (Node scoring threshold)

스케줄링 성능을 높이기 위해, kube-scheduler는 충분한 적합한 노드를 찾으면 검색을 멈출 수 있어요. 대규모 클러스터에서 이는 모든 노드를 고려하는 순진한 접근보다 시간을 절약합니다.

몇 개면 충분한지 임계값을 클러스터 전체 노드의 정수 백분율로 지정해요. kube-scheduler는 이를 정수 개수의 노드로 변환합니다. 스케줄링 중에 kube-scheduler가 설정된 백분율을 초과할 만큼의 적합한 노드를 식별하면, 더 많은 적합한 노드를 찾는 것을 멈추고 점수화 단계로 넘어갑니다.

기본 임계값 (Default threshold)

임계값을 지정하지 않으면, 쿠버네티스는 선형 공식으로 값을 계산합니다. 100노드 클러스터에서는 50%, 5000노드 클러스터에서는 10%를 산출해요. 자동 값의 하한은 5%입니다.

즉 클러스터가 아무리 커도 kube-scheduler는 항상 최소 5%는 점수화합니다. 단, percentageOfNodesToScore를 5보다 작게 명시적으로 설정한 경우는 예외예요.

클러스터의 모든 노드를 점수화하려면 percentageOfNodesToScore를 100으로 설정하세요.

예시 (Example)

percentageOfNodesToScore를 50%로 설정한 설정 예시:

apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
algorithmSource:
  provider: DefaultProvider

...

percentageOfNodesToScore: 50

percentageOfNodesToScore 튜닝 (Tuning percentageOfNodesToScore)

percentageOfNodesToScore는 1~100 사이의 값이어야 하며, 기본값은 클러스터 크기에 따라 계산됩니다. 또한 하드코딩된 최소값 100노드가 있어요.

참고: 적합한 노드가 100개 미만인 클러스터에서는, 스케줄러의 검색을 조기 종료할 만큼 적합한 노드가 없으므로 스케줄러는 여전히 모든 노드를 검사합니다.

작은 클러스터에서 percentageOfNodesToScore를 낮은 값으로 설정하면, 그 변경은 효과가 없거나 거의 없어요.

클러스터에 수백 개 이하의 노드가 있다면 이 설정을 기본값으로 두세요. 변경해도 스케줄러 성능이 크게 개선되지는 않을 가능성이 높아요.

이 값을 설정할 때 중요한 세부사항은, 클러스터의 노드 중 더 적은 수가 적합성 검사 대상이 되면 특정 Pod에 대해 점수화 단계를 거치지 않는 노드가 생긴다는 점입니다. 결과적으로 그 Pod를 실행하기에 더 높은 점수를 줄 수 있는 노드가 점수화 단계에 아예 넘어가지 않을 수도 있어요. 이는 이상적이지 않은 배치로 이어질 수 있습니다.

percentageOfNodesToScore를 매우 낮게 설정하면 kube-scheduler가 잦고 좋지 않은 Pod 배치를 하게 되므로 피하세요. 스케줄러의 처리량이 애플리케이션에 매우 중요하고 노드 점수가 중요하지 않은 경우가 아니라면, 백분율을 10% 아래로 설정하지 마세요. 다시 말해, 적합한 노드라면 어느 노드든 Pod를 실행하기를 선호한다는 뜻이에요.

스케줄러가 노드를 반복하는 방식 (How the scheduler iterates over Nodes)

이 섹션은 이 기능의 내부 동작을 이해하려는 사람들을 위한 것입니다.

클러스터의 모든 노드에 Pod 실행 후보로 고려될 공정한 기회를 주기 위해, 스케줄러는 라운드 로빈(round robin) 방식으로 노드를 반복합니다. 노드가 배열에 있다고 상상해 보세요. 스케줄러는 배열의 시작에서 출발해 percentageOfNodesToScore에 지정된 충분한 노드를 찾을 때까지 노드의 적합성을 검사합니다. 다음 Pod를 위해서는 이전 Pod의 적합성 검사를 멈춘 노드 배열의 지점에서 검사를 이어갑니다.

노드가 여러 존에 있으면 스케줄러는 다양한 존의 노드를 반복해, 서로 다른 존의 노드가 적합성 검사에서 고려되도록 합니다. 예를 들어 두 존에 여섯 노드가 있다고 해볼게요:

Zone 1: Node 1, Node 2, Node 3, Node 4
Zone 2: Node 5, Node 6

스케줄러는 이 순서로 노드의 적합성을 평가합니다:

Node 1, Node 5, Node 2, Node 6, Node 3, Node 4

모든 노드를 돌고 나면 Node 1로 돌아갑니다.

기회적 배치 (Opportunistic Batching) 활성화

기능 상태: Kubernetes v1.35 [beta](기본 활성화)

대규모 워크로드를 스케줄링할 때 Pod들은 종종 동일한 스케줄링 제약을 가지며, 스케줄러가 같은 작업을 반복해서 수행해야 해요. Opportunistic Batching(기회적 배치) 기능은 스케줄링 사이클 사이에 필터링·점수화 결과를 재사용할 수 있게 해줘 스케줄링 과정을 크게 가속합니다.

재점수화(rescoring)가 있으면 스케줄러는 그런 상황에서 배치를 계속할 수 있어요. 다음 Pod가 이전에 선택된 노드에 여전히 들어갈 수 있으면, 스케줄러는 그 노드의 점수를 갱신해 캐시된 후보 목록에 다시 넣습니다. 재점수화가 성공하지 못하면 기존 동작으로 폴백하고 캐시를 비웁니다.

기본적으로 이 기능은 다음과 같이 동작합니다:

  1. 스케줄러가 pod-1을 스케줄링하고 스케줄링 결과를 캐시합니다.
  2. 스케줄러가 캐시된 결과로 pod-2, pod-3, ... 을 스케줄링합니다.
  3. 캐시는 0.5초 뒤 만료됩니다. 스케줄러는 다음 Pod를 스케줄링하며 새 캐시를 만듭니다.

동일한 스케줄링 제약을 가진 Pod는 스케줄링 사이클에 연속으로 와야 해요. 스케줄러가 다른 제약을 가진 Pod를 스케줄링하면, 캐시는 사용되지 않고 새 것으로 교체됩니다.

이 배치 스케줄링은 다음 조건의 특정 Pod에 적용합니다:

  1. 인터-Pod 어피니티/안티-어피니티가 없을 것
  2. 토폴로지 분산 제약이 없을 것
  3. DRA가 없을 것(즉 Resource Claim이 없을 것)
  4. DRA가 지원하는 확장 리소스를 요청하지 않을 것

또한 이 기능을 활성화하려면 스케줄러 설정이 다음을 충족해야 해요:

  1. 기본 토폴로지 분산을 비활성화(빈 값으로 설정)
  2. InterPodAffinityArgsIgnorePreferredTermsOfExistingPodstrue로 설정해 배치를 더 효율적으로

다음 사항에 주의하세요:

  1. 기존 Pod가 스케줄링된 Pod의 라벨과 일치하는 pod 어피니티 제약을 쓰면, 이 기능이 이점을 주지 못할 수 있습니다.
  2. 커스텀 플러그인을 쓰면 Signature 확장 지점을 구현해야 해요.

제한과 조건은 향후 릴리스에서 진화할 것으로 예상됩니다.

더 알아보기 (Learn more)