--- id: 63fa33e5-9957-4d28-8d3c-c75735a73bd6 kind: REFERENCE slug: memory-symptom-needs-layer-separation title: 메모리 증상 하나로 계층을 단정하지 않는다 topic: memory-virtualization topicName: 메모리 가상화 project: virtualization status: 초안 studio: "https://hyeonworks.com/studio/documents/63fa33e5-9957-4d28-8d3c-c75735a73bd6/edit" sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다 source: - final/document.md#86-문제를-진단할-때의-분류 - final/document.md#63-swap-used만-보고-장애를-판단하면-안-된다 - final/document.md#78-numa는-실제-장비-topology부터-확인한다 - final/document.md#88-결론 - final/document.md#61-guest-swap과-host-swap - final/document.md#72-guest-oom과-host-oom --- # 메모리 증상 하나로 계층을 단정하지 않는다 §86 은 메모리 지연이나 OOM(Out Of Memory, 커널이 필요한 메모리를 확보하지 못해 프로세스를 종료할 수 있는 상태)이 보일 때 한 번에 「메모리 부족」이라고 결론내리지 말라고 적었다. 대신 증상을 먼저 다섯 갈래로 가르는 분류를 두었다. Guest Virtual Memory · Virtualization Translation · Host Memory · Dynamic Memory · NUMA 다섯이다. 마지막의 NUMA(Non-Uniform Memory Access, 비균일 메모리 접근)는 어느 CPU 가 어느 RAM 에 접근하느냐에 따라 비용이 달라질 수 있는 구조다. 같은 요구가 개념 문서 안에서 세 번 더 나온다. Swap Used 값 하나로 판단하지 않고(§63), NUMA 최적화를 토폴로지를 재기 전에 정하지 않으며(§78), 게스트 하나의 free -h 만 보고 메모리 상태를 판단하지 않는다(§88). 이 기준은 그 넷을 한 판독 절차로 묶는다. 뒤의 셋을 따로 규칙으로 세우지 않은 것은 보는 대상만 다를 뿐 §86 과 같은 말을 하기 때문이다. 규칙이 세 벌이면 판독하는 사람이 어느 것을 따르는지가 갈린다. ## 관계 - **VM 에서 page fault 는 세 계층에서 따로 일어난다** Guest Virtual Memory 갈래와 Virtualization Translation 갈래, Host Memory 갈래가 각각 어떤 fault 로 보이는지를 그 기록이 푼다. - **Host 메모리 압박이 Guest 와 스토리지까지 내려가는 경로** Host Memory 갈래로 좁힌 뒤에 무엇이 이어지는지를 그 기록이 설명한다. - **virtio-balloon 이 Guest 메모리를 회수하고 돌려주는 방식** Dynamic Memory 갈래에서 볼 balloon target 과 Guest pressure 가 그 기록에서 나온다. - **NUMA 에서는 vCPU 배치와 메모리 배치를 함께 본다** NUMA 갈래로 좁혔을 때 vCPU placement 와 memory placement 를 왜 따로 읽으면 안 되는지를 그 기록이 설명한다. - **메모리 실험 결과에는 Host · VM · Workload 조건을 함께 남긴다** 이 기준은 갈래를 좁히는 데까지만 쓰이고, 원인을 확정하는 측정은 그 기준이 요구한 조건과 함께 남긴다. - **지금 게스트와 호스트에서 swap 이 실제로 오가고 있는가** 2 번 규칙과 3 번 규칙이 요구한 관측을 이 호스트에서 실제로 수행하는 물음이다. - **게스트 page fault 증가는 workload 변화를 따라가는가** Guest Virtual Memory 갈래로 좁힌 증상을 워크로드와 견주는 물음이다. ## 목적 이 기준은 증상 하나를 원인으로 바로 옮기는 판독을 막는다. §86 이 든 예가 메모리 지연과 OOM 인데, 둘 다 다섯 계층 어디서든 나올 수 있다. 다섯 갈래를 개념 한 편 안에 넣지 않고 따로 세운 것은 갈래마다 받는 개념이 다르기 때문이다. 어느 한 개념 안에 두면 그 글이 나머지 넷을 가리키지 못한다. 좁히는 것과 확정하는 것을 갈라 둔 이유도 여기 있다. 이 기준은 어느 갈래인지까지만 좁히고, 원인 확정은 §85 의 조건을 함께 남긴 측정이 한다. ## 규칙 ### 1. 증상을 다섯 갈래로 먼저 가른다 §86 의 분류는 메모리 지연이나 OOM 을 다섯으로 나누고, 갈래마다 볼 것을 함께 적었다. Guest Virtual Memory : Page Fault · Guest reclaim · Guest swap · Guest OOM Virtualization Translation : EPT-related event · TLB pressure · Huge-page/mapping 특성 Host Memory : Host reclaim · Host swap · Host major fault · Host OOM Dynamic Memory : Balloon target · Guest pressure · Hotplug/virtio-mem 여부 NUMA : vCPU placement · memory placement · remote access ### 2. Swap Used 값 하나로 메모리 압박을 단정하지 않는다 §63 은 Swap Used = 2 GiB 라는 값만으로 지금 메모리 압박이 심하다고 단정할 수 없다고 적었다. 과거에 swap-out 된 cold page 가 남아 있을 수도 있기 때문이다. 같은 절이 대신 물으라고 한 것은 넷이다. 현재 swap-in/out 이 지속되는가? reclaim pressure 가 증가하는가? major fault 가 증가하는가? storage latency 가 같이 증가하는가? 이 넷은 게스트와 호스트를 동시에 확인해야 한다고 §63 이 못박았고, 확인 명령으로 free -h 와 vmstat 1 을 들었다. ### 3. 게스트 스왑과 호스트 스왑을 한 값으로 세지 않는다 §61 은 두 스왑이 서로 다른 경로라고 적었다. 게스트 스왑은 게스트 메모리 압박에서 시작해 게스트 커널과 게스트 스왑을 지나 /dev/vda 로 내려가고, virtio-blk 와 QEMU 를 거쳐 호스트 스토리지에 닿는다. 호스트 스왑은 게스트 RAM 의 QEMU memory backing 이 호스트 메모리 압박을 만나 호스트 커널의 스왑으로 내려가는 경로다. 경로가 이렇게 갈리다 보니, 게스트는 메모리에 여유가 있어 보이는데 호스트에서는 스왑과 reclaim 이 심할 수도 있다. ### 4. OOM 은 발생 계층을 확인한 뒤에 부른다 §72 는 게스트 OOM 과 호스트 OOM 을 갈랐다. 게스트 RAM 이 모자라서 게스트 커널이 프로세스를 죽이면 Keycloak 프로세스 종료 같은 결과가 된다. 호스트 물리 RAM 이 모자라서 호스트 커널이 QEMU 를 victim 으로 고르면 그 VM 전체가 중단될 수 있다. cgroup memory limit 이 걸린 환경은 예외로 둔다. 호스트 전체 RAM 에 여유가 있어도 그 cgroup 경계에서 OOM 이 발생할 수 있다고 같은 절이 적었다. ### 5. NUMA 갈래는 토폴로지를 잰 뒤에 순위를 매긴다 §78 은 호스트가 NUMA node 한 개면 cross-node remote-memory 문제가 주요 이슈가 아닐 수 있어서, 실제 환경에서는 먼저 토폴로지를 재고 NUMA 최적화가 필요한지 판단하라고 했다. 확인 명령으로는 lscpu 와 numactl --hardware 를 들었다. QEMU 프로세스별 메모리 분포는 numastat -p , vCPU 배치는 virsh vcpupin 과 virsh vcpuinfo 을 들었다. ### 6. 게스트 하나의 free -h 로 닫지 않는다 §88 은 실제 테스트 서버에서 게스트 하나의 free -h 만 보고 메모리 상태를 판단하지 않는다고 적었다. Guest → QEMU → Host → NUMA → Storage 영향을 같은 시간축에서 관측해야 한다고 했다. ## 적용 조건 메모리 증상을 원인으로 옮기려는 판독 전부에 걸린다. 지연 증가, 스왑 관측, OOM, fault 증가가 여기 들어간다. 가르는 축은 다섯이고, 갈래마다 무엇을 볼지는 1 번 규칙에 적혀 있다. ## 예외 cgroup memory limit 이 걸린 환경에서는 호스트 전체 RAM 에 여유가 있어도 그 경계에서 OOM 이 나기 때문에, Host Memory 갈래를 곧바로 지우면 안 된다(§72). NUMA node 가 하나인 호스트에서는 NUMA 갈래의 우선순위를 낮춰도 된다고 §78 이 적었다. 그것도 토폴로지를 잰 뒤의 이야기다. 이 기준은 갈래를 좁힐 뿐 원인을 확정하지 않는다. 확정은 §85 의 조건을 남긴 측정이 한다. ## 예시 - 게스트에서 Swap Used 만 보고 「메모리 부족」으로 닫은 판독 : swap-in/out 이 지속되는지를 재지 않았다 - 게스트 free -h 에 여유가 보여 호스트를 보지 않은 판독 : 호스트 reclaim 과 호스트 스왑을 확인하지 않았다 - Keycloak 프로세스가 죽었는데 호스트 커널 로그를 보지 않은 판독 : 게스트 OOM 인지 호스트 OOM 인지 갈리지 않는다 - 호스트 RAM 에 여유가 있다는 이유로 OOM 을 다른 갈래로 넘긴 판독 : cgroup 경계를 확인하지 않았다 - 토폴로지를 재지 않고 vCPU pinning 부터 손댄 조치 : NUMA 갈래가 이 호스트에 걸리는지 모른다 - 게스트와 호스트를 다른 시각에 찍어 한 표로 놓은 기록 : 같은 시간축이 아니다