Red Hat Blog를 보다가 관심 가는 글이 보여서 AI번역+약간 교정해 보았습니다.
출처: https://developers.redhat.com/blog/2025/01/31/memory-management-openshift-virtualization
개요
OpenShift Virtualization을 사용하면 베어 메탈 노드를 사용하여 온프레미스 또는 클라우드에서 OpenShift에서 가상 머신(VM)을 실행할 수 있습니다.
기본적으로 Kubernetes와 OpenShift는 메모리를 처리하는 데 있어 매우 간단한 접근 방식을 사용합니다. 즉, 워크로드가 메모리를 요청한 다음 해당 메모리를 사용할 수 있습니다.
하지만 프로덕션 클러스터를 운영할 때는 세부 사항이 중요합니다. 선장은 선박을 조종하기 위해 선박의 모든 세부 사항(운동량, 폭, 길이 등)을 이해해야 합니다.
이 글에서는 스케줄링 과정에서 메모리가 어떻게 제공되고, 소비되고, 고려되는지, 그리고 메모리를 효율적으로 사용하기 위한 다양한 기법들을 살펴봅니다. 이러한 세부 정보는 더 많은 통찰력을 제공하고 사용 사례에 맞게 메모리를 최적화할 수 있도록 제공됩니다.
핵심 내용은 이 글의 맨 마지막에 있는 요약에서 확인할 수 있습니다.
메모리 용량 및 메모리 요청
노드 메모리 용량
Kubernetes의 주요 측면이자 OpenShift의 스케줄링 개념의 주요 측면은 리소스입니다 .
OpenShift의 모든 컨테이너는 아주 작은 양일지라도 CPU와 메모리 리소스를 소모합니다. 결국 모든 컨테이너는 노드 수준 프로세스에 매핑되고, 이를 실행하려면 CPU와 메모리가 필요하기 때문입니다.
이것이 작동하려면 Kubernetes에 두 가지가 필요합니다.
- 노드가 (메모리) 리소스 용량을 보고합니다.
- 특정 양의 (메모리) 리소스를 요청하는 컨테이너
Pod의 컨테이너에 필요한 리소스의 남은 용량이 충분한 경우 Pod를 노드에 예약할 수 있습니다. 노드는 남은 용량을 할당 가능 용량으로 보고합니다.
Node Allocatable = Node Capacity - (Sum of container memory requests on this node)
Example:
Node Capacity = 10G
Sum of container memory requests = 8 x 1G
= 8G
Node Allocatable = 10G - 8G
= 2G이러한 세부 정보는 Kubernetes API의 Node 객체에도 표시됩니다.
kind: Node
apiVersion: v1
metadata:
name: qe-20.lab.eng.example.com
spec: {}
status:
allocatable:
memory: 584594240Ki # 558 GiB
cpu: 159500m
capacity:
memory: 1582394688Ki # 1474 GiB
cpu: '160'메모리 리소스의 경우, 노드의 메모리 용량은 물리적인 RAM 용량만 보고된다는 점에 유의해야 합니다. SWAP, 압축 RAM(ZRAM) 등은 이 용량에 포함되지 않습니다.
두 번째로 중요한 점은 Node 객체가 일반적으로 실제 RAM 용량보다 약간 낮은 값을 보고한다는 것입니다. 이는 일부 용량이 운영 체제와 하이퍼바이저 자체에 예약되어 있기 때문입니다.
우리의 뇌와 눈이 기억할 수 있는 또 다른 것을 제공하기 위해 이것을 시각화해 보겠습니다.

