在 Docker 模擬 Linux Kernel 的 out-of-memory (OOM) 機制

最近我們發現 AWS ECS 的 Log 會出現 Killed 的訊息,一段時間 container 就會重開,而它的訊息大概如下:

Killed
npm ERR! code ELIFECYCLE
npm ERR! errno 137
npm ERR! [email protected] start: `node server.js`
npm ERR! Exit status 137
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2022-01-01T00_00_00_001Z-debug.log

OOM

查了一下發現它是一個叫做 out-of-memory (OOM) 的機制,它的發生在於記憶體不足,而我們在 AWS ECS 上面有設定 Memory Limits (MiB),有設定 Soft limit 與 Hard limit,所以它在超過 Hard limit 的時候會強制停止這個 process。

模擬程式被 OOM 的情況

它其實是一個 Docker 底層原生支援的機制可以在 Runtime options with Memory, CPUs, and GPUs 找到詳細的解釋,也因為這樣所以我決定自己寫一個簡單測試程式來模擬這個情況,它主要的機制就是讓程式一直瘋狂的吃系統記憶體支援就可以,詳細程式可以參考我的範例 https://github.com/clarencetw/nodejs-simulate-oom.git

使用 docker-compose 測試

第一步我先使用 docker-compose 來模擬這個測試,因為這樣測試比較簡單,只要把整個專案 clone 下來後執行 docker-compose up 就可以看到如下的錯誤,成功看到它出現 error Command failed with exit code 137

$ docker-compose up
Starting nodejs-simulate-oom_node_1 ... done
Attaching to nodejs-simulate-oom_node_1
node_1  | yarn run v1.22.18
node_1  | $ node server.js
node_1  | Example app listening on port 3000
node_1  | Heap allocated 0.01 GB
node_1  | Heap allocated 0.01 GB

 ...

node_1  | Heap allocated 0.07 GB
node_1  | Killed
node_1  | error Command failed with exit code 137.
node_1  | info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
nodejs-simulate-oom_node_1 exited with code 137

使用 docker 指令測試

那如果是直接使用 docker 指令直接指定 -m 就可以完成了,所以指令就是 docker run -ti --rm -m 64M nodejs-simulate-oom_node 就可以了,執行後也會看到下面出現 error Command failed with exit code 137. 程式被收回。

$ docker run -ti --rm -m 64M nodejs-simulate-oom_node
yarn run v1.22.18
$ node server.js
Example app listening on port 3000
Heap allocated 0.01 GB
Heap allocated 0.01 GB

 ...

Heap allocated 0.07 GB
Heap allocated 0.07 GB
Killed
error Command failed with exit code 137.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. 

參考資料