쿠버네티스 파드 우선순위 (PriorityClass)

온프레미스 K8s 클러스터 구축하기 - 이론 및 검증 3 (작성 중...)
이민석's avatar
Apr 08, 2025
쿠버네티스 파드 우선순위 (PriorityClass)

💡

PriorityClass 이론 및 실습을 포함한 문서입니다.

🚫

현재 이 문서의 B.1. ~ B.6. 은 작성이 대기 중인 항목입니다.

A. PriorityClass 이론

A.1. PriorityClass 기본 개념

PriorityClass[A.1-1]는 Pod의 중요도를 상대적으로 표현하는데 사용됩니다.
kube-scheduler[A.1-2]는 Pod를 스케줄링 못하면, PriorityClass로 해결합니다.

  1. PriorityClass 값이 낮은 파드를 선점(축출, evict) 한다.

  2. PriorityClass 값이 높은 파드가 스케줄링할 수 있게 만들어줍니다.

PriorityClass핵심 옵션은 value, globalDefault, preemptionPolicy 등 입니다.
(옵션에 따라서 작동 원리는 문서 아래에서 후술하도록 하겠습니다.)

option

default

supported

value

0

-2,147,483,648 ~ 1,000,000,000
(32-bit integer)

globalDefault

false

true, false

preemptionPolicy

PreemptLowerPriority

PreemptLowerPriority, Never

[명령어 1] PriorityClass, Pod 샘플링
--- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: sample-priority value: 1000000 globalDefault: false preemptionPolicy: PreemptLowerPriority description: "sample-priority" --- apiVersion: v1 kind: Pod metadata: name: sample-pod spec: priorityClassName: sample-priority containers: - name: nginx image: nginx

예를 들어, 온프레미스 클러스터[A.1-3]는 2개의 PriorityClass가 자동으로 생깁니다.
(32-bit integer에서 10억보다 큰 자연수는 시스템 내장 PriorityClass에 예약됨)

option

system-cluster-critical

system-node-critical

value

2,000,000,000

2,000,001,000

globalDefault

false

false

preemptionPolicy

PreemptLowerPriority

PreemptLowerPriority

[명령어 2] 기본 PriorityClass (kubeadm)

1. PriorityClass 리스트 조회하기

kubectl get priorityclass -A
NAME VALUE GLOBAL-DEFAULT AGE system-cluster-critical 2000000000 false 38d system-node-critical 2000001000 false 38d

2. PriorityClass 디테일 조회하기

kubectl get priorityclass system-cluster-critical -o yaml kubectl get priorityclass system-node-critical -o yaml
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass description: # ... metadata: name: system-cluster-critical # ... preemptionPolicy: PreemptLowerPriority value: 2000000000 apiVersion: scheduling.k8s.io/v1 kind: PriorityClass description: # ... metadata: name: system-node-critical # ... preemptionPolicy: PreemptLowerPriority value: 2000001000

이들은 컨트롤 플레인 및 워커 노드의 필수 컴포넌트(오브젝트)에서 사용됩니다.

option

system-cluster-critical

system-node-critical

example

etcd, kube-apiserver, kube-scheduler, kube-controller-manager, kube-proxy, …, kube-flannel-ds

coredns, metrics-server

[명령어 3] PriorityClass 사용 중인 파드 찾기

1.

kubectl get pods -A -o json | jq -r '.items[] | select(.spec.priorityClassName=="system-cluster-critical") | [.metadata.namespace, .metadata.name] | @tsv' kube-system coredns-7c65d6cfc9-g2qxv kube-system coredns-7c65d6cfc9-sscfz kube-system metrics-server-8dd4f4fd6-mwm66

2.

kubectl get pods -A -o json | jq -r '.items[] | select(.spec.priorityClassName=="system-node-critical") | [.metadata.namespace, .metadata.name] | @tsv' kube-flannel kube-flannel-ds-5jww4 kube-system etcd-cp-k8s kube-system kube-apiserver-cp-k8s kube-system kube-controller-manager-cp-k8s kube-system kube-proxy-lpjh5 kube-system kube-scheduler-cp-k8s

A.2. PriorityClass value 범위에 대한 내용

PriorityClass value는 32-bit integer 자료형을 사용합니다.
따라서 -2,147,483,648 ~ 2,147,483,647의 값을 가질 수 있어야 합니다.
하지만 실제로는 -2,147,483,648 ~ 1,000,000,000의 값을 할당할 수 있습니다.

1,000,000,000 ~ 2,147,483,647 범위는 시스템에서 예약하고 있기 때문입니다.

A.3. PriorityClass globalDefault: true가 없는 경우