지금까지 얻은 중요한 내용은 다음과 같습니다.
- 노드는 메모리 리소스를 통해 RAM 용량을 보고합니다.
- 워크로드가 메모리 리소스를 요청하고 있습니다.
- Kubernetes 스케줄러는 리소스 요청을 기반으로 합니다.
- Kubernetes 스케줄러는 생성 시에 포드를 한 번만 스케줄링합니다.
가상 머신 메모리 요청
일반적으로는 중요하지 않지만, 이 맥락에서 OpenShift에서 가상 머신은 결국 컨테이너 내부의 프로세스로 실행되고 Pod 내부에서 실행된다는 점을 알아두는 것이 중요합니다. 이 Pod를 virt-launcher라고 합니다. OpenShift와 Kubernetes의 원자적 컴퓨팅 단위가 Pod이기 때문입니다.
이 Pod는 OpenShift Virtualization의 구성 요소 중 하나인 KubeVirt 에 의해 생성 및 관리되며, 수명 주기도 관리됩니다 . KubeVirt는 virt-launcher Pod의 소유자이므로 메모리 요청 설정도 담당합니다.
자세히 살펴보겠습니다.
사용자가 u1.2xlarge 인스턴스 유형을 사용하여 다음 가상 머신을 생성했습니다.
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: fedora-ivory-ermine-40
spec:
instancetype:
name: u1.2xlarge
preference:
name: fedora
running: true
template:
spec:
domain:
resources: {}이 가상 머신을 시작하면 KubeVirt가 실행 중인 VM을 반영하는 VirtualMachineInstance를 생성하여 인스턴스 유형을 특정 리소스 요구 사항에 맞게 확장합니다. 이 경우, u1.2xlarge는 32GiB의 (가상) 메모리를 가진 VM으로 확장됩니다.
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstance
metadata:
name: fedora-ivory-ermine-40
spec:
domain:
memory:
guest: 32Gi # 32 GiB
resources:
requests:
memory: 32Gi이 VirtualMachineInstance는 KubeVirt에 의해 거의 즉시 Pod로 변환됩니다.
kind: Pod
apiVersion: v1
metadata:
generateName: virt-launcher-fedora-ivory-ermine-40-
name: virt-launcher-fedora-ivory-ermine-40-h4bg5
spec:
containers:
- resources:
requests:
cpu: 800m
memory: '34739322881' # 32.35 GiB
name: computePod와 VMI 간의 숫자를 비교할 때, 가상 머신을 호스팅하는 Pod가 게스트에 대해 정의한 메모리(32GiB)보다 약간 더 많은 메모리(32.35GiB)를 요청하는 것을 알 수 있습니다.
KubeVirt는 캐시와 같은 하이퍼바이저 관련 오버헤드와 가상 머신 런타임(qemu)을 위한 충분한 공간을 확보하기 위해 이러한 작은 오버헤드를 계산합니다.
참고 사항: 기본적으로 64GiB의 두 VM은 128GiB RAM이 있는 노드에 맞지 않습니다. 노드의 메모리 리소스 용량이 RAM 용량보다 적고, Pod의 메모리 요청이 가상 머신 게스트 메모리(64GiB)보다 높기 때문입니다.
우리의 뇌와 눈이 기억할 수 있는 또 다른 것을 제공하기 위해 이것을 시각화해 보겠습니다.

