CI 서버 관리 화면에 메모리 미설정 경고가 떠서 빌드가 무거우니 힙을 키우면 되겠다고 생각했다.
Table of contents
Open Table of contents
상황 — 경고와 첫 생각
처음 떠올린 값은 이랬다.
-Xmx16g
-Xmx 를 그만큼 잡아 주면 될 것으로 봤다.
값을 정하기 전에 그 힙을 실제로 무엇이 쓰는지 확인하기로 했다. 무엇이 쓰는지 모르고 숫자만 키우면 아무 효과 없이 자원만 잡아 둔다.
검증 — 빌드가 뭘 쓰나 봤다
프론트 빌드 설정을 봤다.
--max_old_space_size=16384
max_old_space_size 가 16GB로 잡혀 있었다.
max_old_space_size 의 이력도 남아 있었는데 12GB에서 죽어서 16GB로 올린 것이었다. 추정이 아니라 한 번 죽어 보고 나온 실수요라 근거가 확실했다.
원인 — 두 풀이었다
여기서 걸렸다.
[컨트롤러] JVM — 힙에서 씀
[이 빌드] 비JVM — 힙과 무관
프론트 빌드는 JVM 이 아니라 node 프로세스로 따로 뜬다.
여기에 서로 독립된 두 개의 메모리 풀이 있었다.
① 컨트롤러 힙 CI 자신의 운영용
② 빌드가 쓰는 메모리 컨테이너 한도에서 소비
빌드는 ② 를 쓰므로 -Xmx 를 키워도 그쪽으로 가지 않는다.
그러니 키워야 할 것은 -Xmx 가 아니라 컨테이너 쪽 한도였다. -Xmx 를 키우면 오히려 같은 한도 안에서 빌드가 쓸 자리를 줄인다.
설정 — 힙은 작게 한도는 합으로
JVM 힙은 운영 전용이라 작아도 됐다.
-Xms2g -Xmx2g
작업 목록과 이력과 화면에만 쓰므로 2GB면 충분하고 최소와 최대를 같게 뒀다.
--memory 한도는 합으로 잡았다.
컨트롤러 힙 2g
단일 빌드 최대치 16g
여유 +α
──────────────────────
합계 20g
힙과 빌드가 같은 컨테이너 안에 있으니 합으로 잡아야 했다.
주의 — 실행기 수
설정을 더 보다가 위험한 값이 하나 걸렸다.
numExecutors = 12
numExecutors 가 12라 16GB짜리 빌드가 열둘이면 192GB가 필요해진다.
한도 20GB에 열둘이 동시에 뜰 수 있는 상태였다. 동시 실행은 메모리 값으로 막는 것이 아니라 실행기 수로 정해진다.
numExecutors = 1
numExecutors 를 1로 두니 대형 빌드가 단독 실행되는 것이 보장됐다.
동시 실행 제한 플러그인을 넣을까 했는데 실행기가 하나면 필요 없었고 더 단순한 수단으로 같은 결과가 났다.
배경 — 딸려 들어온 설정
이 numExecutors 값이 애초에 어디서 왔는지도 봤다.
마이그레이션으로 딸려 들어온 설정이었고 이전 환경의 값이 그대로 넘어온 것이었다. 그 환경에서는 빌드가 가벼웠을 것이다.
[코드] 검토를 거침
[설정 파일] 마이그레이션에 묻어 들어옴
코드는 옮길 때 검토를 거치는데 설정 파일은 그대로 복사되는 경우가 많았다.
최종 구성은 처음 생각과 셋 다 달랐다.
컨트롤러 힙 2g 고정 (Xms = Xmx)
GC G1
컨테이너 한도 20g
실행기 수 1
결국 힙은 안 키우고 한도를 키우고 실행기 수를 줄이는 쪽으로 끝났다.
정리
- 컨테이너에서 도는
CI의 메모리는 독립된 두 풀이다 - 무엇이 쓰는지 모르고 숫자만 키우면 효과가 없다
- 비
JVM빌드는 힙과 무관하고 컨테이너 한도에서 쓴다 - 빌드가 무거우면 힙이 아니라 한도를 키운다
- 컨트롤러 힙은 운영 전용이라 작아도 된다
- 최소와 최대를 같게 고정한다
- 한도는 힙과 단일 빌드 최대치와 여유를 더해 잡는다
- 동시 실행은 실행기 수로 통제한다
- 실행기가 하나면 별도 플러그인이 필요 없다
- 마이그레이션으로 딸려온 설정이 코드보다 위험할 수 있다