Nhận biết container bị OOMKilled
Container restart liên tục nhưng không có crash log rõ ràng? Kiểm tra exit code — nếu là 137 (= 128 + SIGKILL) thì Linux kernel OOM killer đã kill process vì vượt memory limit.
Đọc log xác nhận
docker inspect <container_id> | jq '.[0].State'
# {
# "OOMKilled": true,
# "ExitCode": 137,
# ...
# }
# Hoặc
docker stats --no-stream
Trên Kubernetes:
kubectl describe pod <pod-name>
# Containers:
# app:
# Last State: Terminated
# Reason: OOMKilled
# Exit Code: 137
Nguyên nhân phổ biến
- Memory leak trong application code
- Node.js heap limit thấp hơn container limit
- Cache không có TTL hoặc eviction policy
- N+1 query load quá nhiều data vào memory
Cách fix
Set memory limit phù hợp
# docker-compose.yml
services:
app:
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 256M
Tune Node.js heap size
ENV NODE_OPTIONS="--max-old-space-size=400"
# Để 80% của container memory limit cho Node heap
# Container 512M → Node heap 400M
Monitor memory usage
// Log memory usage định kỳ
setInterval(() => {
const usage = process.memoryUsage();
logger.log({
heapUsed: Math.round(usage.heapUsed / 1024 / 1024) + 'MB',
heapTotal: Math.round(usage.heapTotal / 1024 / 1024) + 'MB',
rss: Math.round(usage.rss / 1024 / 1024) + 'MB',
});
}, 60000);
Kết luận
OOMKilled thường xảy ra vì 3 nguyên nhân chính: memory leak trong code, Node.js heap limit không được set phù hợp với container limit, hoặc load quá nhiều data vào memory cùng lúc.
Checklist xử lý:
- Xác nhận OOMKilled qua
docker inspecthoặckubectl describe pod - Set
--max-old-space-sizebằng ~80% memory limit của container - Thêm memory monitoring để theo dõi trend
- Nếu heap tăng liên tục không giảm → có memory leak, dùng
node --inspect+ Chrome DevTools để profile heap snapshot