
💡
PriorityClass 이론 및 실습을 포함한 문서입니다.
🚫
현재 이 문서의 B.1. ~ B.6. 은 작성이 대기 중인 항목입니다.
A. PriorityClass 이론
A.1. PriorityClass 기본 개념
PriorityClass[A.1-1]는 Pod의 중요도를 상대적으로 표현하는데 사용됩니다.
kube-scheduler[A.1-2]는 Pod를 스케줄링 못하면, PriorityClass로 해결합니다.
PriorityClass 값이 낮은 파드를 선점(축출, evict) 한다.
PriorityClass 값이 높은 파드가 스케줄링할 수 있게 만들어줍니다.
PriorityClass핵심 옵션은 value, globalDefault, preemptionPolicy 등 입니다.
(옵션에 따라서 작동 원리는 문서 아래에서 후술하도록 하겠습니다.)
option | default | supported |
---|---|---|
value | 0 | -2,147,483,648 ~ 1,000,000,000 |
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-mwm662.
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-k8sA.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 테스트를 진행하고자 합니다.
maxPods : 110
vCPU : 8
MEM : 7.64 Gi
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"
현재 시스템의 주요 매트릭(지표)는 다음과 같이 보여집니다.
nowPods : 45
CPU(cores) : 334m
CPU% : 4%
MEMORY : 2965Mi
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 중에서도 시스템 점유분을 구분하면 다음과 같습니다.
시스템 점유분 : 9 (value: 2,000,000,000 혹은 2,000,001,000)
그 외 : 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