지금까지 얻은 중요한 내용은 다음과 같습니다.
- OpenShift가 Virtual Machines을 실행할 수 있더라도 원자 컴퓨팅 유닛은 여전히 Pod입니다.
- 가상 머신은 Pod 내부에서 실행됩니다.
- KubeVirt는 VM 정의에 따라 Pod를 구축합니다.
- 하이퍼바이저 관련 예약으로 인해 포드가 VM에 필요한 것보다 약간 더 많은 메모리를 요청합니다.
스케줄러 대 커널
메모리 요청은 스케줄러에게 특정 워크로드를 위해 노드에 지정된 양의 메모리를 예약하도록 지시합니다. 스케줄러는 워크로드를 위해 메모리를 예약합니다.
하지만 이 예약은 스케줄러 수준에서만 논리적인 예약이며, 노드 수준에서는 이 예약이 강제로 적용되지 않습니다.
4GiB의 메모리를 요청하는 작업 부하가 주어지면 스케줄러는 할당 가능한 용량을 4GiB만큼 줄여서 노드에서 4GiB의 메모리를 예약합니다.
해당 노드에서 워크로드가 실행되면 노드는 4GiB 예약을 적용하지 않으며 워크로드는 이 4GiB보다 많거나 적게 사용할 수 있습니다.
제한
쿠버네티스와 오픈시프트에 대해 읽어보셨다면 메모리, 리소스 등의 맥락에서 ‘제한(limits)’이라는 용어를 접하셨을 것입니다. 제한은 쿠버네티스가 노드 수준에서 리소스 소비를 제한하는 도구입니다. 특히 메모리 제한은 가상 머신의 작동을 중단시킬 수 있습니다.
좋은 소식은 OpenShift Virtualization이 선택한 네임스페이스에 대해 자동으로 적절한 제한을 설정할 수 있다는 것입니다.
지금까지 얻은 중요한 내용은 다음과 같습니다.
- OpenShift Virtualization은 필요한 경우 메모리(및 CPU) 제한을 자동으로 설정할 수 있습니다.
- 실제로 무엇을 하고 있는지 확실히 알지 않는 한 가상 머신에 메모리 제한을 명시적으로 설정하지 마십시오.
- memory.guest 필드를 통해서만 VirtualMachine 객체에 메모리를 설정합니다.
예약 및 사용량
쿠버네티스는 워크로드가 런타임에 사용할 것으로 예상되는 메모리 리소스 양을 미리 명시하도록 요구한다는 것을 확인했습니다. 따라서 이는 추정치일 뿐이며, 런타임 시 실제 리소스 사용량을 나타내는 것은 아닙니다.
요청이 작업 부하의 메모리 예약이라면, 사용률은 런타임 시의 실제 메모리 사용량입니다.
현실 세계에서는 특정 시점에 워크로드에 실제로 얼마나 많은 메모리가 필요한지 추정하는 것이 매우 어렵습니다. 세상은 매우 다양하기 때문에 메모리 사용량을 정확히 알고 있는 워크로드도 있지만, 반대로 메모리 사용량을 전혀 알 수 없거나 요구 사항이 급격하게 변하는 워크로드도 있습니다.
여기서 중요한 점은 사용률이 워크로드 예약과 상당히 다를 수 있다는 것입니다. 노드 수준에서 살펴보면 이러한 차이가 더욱 뚜렷하게 드러납니다.
하나의 워크로드가 예약량의 50%만 사용하는 것은 문제가 되지 않을 수 있습니다. 하지만 노드의 모든 워크로드가 예약량의 50%만 사용하는 것은 문제가 될 수 있습니다. 이는 노드의 50%가 활용되지 않는다는 것을 의미하기 때문입니다.
참고: 급격하게 변화하는 수요, 즉 급증은 실제로 쿠버네티스와 상태 비저장(12팩터) 애플리케이션의 핵심 원칙에 영향을 미쳤습니다. 바로 확장을 통해 급증에 대응하는 것입니다. 어떤 면에서는 확장이 간단한데, 기존 워크로드를 변경하지 않고 예약만 추가(또는 나중에 삭제)하기 때문입니다. 하지만 본론으로 돌아가 보겠습니다.
우리의 뇌와 눈이 기억할 수 있는 또 다른 것을 제공하기 위해 이것을 시각화해 보겠습니다.