PriorityClass globalDefault는 bool 자료형을 사용합니다.
기본값과 시스템 PriorityClass는 모두 false를 가지고 있습니다.
따라서 별도의 설정이 없다면 globalDefault: true인 PriorityClass가 없습니다.

이때, 파드는 기본적으로 priorityClassName: null, priorityValue: 0을 가집니다.

A.4. PriorityClass PreemptionPolicy 두 가지 옵션

PriorityClass 기본 개념[A.4-1]에서는 선점(축출, evict/preempt)을 말했습니다.
이는 기본값인 preemptionPolicy: PreemptLowerPriority 해당하는 작동입니다.

만약 preemptionPolicy: Never을 사용한다면, 기본 파드를 축출하지 않습니다.
(즉, 기능 자체가 Require보다는 Prefer에 가깝게 변하는 것을 의미합니다.)

💡

운영 중인 서비스의 특징을 고려한 정책* 차원의 문제라고 생각합니다. 예를 들어, 고객 대상 서비스(api, batch)에는 PreemptLowerPriority를 할당하고 사내 대상 서비스(ci/cd, bi) 등에서는 Never 등을 할당하는 등이 있습니다.

💡

만약 CI/CD 파이프라인이 Affinity, Taints 등으로 격리되어 있다면 파이프라인 간에 경합으로 인한 축출이 발생하지 않도록 Never 옵션을 쓰는 것도 좋아보입니다.

B. PriorityClass 테스트

B.0. 환경 확인

온프레미스 클러스터[A.1-3]를 사용하고 있으며 별도 설정을 하지 않은 상태입니다.
따라서 아래와 같은 스펙의 환경에서 PriorityClass 테스트를 진행하고자 합니다.

  1. maxPods : 110

  2. vCPU : 8

  3. MEM : 7.64 Gi

  4. Disk : 232.2 Gi

[명령어 4] 실습환경 시스템 스펙 확인하기

1. 노드 조회하기

kubectl get nodes
NAME STATUS ROLES AGE VERSION cp-k8s Ready control-plane 39d v1.31.6

2. 노드 allocatable 조회하기

kubectl get nodes cp-k8s -o yaml | grep allocatable -A 6
allocatable: cpu: "8" ephemeral-storage: "225337595531" hugepages-1Gi: "0" hugepages-2Mi: "0" memory: 7915344Ki pods: "110"

3. 노드 capacity 조회하기

kubectl get nodes cp-k8s -o yaml | grep capacity -A 6
capacity: cpu: "8" ephemeral-storage: 244506940Ki hugepages-1Gi: "0" hugepages-2Mi: "0" memory: 8017744Ki pods: "110"

현재 시스템의 주요 매트릭(지표)는 다음과 같이 보여집니다.

  1. nowPods : 45

  2. CPU(cores) : 334m

  3. CPU% : 4%

  4. MEMORY : 2965Mi

  5. MEMORY : 38%

[명령어 5] 실습환경 시스템 매트릭(지표) 확인하기

1. 시스템 사용량 확인하기

kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% cp-k8s 334m 4% 2965Mi 38%

<2. 시스템 파드 할당량 확인하기

kubectl get pods -A --no-headers | wc -l
45

그리고 nowPods 중에서도 시스템 점유분을 구분하면 다음과 같습니다.

  1. 시스템 점유분 : 9 (value: 2,000,000,000 혹은 2,000,001,000)

  2. 그 외 : 36 (value: 0)

[명령어 6] Pod 별 시스템 점유분 구분 (Priority.Value)

1. 시스템 점유분 수량

kubectl get pods -o custom-columns=NAME:.metadata.name,PRIORITY:.spec.priority,PRIORITY_CLASS:.spec.priorityClassName -A --no-headers | grep system- | wc -l
9

2. 일반 점유분 수량

kubectl get pods -o custom-columns=NAME:.metadata.name,PRIORITY:.spec.priority,PRIORITY_CLASS:.spec.priorityClassName -A --no-headers | grep -v system- | wc -l
36

B.1. PreemptLowerPriority가 파드를 밀어내는 방식 검증

B.2. Value가 다른 PreemptLowerPriority 끼리 경합 검증

B.3. Value가 같은 PreemptLowerPriority 끼리 경합 검증

B.4. Never가 파드를 밀어내는 방식 검증

B.5. Never과 Rollout이 공존하는 상황의 검증

B.6. Value가 파드 생성 순서에 미치는 영향 검증

참고 자료

  1. T Story (악분의 블로그) - pod 우선순위클래스(PriorityClass)

  2. Velog (hoju.log) - Pod Priority, Preemption 구성하기

Share article

Unchaptered