Skip to content
isdnetworks
Go back

표시된 값과 실제 할당의 대조

(수정됨)

메모리가 모자란다는 알림이 왔는데 관리 화면의 /health 에는 여유가 충분하다고 나왔다. 두 값이 서로 안 맞으므로 어느 쪽이 무엇을 재고 있는지부터 확인해야 했다.

Table of contents

Open Table of contents

배경 — 화면과 알림이 어긋난 지점

호스트에서 free -m 으로 전체 사용량을 보니 화면이 보여 주는 값과 같았고 실제로 여유가 있었다. 컨테이너 안에서 cgroup 의 memory.current 와 memory.max 를 읽어 보니 한도에 거의 닿아 있었다.

호스트 전체는 여유가 있는데 컨테이너는 꽉 차 있는 상태였고 두 값 다 맞는 값이었다. 어긋난 것은 값이 아니라 무엇을 재는지에 대한 합의였다.

원인 — 무엇을 읽고 있었는가

화면을 그리는 코드가 컨테이너가 아니라 /proc/meminfo 의 호스트 전체 메모리 정보를 읽고 있었다. 컨테이너 안에서 도는 프로세스의 관점에서는 그 값이 아무 의미도 갖지 않는다.

커널 공식 문서대로 memory.current 는 그 cgroup 이 지금 쓰는 양이고 memory.max 가 상한이므로 그 둘을 읽도록 바꾸니 화면 값이 실제와 맞았다. 같은 이름의 값이라도 그것을 어디서 읽느냐가 그 값의 뜻을 정한다.

검증 — 설정과 한도의 어긋남

화면 값이 맞아졌어도 왜 한도에 닿았는지는 그것과 별개로 봐야 했다. 프로세스별 사용량을 세어 보니 프로세스 하나가 수백 메가를 쓰고 있었다.

pm.max_children 은 그 값에 곱해 보면 한도를 크게 넘는 수였다. 설정은 호스트 기준으로 잡혀 있고 한도는 컨테이너 기준이라 둘이 서로를 모르고 있었다.

조치 — 프로세스가 커진 이유

프로세스 하나가 그만큼 커진 것도 정상적인 상태라고 볼 수는 없었다. memory_limit 이 크게 잡혀 있었고 실제로 그만큼 쓰는 요청이 있었다.

두 가지 방법이 있었는데 pm.max_children 을 한도에 맞춰 줄이는 것과 목록을 통째로 올리는 자리를 chunk() 로 나눠 가져오게 바꾸는 것이다. 뒤쪽을 골랐다. 이유는 개수를 줄이면 동시 처리량이 그만큼 줄어서다. 대신 코드 수정과 배포가 한 번 더 필요한 것을 감수했다. 바꾸니 프로세스 크기가 오분의 일로 줄었고 그러고 나서 프로세스 개수를 원래 값으로 되돌려도 한도 안에 들어갔다.

주의 — 강제 종료가 안 보이던 까닭

memory.events 의 oom_kill 을 읽어 보니 강제 종료가 여러 번 기록돼 있었다. 재시작 설정 때문에 곧바로 다시 떠서 겉으로는 계속 정상으로 보이고 있었다.

그 값을 지표로 내보내 0이 아니면 알리게 했고 같은 방식으로 처리 능력과 디스크도 함께 확인했다. 코어 수도 nproc 호스트 값을 읽어 워커를 띄우고 있었으므로 cpu.max 를 읽어 정하게 바꿨다.

정리


Share this post on:

Previous Post
쓰는 길과 읽는 길이 다르다
Next Post
공통 규칙이 잡아먹은 예외