지금까지 얻은 중요한 내용은 다음과 같습니다.
- 워크로드 활용도는 예약과 상당히 다를 수 있습니다.
- 규모에 따라 활용도가 낮으면 리소스 사용이 비효율적입니다.
- 메모리 사용률이 낮으면 노드에 더 많은 작업 부하를 예약할 수 없습니다.
더 높은 작업 밀도
이런 시스템에서 단일 노드나 클러스터의 리소스 활용도를 높이기 위해 무엇을 할 수 있을까요?
지금까지 이 게시물에서 가장 중요한 두 가지 핵심 내용을 뽑아서 답변을 얻으려고 합니다.
- 노드는 사용 가능한 RAM만 메모리로 보고합니다.
- Pod는 가상 머신을 실행하기 위해 메모리를 요청합니다.
그리고 우리에게는 실제로 두 가지 선택권이 있습니다.
a. 더 많은 메모리 리소스를 보고하기 위해 노드의 RAM을 확장합니다.
b. 작업 부하의 메모리 요청을 줄입니다.
쿠버네티스는 메모리 보고에 대해 매우 엄격합니다. 현재는 노드의 물리적 RAM만 보고합니다. 그 외에는 보고하지 않습니다. 보고된 메모리 용량을 실제로 변경할 수 없기 때문에 (a) 옵션은 더 높은 밀도를 달성하기 위한 도구가 아닙니다.
옵션 (b)는 Kubernetes 특유의 방식(“워크로드 메모리 요청 감소”)으로 표현되지만, 전반적인 개념인 “주어진 워크로드에 대해 예약하는 메모리를 줄인다”는 것은 수십 년 동안 가상화 산업 표준이었으며 “메모리 과잉 할당”으로 잘 알려져 있습니다.
OpenShift Virtualization도 동일한 패턴을 따르며 가상 머신에 대해 더 적은 메모리를 요청하여 메모리 과잉 사용을 달성하고 있습니다.
우리의 뇌와 눈이 기억할 수 있는 또 다른 것을 제공하기 위해 이것을 시각화해 보겠습니다.

워크로드에 대한 메모리 요청을 줄이는 것은 꽤 쉬워 보입니다. 바로 요청을 줄이는 것이죠. 물론 쉽게 달성할 수 있습니다. 하지만 이 구성 변경은 어떤 효과를 가져올까요?
가상 머신에 9GiB의 (가상) 메모리가 있고 메모리 요청(예약)을 6GiB로 줄이는 경우 가상 메모리의 3GiB 델타에 대한 메모리 예약은 존재하지 않습니다.
즉, Kubernetes는 이 작업 부하를 위해 6GiB의 메모리를 예약했고, 나머지 3GiB는 예약되지 않은 메모리(초과 할당된 메모리)이며 어딘가에서 가져와야 합니다.
잠시 후에 다시 이야기해 보겠습니다.
OpenShift Virtualization에서 더 높은 워크로드 밀도 구성
OpenShift 가상화는 메모리 과잉 할당을 제공 하지만 기본적으로 비활성화되어 있습니다.
클러스터 관리자는 다음 명령을 실행하여 OpenShift의 모든 워크로드에 대해 메모리 오버커밋을 기본값으로 설정할 수 있습니다.
$ oc -n openshift-cnv patch HyperConverged/kubevirt-hyperconverged --type='json' -p='[ \
{ \
"op": "replace", \
"path": "/spec/higherWorkloadDensity/memoryOvercommitPercentage", \
"value": 150 \
} \
]'
hyperconverged.hco.kubevirt.io/kubevirt-hyperconverged patched
$내부적으로는 매우 간단하게 작동합니다. 게스트에 할당된 메모리(memory.guest)는 memoryOvercommitPercentage 값에 따라 비례적으로 조정됩니다.
memory.guest = 12 GiB
memoryOvercommitPercentage = 150
requests.memory = memory.guest * 100 / memoryOvercommitPercentage
= 12 GiB * 100 / 150
= 8 GiBVM 객체에서 requests.memory와 memory.guest를 수동으로 조정하는 것은 권장되지 않지만, 동일한 결과를 초래할 수 있습니다. 또한, 이러한 워크로드 수준의 수동 접근 방식을 통해 클러스터 기본값을 재정의하고 더 높거나 낮은 오버커밋을 달성할 수 있습니다.
동시에 이는 클러스터 기본 메모리 오버 커밋 구성을 수신하기 위해서는 워크로드가 memory.guest만 정의해야 한다는 것을 보여줍니다.
지금까지 얻은 중요한 내용은 다음과 같습니다.
- OpenShift에서 더 높은 워크로드 밀도를 위해서는 워크로드의 메모리 요청을 낮추는 것이 중요합니다.
- 클러스터 수준 memoryOvercommitPercentage 값을 설정하면 워크로드가 메모리 초과 커밋을 사용하게 됩니다.
- 클러스터 기본 메모리 오버 커밋은 VM 수준에서 memory.guest 및 requests.memory를 수동으로 설정하여 재정의할 수 있습니다. 이 설정은 권장되지 않습니다.
메모리 사용량 줄이기
우리는 과도하게 할당된 메모리를 어딘가에서 가져와야 한다고 말했습니다.
아이디어는 다른 워크로드에서 이 메모리를 가져와서 다른 워크로드가 현재 사용하지 않는 용량을 활용하는 것입니다.
메모리가 9GiB인 VM이 있는데, 이는 6GiB의 메모리 요청으로 뒷받침됩니다.
어느 시점에서 이 VM은 실제로 9GiB의 메모리를 필요로 합니다. 따라서 9GiB VM에 메모리를 제공하기 위해 어딘가에서 3GiB의 메모리를 추가로 가져와야 합니다.
다행히 같은 노드에 12GiB VM(8GiB 메모리 요청)이 있는데, 실제로는 4GiB의 메모리 사용률로 유휴 상태입니다. 따라서 VM은 예약된 것보다 4GiB 적게 사용하고 있습니다.
9GiB VM은 12GiB VM에서 사용되지 않는 메모리를 쉽게 사용할 수 없습니다.
우리의 뇌와 눈이 기억할 수 있는 또 다른 것을 제공하기 위해 이것을 시각화해 보겠습니다.

