파드 서비스 품질(QoS) 클래스
파드 서비스 품질(QoS) 클래스 (pod-qos)
이 페이지는 Kubernetes의 _서비스 품질(QoS) 클래스_를 소개하고, 파드 안의 컨테이너에 지정하는 리소스 제약의 결과로 Kubernetes가 각 파드에 어떻게 QoS 클래스를 할당하는지 설명해요. Kubernetes는 이 분류에 의존해서...
서비스 품질 클래스
Kubernetes는 실행하는 파드를 분류해서 각 파드를 특정 _서비스 품질(QoS) 클래스_에 배정해요. Kubernetes는 이 분류를 사용해서 서로 다른 파드가 어떻게 처리되는지에 영향을 줘요. Kubernetes는 파드 안 컨테이너의 리소스 **요청(request)**과 그 요청이 리소스 **제한(limit)**과 어떻게 관련되는지에 기반해 이 분류를 해요.
이것을 QoS 클래스라고 불러요. Kubernetes는 구성 요소 컨테이너의 리소스 요청과 제한을 기반으로 모든 파드에 QoS 클래스를 할당해요. QoS 클래스는 노드 압박(Node Pressure)을 겪는 노드에서 어떤 파드를 축출(evict)할지 결정하는 데 사용돼요. 가능한 QoS 클래스는 Guaranteed, Burstable, BestEffort 세 가지예요. 노드의 리소스가 떨어지면...
Guaranteed
기준
- 파드의 모든 컨테이너는 0보다 큰 메모리 제한과 메모리 요청을 가져야 해요.
- 파드의 모든 컨테이너에 대해 메모리 제한은 메모리 요청과 같아야 해요.
- 파드의 모든 컨테이너는 0보다 큰 CPU 제한과 CPU 요청을 가져야 해요.
대신 파드가 Pod 수준 리소스를 사용한다면:
기능 상태: Kubernetes v1.34 [beta] (기본적으로 활성화됨)
- 파드는 Pod 수준 메모리 제한과 메모리 요청을 가져야 하고, 그 값은 같아야 해요.
- 파드는 Pod 수준 CPU 제한과 CPU 요청을 가져야 하고, 그 값은 같아야 해요.
Burstable
Burstable 파드는 요청에 기반한 어떤 하한 리소스 보장을 갖지만, 특정 제한을 요구하지는 않아요. 제한이 지정되지 않으면 노드의 용량과 동등한 제한이 기본값이 돼서, 리소스를 사용할 수 있다면 파드가 리소스를 유연하게 늘릴 수 있어요.
기준
다음의 경우 파드에 Burstable QoS 클래스가 부여돼요.
- 파드가 QoS 클래스
Guaranteed의 기준을 충족하지 못하는 경우 - 파드의 최소 하나의 컨테이너가 메모리 또는 CPU 요청이나 제한을 가지거나, 파드가 Pod 수준 메모리 또는 CPU 요청이나 제한을 가지는 경우
BestEffort
BestEffort QoS 클래스의 파드는 다른 QoS 클래스의 파드에 특별히 할당되지 않은 노드 리소스를 사용할 수 있어요. 예를 들어 kubelet에 16개의 CPU 코어가 있고, 4개의 CPU 코어를 Guaranteed 파드에 할당했다면, BestEffort QoS 클래스의 파드는 남은 12개의 CPU 코어 중 얼마든지 사용하려고 시도할 수 있어요. kubelet은 노드가 리소스 압박을 받으면 BestEffort 파드를 우선 축출해요.
기준
파드가 Guaranteed나 Burstable 기준을 모두 충족하지 못하면 BestEffort QoS 클래스를 가져요. 다시 말해 파드는 컨테이너 중 어느 것도 메모리 제한이나 메모리 요청이 없고, 컨테이너 중 어느 것도 CPU 제한이나 CPU 요청이 없으며, 파드도 Pod 수준 메모리나 CPU 제한 또는 요청이 없을 때만 BestEffort가 돼요. 파드 안의 컨테이너는 다른 리소스(CPU나 메모리가 아닌)를 요청할 수 있고 여전히 BestEffort로 분류돼요.
cgroup v2를 이용한 메모리 QoS
메모리 QoS는 cgroup v2의 메모리 컨트롤러를 사용해서 Kubernetes에서 메모리 스로틀링과 보호를 관리해요. 파드의 QoS 클래스를 사용해서 어떤 cgroup 설정을 적용할지 결정하지만, 이것은 별도의 opt-in 기능이에요. 메모리 QoS를 비활성화해도 파드가 어떻게 분류되는지는 바뀌지 않아요.
메모리 스로틀링
Burstable 파드의 경우 kubelet은 워크로드가 하드 제한(memory.max)에 도달하기 전에 메모리 할당을 스로틀하도록 memory.high를 설정해요. 스로틀링 임계값은 다음과 같이 계산돼요.
memory.high = requests + memoryThrottlingFactor * (limits - requests)
Guaranteed 파드는 요청이 제한과 같으므로 memory.high를 받지 않아요. BestEffort 파드는 요청이나 제한이 없으므로 memory.high를 받지 않아요.
메모리 예약 구성
None(기본값): kubelet이 컨테이너와 파드에memory.min또는memory.low를 설정하지 않아요. 커널에 의해 메모리가 하드 락되지 않아요.TieredReservation: kubelet이 파드의 QoS 클래스에 기반해 계층적 메모리 보호를 설정해요.- Guaranteed 파드:
memory.min이 메모리 요청으로 설정돼요. 커널은 어떤 경우에도 이 메모리를 회수하지 않아요. - Burstable 파드:
memory.low가 메모리 요청으로 설정돼요. 커널은 이 메모리를 우선적으로 유지하지만 극심한 압박에서는 회수할 수 있어요. - BestEffort 파드: 메모리 보호가 설정되지 않아요.
- Guaranteed 파드:
시스템 요구 사항
메모리 QoS는 cgroup v2를 사용하는 Linux를 요구해요. 커널 5.9 이상이 권장되는데, 이전 커널의 memory.high 스로틀링은 알려진 라이브락(livelock) 버그를 촉발시킬 수 있기 때문이에요. MemoryQoS 기능 게이트가 이전 커널에서 활성화되면 kubelet은 경고를 기록해요.
QoS 클래스와 무관한 동작
- kube-scheduler는 어떤 파드를 선점할지 선택할 때 QoS 클래스를 고려하지 않아요. 선점은 클러스터에 정의한 모든 파드를 실행할 리소스가 충분하지 않을 때 발생할 수 있어요.
- QoS 클래스는 파드가 생성될 때 결정되며 파드의 수명 동안 변하지 않아요. 나중에 다른 QoS 클래스가 되는 인플레이스 리사이즈를 시도하면 admission이 리사이즈를 거부해요.