본문 바로가기
카테고리 없음

page allocation failure: order: 5 메모리 할당 실패 이슈원인, 로그분석, 대응방안

by 기본기를 다지는 블로그 2025. 4. 16.

메모리할당 실패

1. 메모리 할당 실패 메모리 이슈 원인

리눅스 서버를 점검하다 보면 심심치 않게 나오는 로그가 있습니다.

 

바로 아래와 같은 메모리 페이지 할당 실패 로그입니다.

Apr 14 07:32:42 server1 kernel: kworker/u448:1: page allocation failure: order:5, mode:0x80d0

 

커널은 데이터와 구조체의 임시 저장을 위해 메모리 청크(4KB의 페이지)를 자주 할당해야 합니다.

 

그러나 할당하는 과정에서 유저 영역의 어플리캐이션이 여러 페이지에 걸쳐 연속된 큰 메모리를 할당하고자 가상 메모리 주소를 예약하지만, 물리적인 연속된 여러 페이지 집합이 없을 가능성이 있습니다. 

 

이러한 경우 메모리 할당자는 할당요청에 실패하며 시스템 로그에 할당 실패 메시지가 생성됩니다. 

 

다량으로 발생된다면 메모리 압박이 심한 경우일테니 바로 조치가 필요한 경우( 애플리케이션에서 익명의 메모리를 swap으로 푸시, cache drop 등)일테지만 간헐적으로 드물게 나온다면 괜찮은거 같으면서도  조금 찜찜합니다.

 

2. 로그 분석

먼저  로그를 확인해보겠습니다.

 

정말 메모리가 부족하여 에러가 발생했는지 확인합니다.

Apr 14 07:32:42 server1 kernel: kworker/u448:1: page allocation failure: order:5, mode:0x80d0
Apr 14 07:32:42 server1 kernel: CPU: 6 PID: 138678 Comm: kworker/u448:1 Tainted: P           OE  ------------   3.10.0-514.el7.x86_64 #1
Apr 14 07:32:42 server1 kernel: Hardware name: FUJITSU PRIMERGY RX2540 M4/D3384-A1, BIOS V5.0.0.12 R1.60.0 for D3384-A1x                    04/07/2023
Apr 14 07:32:42 server1 kernel: Workqueue: i40e i40e_service_task [i40e]
Apr 14 07:32:42 server1 kernel: 00000000000080d0 000000009bfcd894 ffff881fd0fb38e8 ffffffff81685eac
Apr 14 07:32:42 server1 kernel: ffff881fd0fb3978 ffffffff811869a0 0000000000000000 00000000ffffffff
Apr 14 07:32:42 server1 kernel: ffffffffffffffe0 000080d000000000 ffff881fd0fb3948 000000009bfcd894

 

Apr 14 07:32:42 server1 kernel: Mem-Info:
Apr 14 07:32:42 server1 kernel: active_anon:5426854 inactive_anon:727006 isolated_anon:0#012 active_file:1709471 inactive_file:12977358 
...
Apr 14 07:32:42 server1 kernel: Node 0 DMA free:14560kB min:40kB low:48kB high:60kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB 
...
Apr 14 07:32:42 server1 kernel: Node 0 DMA32 free:382056kB min:3284kB low:4104kB high:4924kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB
...
Apr 14 07:32:42 server1 kernel: Node 0 Normal free:825916kB min:257700kB low:322124kB high:386548kB active_anon:7615896kB inactive_anon:1215764kB active_file:3116436kB inactive_file:29425340kB 
...
Apr 14 07:32:42 server1 kernel: Node 1 Normal free:933620kB min:263256kB low:329068kB high:394884kB active_anon:14091520kB inactive_anon:1692260kB active_file:3721448kB inactive_file:22484092kB
...

 

 Node 0 의 Normal 메모리 영역을 확인해보면, free:825916kb (약 806 MB) 이 존재하는것을 알 수 있습니다. 따라서

메모리의 총 량은 부족하지 않았습니다. Node1도 마찬가지 이구요

...
Apr 14 07:32:42 server1 kernel: Node 0 Normal free:825916kB min:257700kB low:322124kB high:386548kB active_anon:7615896kB inactive_anon:1215764kB active_file:3116436kB inactive_file:29425340kB 
...

 

 

메모리가 부족해서 발생한 문제는 아닌것으로 확인됩니다.

 