주의할 중요한 사항:
- 메모리 할당은 VM에 동적으로 투명하게 이루어집니다.
- 메모리 할당은 Kubernetes와 OpenShift에서도 투명합니다.
- 메모리의 할당, 해제, 재할당은 특별한 것이 아니며 일반적인 운영 체제 작업입니다.
OpenShift Virtualization은 워크로드에 대한 동적 메모리 할당 외에도 두 가지 기술을 사용하여 VM의 메모리 사용량을 적극적으로 줄이고 이를 통해 메모리 압박을 더욱 방지합니다.
- FPR이라고도 알려진 Free Page Reporting
- Kernel Same Page Merging(KSM이라고도 함)
각각을 살펴보겠습니다.
Free Page Reporting(FPR)
무료 페이지 보고 기능을 통해 하이퍼바이저는 게스트가 메모리를 사용하지 않는 시점을 확인할 수 있습니다. 하이퍼바이저는 이 메모리를 사용하여 필요에 따라 다른 VM(및 해당 노드의 프로세스)에 제공할 수 있습니다.
게스트 내부에서 Ballooning 드라이버( virtio 드라이버 제품군의 일부 )는 qemu 게스트 에이전트를 통해 하이퍼바이저에 사용 가능한 페이지를 보고하는 역할을 합니다.
FPR은 게스트가 사용하지 않는 메모리 페이지를 보고하는 데 의존합니다.
FPR은 기본적으로 활성화되어 있지만, 게스트 OS 내부에 벌루닝 드라이버가 있어야 합니다.
Kernel Same Page Merging(KSM)
커널 동일 페이지 병합은 호스트 전용 기술입니다. KSM이 활성화되면 커널은 주기적으로 동일한 VM 관련 메모리 페이지를 검색합니다. 중복 메모리 페이지를 발견하면 해당 페이지를 단일 페이지로 병합하여 발견된 모든 중복 메모리를 해제합니다.
프로세스가 이 페이지를 변경하면 커널은 해당 변경 사항을 반영하기 위해 변경 사항이 포함된 해당 페이지를 다시 복제합니다.
KSM은 여러 개의 유사한 VM(예: Windows Workstation)이 동일한 노드에서 실행되는 시나리오에서 특히 유용합니다.
하지만 메모리 중복 제거와 복제(쓰기가 발생하는 경우)로 인해 일반적으로 메모리 작업이 느려집니다(스캔, 중복 제거, 복사가 발생하기 때문).
이론상으로는 이는 공격의 성공 시기를 예측하는 데 도움이 될 수 있으며, 이는 보안 측면에서도 고려사항이 될 수 있습니다.
이 때문에 KSM은 기본적으로 비활성화되어 있으며, 필요한 경우 활성화할 수 있으며, 환경이 허용하는 경우에도 활성화할 수 있습니다.
잘못된 예약
실제로 노드에 충분한 메모리가 있는 데에는 세 번째 이유가 있습니다. 잘못된 메모리 예약입니다.
메모리 예약은 상당히 보수적인 것으로 나타났습니다. 따라서 VM 소유자는 필요 이상으로 많은 메모리를 할당하는 경향이 있습니다.
따라서 메모리 요청이 너무 커지면 노드에 “사용되지 않는” 메모리 예약이 제공됩니다.
지금까지 얻은 중요한 내용은 다음과 같습니다.
- FPR 및 KSM은 더 많은 여유 메모리를 유지하기 위해 VM의 메모리 사용량을 줄이는 기술입니다.
- 크기가 큰 메모리 요청은 사용되지 않는 메모리를 노드에 제공합니다.
메모리 활용 확산
최악의 상황을 피하는 방법에 대해 이야기하려면 먼저 최악의 상황이 무엇인지 이야기해야 합니다.
가장 나쁜 경우는 작업 부하가 더 이상 제공되지 않는 경우입니다.
이러한 현상은 두 가지 원인으로 인해 발생할 수 있습니다. 작업 부하 자체를 사용할 수 없게 되거나, 하이퍼바이저를 사용할 수 없게 되어 정상적으로 작동하던 작업 부하도 사용할 수 없게 되는 것입니다.
이러한 현상의 원인 중 하나는 특정 작업 부하나 시스템에 중요한 데몬으로 인해 메모리가 부족해지는 것입니다.
이제 과도하게 할당된 메모리가 있는 노드가 있지만, VM 메모리 활용도를 낮추는 기술과 잘못된 메모리 요청 크기 조정으로 인해 이러한 작업 부하가 정상적으로 작동하기에 충분한 메모리를 유지하는 경우가 많습니다.
하지만 “보통”이라는 표현은 기업 환경에서 보장을 제공하는 좋은 방법이 아닙니다.
이 섹션에서는 최악의 상황에 대비하는 방법을 살펴보겠습니다. 모든 VM은 우리가 부여한 모든 메모리가 필요합니다. 즉, 모든 VM이 동시에 예약된 메모리를 초과하게 됩니다.
추가 조치가 없으면 노드의 RAM이 부족해져 메모리 부족 오류가 발생하고 작업 부하가 중단됩니다. 이는 용납할 수 없는 일이며, 관리자는 이러한 상황이 발생하기 전에 대응할 시간을 확보해야 합니다.
SWAP
따라서 물리적 RAM을 확장할 수 없으므로 가상 메모리를 확장하는 것을 고려해 볼 수 있습니다.
가상 메모리 또는 주소 공간은 Linux 커널이 프로세스의 메모리를 관리하는 데 사용할 수 있는 메모리입니다.
기본적으로 가상 메모리는 실제 RAM과 동일합니다. 스왑을 제공하여 가상 메모리를 확장할 수 있습니다.
따라서 스왑은 현재 노드에서 실행 중인 모든 VM에 충분한 가상 메모리를 제공하기 위해 충분한 가상 메모리를 제공하는 데 사용됩니다.
스왑과 RAM은 커널에서 동등하게 처리되지 않기 때문에 커널은 “핫”(자주 사용되는) 메모리를 RAM에, “콜드”(덜 자주 사용되는) 메모리를 스왑에 유지하기 위해 휴리스틱을 사용합니다. 스왑은 RAM에 비해 성능이 상당히 느리기 때문입니다.
워크로드 사용자는 일반적으로 워크로드가 스왑으로 교체되기 시작하면 성능 저하를 경험하게 됩니다.
성능에 미치는 영향 때문에 관리자는 일반적으로 스왑이 전혀 발생하지 않도록 방지하는 것이 좋지만, 최악의 경우를 대비해 스왑을 남겨둡니다.
OpenShift의 SWAP
SWAP은 아직 Kubernetes에서 일반적으로 사용할 수 없으므로 OpenShift Virtualization은 가상 머신에 스왑을 제공하기 위해 작은 구성 요소인 WASP를 제공합니다 .
기술적으로 스왑은 메모리 오버커밋과 독립적으로 구성되지만, 메모리 부족 상황에 대응할 시간을 확보하기 위해 메모리 오버커밋의 경우 항상 스왑을 활성화하는 것이 좋습니다.
즉, SWAP은 물리적 메모리를 보완하고 더 큰 가상 메모리를 함께 구성하는 데 사용됩니다. 가상 메모리는 가상 머신에 제공되는 모든 가상 메모리를 지원할 만큼 충분히 큰 것이 권장됩니다.
시간이 꽤 흘렀습니다. 이를 시각화해 보겠습니다. 우리의 뇌와 눈이 기억할 수 있는 또 다른 것을 제공하기 위해:

