Kubernetes 1.26에서 Scheduling gates라는 새로운 파드 옵션이 도입되었습니다. 이 옵션은 파드를 Readiness 상태로 두어, 스케줄러는 해당 파드를 무시하며 궁극적으로 스케줄링 주기의 속도를 향상시킬 수 있습니다. 그렇다면 스케줄링 게이트란 무엇일까요? 먼저, 파드의 스케줄링 방식을 알아봅시다.

Pod 스케줄링

파드는 쿠버네티스에서 가장 작은 컴퓨팅 단위입니다. 프로젝트가 커지고 세분화될수록 파드의 수는 많아지는데요, 파드의 수가 방대해질수록 스케줄링의 중요도는 증가합니다. 스케줄링에 대해 알아보면, Node affinity 이나 Selector 를 사용하여 스케줄링 조건을 추가할 수 있지만 기본 방식은 FCFS 방식입니다.

하지만 스케줄링을 통해 노드가 결정되면 끝나지만 외부 이벤트를 통해 노드를 찾지 못해 스케줄링 프로세스가 계속 반복될 수 있습니다. 아래의 그림과 같이 파드가 생성되면 스케줄러는 지속적으로 적합한 노드를 찾습니다. 이런 과정은 노드를 찾거나 파드가 삭제될 때까지 계속 진행됩니다. 외부 이벤트로 차단된 파드와 같이 몇몇 파드는 오랜 기간 준비상태를 유지하며 스케줄링 사이클에 버려집니다. 이런 파드들로 인해 스케줄링 주기는 20ms 이상 걸릴 수 있고 스케줄링 성능에 큰 영향을 미치게 됩니다.

스케줄링 게이트는 이런 문제를 해결해 줄 수 있습니다.

  • 기존
photo | 인포그랩 GitLab | 인포그랩 GitLab
  • Pod Scheduling Readiness
photo | 인포그랩 GitLab | 인포그랩 GitLab

Scheduling gate

스케줄링 게이트는 새로 생성된 파드가 작동할 준비가 되지 않았음을 알리고 스케줄러는 이 파드를 무시하므로 불필요한 스케줄링 시도를 줄입니다. Cluster Autoscaler에서도 동일합니다. 이런 과정은 API 서버의 호출 없이 일어나, 부하를 유발하지 않습니다. 게이트를 지우는 것은 외부 컨트롤러가 합니다. 여러 스케줄링 게이트가 있다면 모두 삭제되어야 파드는 스케줄링 됩니다. 그렇다면, 스케줄링 게이트는 어떻게 사용할까요

photo | 인포그랩 GitLab | 인포그랩 GitLab

사용방법

먼저, API 서버와 스케줄러에 먼저 스케줄링 게이트를 사용하기 위해서는 API 서버와 스케줄러의 feature gate PodSchedulingReadiness  옵션을 허용해야 합니다. 파드에서는 spec 부분에 schedulingGates 항목을 추가해야 합니다. API 서버와 스케줄러는 다음과 같이 기존의 .yaml 파일을 이용합니다.

  • API server
spec:
containers:
- command:
- kube-apiserver
...
- --feature-gates=PodReadinessGates=true
  • Scheduler
spec:
containers:
- command:
- kube-scheduler
...
- --feature-gates=PodReadinessGates=true

API 서버와 스케줄러는 작동 중인 환경에서 수동으로 바꿀 수 있으나 운영환경에서는 kubeadm의 도움을 받아 설정하는 것을 권장합니다.

  • Pod

아래와 같이 파드의 .yaml 파일에서 스케줄링 게이트 필드를 추가하면 됩니다. 여러 개를 추가할 수 있지만, 모든 항목이 제거되어야 다시 스케줄링 됩니다.

apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
schedulingGates:
- name: foo
- name: bar
containers:
- name: pause
image: registry.k8s.io/pause:3.6
$kubectl get pod test-pod
NAME READY STATUS RESTARTS AGE
test-pod 0/1 SchedulingGated 0 7s

위의 명령어를 보면, kubectl get pod test-pod를 통해 상태를 확인하여 파드가 SchedulingGated 상태로 작동되지 않은 것을 확인할 수 있습니다.

$kubectl get pod test-pod -o jsonpath='{.spec.schedulingGates}’
[{"name":"foo"},{"name":"bar"}]

현재 실행 중인 파드의 스케줄링 게이트 필드를 확인하고 싶다면 kubectl get pod test-pod -o jsonpath='{.spec.schedulingGates}’ 명령어를 통해 내용을 확인할 수 있습니다.

관련 지표

아래의 명령어를 통해 지표를 확인할 수 있습니다.

$scheduler_pending_pods{queue="gated"}
10

스케줄링 큐 대기열에서 “gated”에 의해 대기 중인 포드의 수를 의미합니다. 포드의 수가 많아지면 롤백을 고려해야 합니다.

$scheduler_plugin_execution_duration_seconds{plugin="SchedulingGates"}
0.023

스케줄링 게이트의 성능을 평가합니다. 단위는 초단위이며 꾸준히 0.1s를 초과한다면 롤백을 고려해야 합니다.

사용예시

대표 사례로, 동적 할당량 관리와 관련한 예시가 있습니다.

쿠버네티스에서는 resourceQuota를 지원하지만, API 서버는 파드 생성을 시도할 때만 옵션을 적용하여 자원 할당량을 초과한 파드는 대기열 상태로 가지 않고, 단순히 거부됩니다. 만약 해당 파드가 필요하다면, 유저는 계속해서 생성을 시도하고 이는 API 서버와 스케줄러에 부하를 유발합니다.

이제, 스케줄링 게이트를 통해 이 문제를 해결할 수 있습니다. 먼저, 파드에 모두 게이트를 추가한 뒤 관리자는 파드를 시작할 할당량이 있을 때만 게이트를 제거합니다. 이로써 자원이 있을 때 자동으로 파드가 생성되어 문제를 해결할 수 있습니다.

맺음말

지금까지 파드의 스케줄링 방식과 Pod Scheduling Readiness에 대해 알아봤습니다. 외부 이벤트에 막혀 버려지는 파드들로 인해 부하가 발생합니다. 파드를 Readiness 상태로 두어 스케줄러가 일부 파드를 무시하도록 합니다. 이로써 문제를 해결하여 불필요한 과정을 피하고 스케줄링 주기를 최적화할 수 있습니다.

인포그랩은 GitLab 및 DevOps에 대한 맞춤 기술 지원을 제공합니다.GitLab(Omnibus/Cloud Native Hybrid) 구축 관련한 지원이 필요하시면 문의하기 로 연락 주십시오.

<참고자료>

KEP-3521: Pod Scheduling Readiness

Kubernetes Pod Scheduling Readiness

Kubernetes 1.26