다시한번 로그를 살펴보면 "kworker/u448:1: page allocation failure" 로그는 커널 스레드에서 메모리 페이지를 할당하려다 실패한 것 같은데 order:5 는 뭘까요?

 

이 번호에 뭔가 힌트가 있을거 같습니다.

Apr 14 07:32:42 server1 kernel: Node 0 DMA: 0*4kB 0*8kB 0*16kB 1*32kB (U) 1*64kB (U) 1*128kB (U) 0*256kB 0*512kB 0*1024kB 1*2048kB (M) 3*4096kB (UM) = 14560kB
Apr 14 07:32:42 server1 kernel: Node 0 DMA32: 10*4kB (UM) 14*8kB (UEM) 13*16kB (UEM) 8*32kB (UEM) 12*64kB (UEM) 6*128kB (UEM) 6*256kB (UEM) 5*512kB (UEM) 5*1024kB (UEM) 5*2048kB (UEM) 88*4096kB (UM) = 382056kB
Apr 14 07:32:42 server1 kernel: Node 0 Normal: 67880*4kB (UEM) 30487*8kB (UEM) 16515*16kB (UEM) 1620*32kB (UEM) 2*64kB (UM) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 831624kB
Apr 14 07:32:42 server1 kernel: Node 1 Normal: 27029*4kB (UEM) 29623*8kB (UEM) 31667*16kB (UEM) 2003*32kB (UEM) 340*64kB (UEM) 7*128kB (UM) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 938524kB

 

order 5 를 확인하기에 앞서 로그에서 Node 0과 1로 나뉘어 있는것을 볼 수 있는데요, NUMA 노드가 활성화 되어 있어서 그렇습니다. NUMA는 CPU가 메모리를 지역적으로 사용할 수 있게 묶어주는 기능입니다.

 

위 로그에 보면 Node0과 1의 DMA, DMA32, Normal가 보이는데 이건 무얼까요?

이 메시지는 바로 커널이 메모리를 Zone 단위로 관리를 하는데, 각각 메모리 할당 상태를 나타낸 내용입니다.

 

예를들어 "Zone DMA"는 Direct Memory Access 라고도 하는데 네트워크 카드, 디스크 컨트롤러 등이 CPU를 거치지 않고 메모리에 직접 접근하기 위해 사용되는 영역입니다.

 

 

- 하기 내용부터 아래 링크의 "Memory zones on a x86-64 bit cpu" 설명 인용 -

 

  • Zone DMA 영역의 메모리는 예를 들어 24비트(16MB)만 주소 지정할 수 있는 네트워크 카드와 같은 전송에 사용될 수 있습니다. 일부 카드/드라이버는 DMA 영역의 메모리만 사용할 수 있습니다.
  • Zone DMA32 영역의 메모리는 크기가 4GB이며, 32비트 주소 지정이 가능한 카드와의 데이터 교환에 사용됩니다.
  • Zone Normal 영역의 메모리는 커널이 DMA, DMA32를 할당하고 남은  모든 메모리 영역을 지칭합니다.

 

내용이 조금 어려우니 그냥 커널이 메모리 영역별로 상황에 맞게 관리하는 zone이 있다는 정도로만 이해해도 좋을거 같습니다.

 

참고1)

https://www.redhat.com/en/blog/memory-zones-and-linux-driver-issue

 

Memory zones and a Linux driver issue

In my time as a TAM at Red Hat, I've helped to solve a variety of issues for customers. Each day is a new challenge and with that, a new learning opportunity. The story I want to share with you today started with a customer’s report about multiple cluste

www.redhat.com

 

 

이 Zone을 좀 더 자세히 확인하려면  /proc/buddyinfo 파일을 열어  각 필드를 살펴봅니다. 

buddyinfo는 zone마다 order별로 몇 개의 연속된 페이지 블록이 남아 있는지를 보여줍니다.

쉽게 말해 각 열은 서로 다른 크기의 메모리를 담는 바구니로 생각할 수 있습니다.

                           V     VV     VVV    VVVV
Node 0, zone      DMA      1      0      1      1   [..] 
Node 0, zone    DMA32      8      7      5      7   [..]
Node 0, zone   Normal   9539   4328   7412   2374   [..]
Order                      0      1      2      3   [..] 
Zone Byte Size           4kB    8kB   16kB   32kB   [..]

 