지금까지 얻은 중요한 내용은 다음과 같습니다.
- SWAP은 물리적 메모리를 보완하며 함께 가상 메모리를 형성합니다.
- 메모리 오버 커밋이 활성화된 경우 SWAP을 사용해야 합니다.
쿠버네티스 디스케줄러
SWAP이 물리적 메모리를 초과하는 요청을 처리할 수 있을 만큼 충분한 가상 메모리를 확보하도록 보장하더라도, 일반적으로는 스왑 사용을 피하는 것도 목표입니다.
그 이유는 스왑이 일반적으로 디스크에 상주하는데, 이는 물리적 RAM보다 훨씬 느리기 때문입니다. 따라서 스왑을 사용할 때마다 스왑과 관련된 메모리 작업의 지연 시간이 크게 증가하여 시스템이 느려지거나(최악의 경우) 정지되는 현상이 발생합니다. 아마 이런 느낌을 경험해 보셨을 겁니다.
FPR과 KSM은 노드의 로컬 메모리 소비를 줄이는 두 가지 메커니즘입니다.
descheduler는 다른 전략을 사용하기 위해 제공됩니다. 로컬 노드에서 메모리가 이미 효율적으로 사용되고 있더라도 클러스터에 여전히 여유 용량이 있는 노드가 있을 수 있으므로 메모리가 부족한 노드에서 VM을 이동합니다.
디스케줄러는 최근에야 노드 부하 인식 기능을 추가했습니다 .
이 새로운 기능의 핵심은 노드에서 발생하는 워크로드의 부하를 모니터링하는 것입니다. 부하가 너무 높으면 해당 노드는 스케줄링에서 제외되고(쿠버네티스 테인트 사용), 과부하된 노드의 부하를 줄이기 위해 영향을 받는 노드에서 워크로드가 제거됩니다.
디스케줄러는 과도하게 사용된 노드를 식별하고, 이를 오염시키고, 작업 부하를 제거하여 노드에 가해지는 압력을 줄이는 역할을 하며, 이를 통해 관리자가 노드에 메모리 압력이 가해졌을 때 수행해야 하는 작업을 자동화합니다.
우리의 뇌와 눈이 기억할 수 있는 또 다른 것을 제공하기 위해 이것을 시각화해 보겠습니다.