"V" 칼럼의 제일 마지막 라인의 4KB의 여유페이지는 Node 0 의 DMA 영역에서 1개, DMA32 영역에서 8개를 가지고 있음을 보여줍니다.

위 내용을 확인한 뒤, 문제의 시스템에서 /proc/buddyinfo를 확인해 보았습니다.

 

 

이제 order 5의 단서를 찾을 수 있을거 같습니다.

 

자세히 확인해보니 NUMA Node 0의 order 5 열의 128KiB 페이지 영역의 (2^5 = 32 pages) 여유페이지가 "0"개 인 것을 확인할 수 있습니다.

 

이 128KiB 용량의 메모리 덩어리를 할당할 수 있는 여유 페이지가 없기 때문에 kworker/u448:1: page allocation failure: order 5 에러가 발생된 것으로 파악됩니다.

                                                            V
                          4K     8K    16K    32K    64K   128K   256K   512K  1024K  2048K  4096K
                order      0      1      2      3      4      5      6      7      8      9     10
--------------------------------------------------------------------------------------------------     
Node 0, zone      DMA      0      0      0      1      1      1      0      0      0      1      3
Node 0, zone    DMA32     10     14     13     11     10      7      7      4      5      5     88
Node 0, zone   Normal 185367 100372  74245   1034     39      0      0      0      0      0      0  <---
Node 1, zone   Normal  89769 135142  41108    598    134     41     21      7      0      0      0

 

 

3. 대응방안

 

위 언급한대로, 메모리는 부족하지 않았으나 메모리 단편화 등으로 인해 발생하는 메모리 페이지의 할당 불가 이슈를 회피할 수 있는 방법은 무었이 있을까요?

 

리눅스 커널은 메모리가 너무 부족해지기 전에 미리 정리(reclaim)하거나 조치를 취하려고 합니다.

 

이와 연관된 커널 파라미터는 "vm.min_free_kbytes" 이며 이 값을 조절하므로써 할당 불가 이슈를 회피할 수 있습니다.

 

 "vm.min_free_kbytes" 를 통해 메모리의 낮은 임계값을 상승 조정하여 위와 같은 메모리 페이지가 부족할 때를 대비하여  반환을 더욱 적극적으로 하려는것이 목적입니다.

 

  • 항목기본값 (기준: pages_min)역할 및 의미동작 방식

     

    pages_min 1x (pages_min) 최소 워터마크. 이 수치에 도달하면 동기적 메모리 회수(direct reclaim) 수행 프로세스가 직접 reclaim 함 (→ 성능 저하 가능)
    pages_low 2x (pages_min) kswapd를 깨우는 기준. 여기에 도달하면 비동기적 메모리 회수 시작 buddy allocator가 kswapd를 wake-up 시킴
    pages_high 3x (pages_min) 메모리가 충분히 회수되었다고 간주되는 기준. 여기에 도달하면 kswapd는 다시 sleep 메모리가 pages_high 이상 되면 kswapd는 멈춤
     
    메모리 부족 처리 흐름 요약:
    1. 정상 상태: free memory > pages_high → 아무 작업도 안 함
    2. 메모리 감소: pages_low 도달 → kswapd가 wake up → 백그라운드 reclaim
    3. 심각한 부족: pages_min 도달 → 직접 reclaim 수행 (프로세스가 멈춰 reclaim)

참고2)

https://www.kernel.org/doc/gorman/html/understand/understand005.html

 

Describing Physical Memory

PG_launderThis bit is important only to the page replacement policy. When the VM wants to swap out a page, it will set this bit and call the writepage() function. When scanning, if it encounters a page with this bit and PG_locked set, it will wait for the

www.kernel.org

 

현업에서는 위와 같은 이슈 발생시  " vm.min_free_kbytes"  파라미터 현재 값의 2-3배를 우선 적용하고 모니터링을 통해 경과를 지켜봅니다.

 

주의:  vm.min_free_kbytes의 극단적인 값은 시스템 성능저하가 발생할 수 있습니다. 해당 파라미터는 시스템 메모리에 비례하여 값이 정해지므로 매우 낮거나 매우 높은 값은 시스템에 악영향을 일으킬 수 있으니 주의하시기 바랍니다.

 

경험상 간헐적인 할당 실패 로그는 큰 문제로 이어지지 않았습니다.

다만, 시스템 관리자라면 시스템 이슈에 항상 대응을 할 필요가 있으므로 세심한 관찰이 필요합니다.