지금까지 얻은 중요한 내용은 다음과 같습니다.
- Descheduler는 노드의 작업 부하 압력을 모니터링하고 필요한 경우 노드 수준 압력을 줄이기 위해 작업 부하를 제거합니다.
- 규모에 따라 이는 클러스터의 모든 작업자에 대한 압력을 평준화하는 데 도움이 됩니다.
메모리 압력 감소
노드 압력 제거
노드 압력 축출(Node-pressure eviction)은 노드가 압력을 받으면 파드를 축출하기 위한 노드 로컬 축출 메커니즘(클러스터 수준 축출과 혼동되는 경우가 많음)입니다. 노드 압력은 메모리, 스토리지, PID 개수(동시에 실행할 수 있는 프로세스 수에 제한이 있기 때문)와 같이 압축 불가능한 리소스에 대해서도 발생할 수 있습니다.
따라서 이러한 리소스 중 하나라도 과부하 상태가 되면 쿠버네티스(kubelet)는 파드를 가져와 제거합니다. 이 경우 제거는 관리자가 정의한 유예 기간 내에 워크로드를 종료하라는 요청입니다.
노드 압력 제거에는 두 가지 변형이 있습니다.
- 소프트 퇴거 – 유예 기간 후 작업 종료
- 강제 퇴거 – 유예 기간 없이 작업 종료
현재 소프트 퇴거는 기본적으로 사용되지 않지만, 하드 퇴거는 기본적으로 구성됩니다.
메모리 부족
아직 함께하고 계신가요? 축하합니다. 이제 꽤 짧은 섹션을 만나보실 수 있게 되었습니다.
메모리가 실제로 부족해지는 경우는 매우 드물지만, 가상 머신이 종료됩니다. 이는 전체 노드를 사용할 수 없게 되는 것을 방지하기 위한 조치이며, 해당 노드의 모든 가상 머신을 사용할 수 없게 됩니다.
요약
이 게시물에서는 OpenShift Virtualization에서 가상 머신의 메모리 관리가 어떻게 작동하는지, 그리고 메모리 압박을 방지하고 처리하기 위한 메커니즘이 무엇인지 살펴보았습니다.
높은 수준에서 주목할 점은 두 가지입니다.
- 클러스터 관리자와 워크로드 소유자는 필요한 경우 클러스터 및 워크로드 메모리 구성을 엄격하게 제어할 수 있습니다.
- 기본적으로 OpenShift Virtualization은 메모리 오버 커밋을 수행하지 않고 FPR(Functional Percentage)을 사용하여 메모리를 효율적으로 사용합니다. 선택적으로 KSM, SWAP, 그리고 Descheduler를 사용하여 메모리 사용량을 줄이거나 분산할 수 있습니다.
- 메모리 오버 커밋에는 스왑이 필요하며 선택적으로 활성화할 수 있습니다.
지금까지 얻은 중요한 내용은 다음과 같습니다.
- 노드 압력 퇴출은 노드가 리소스 압력을 받으면 작동하는 노드 수준 보호 메커니즘입니다.
- 가상 머신의 메모리는 memory.guest 필드를 사용해서만 구성해야 합니다.
- Kubernetes와 OpenShift는 물리적 메모리(RAM)를 메모리 리소스로 노출합니다.
- 포드 스케줄링은 메모리 요청(resources.requests.memory)을 기반으로 합니다.
- 오늘날 더 높은 워크로드 밀도를 달성하는 유일한 방법은 워크로드의 메모리 요청을 줄이는 것입니다. 워크로드 또는 클러스터 수준에서 말입니다.
- FPR과 KSM은 메모리 압박을 방지하기 위해 노드의 메모리 사용량을 줄이는 메커니즘입니다.
- SWAP은 모든 작업 부하에 충분한 공간을 확보하기 위해 가상 메모리를 확장하는 메커니즘입니다.
- descheduler는 노드 압력에 따라 클러스터 노드에 작업 부하를 분산합니다.