Sau bài này bạn làm được: đọc ps/top để biết process đang chờ gì; gửi đúng tín hiệu (TERM vs KILL); hiểu vì sao app “bị kill không báo”; đọc sơ cgroup v2 và thấy đường nối tới limit trong container orchestrator.


Process là inode sống: PID, PPID, state

ps auxww | head
ps -eo pid,ppid,stat,cmd --sort=pid | tail

Cột STAT (ví dụ):

  • S sleeping interruptible
  • R running
  • D uninterruptible sleep (thường I/O kernel — khó kill)
  • Z zombie (đã exit nhưng parent chưa wait)

Zombie: không “ăn” RAM như process sống, nhưng chiếm slot PID; parent bug có thể làm cạn PID space hiếm gặp nhưng đau.


Tín hiệu: SIGTERM là yêu cầu, SIGKILL là án tử hình

SignalHành vi điển hình
SIGTERM (15)Daemon bắt được, graceful shutdown
SIGINT (2)Ctrl+C — tương tự graceful cho CLI
SIGKILL (9)Kernel kill ngay — không bắt được để dọn resource userspace

Ops: kill -9 là biện pháp cuối; nếu process ở D state, kill có thể không giải quyết — cần kernel/fs fix hoặc reboot node.

kill -TERM "$PID"
sleep 2
kill -0 "$PID" 2>/dev/null && echo still_alive

OOM killer: khi kernel phải chọn nạn nhân

Khi RAM+cấu hình overcommit đẩy hệ thống tới wall, OOM killer có thể chọn process để kill để cứu hệ thống.

# Xem log OOM (journald)
journalctl -k --grep -i oom --no-pager | tail
dmesg -T | grep -i oom | tail

Giảm thiểu: MemoryMax= / MemoryHigh= trong systemd; cgroup limit trong K8s; tuning JVM/Go heap; swap (trade-off latency).


ulimit/etc/security/limits.conf

ulimit điều chỉnh giới hạn per-session / PAM — dễ gây nhầm với cgroup.

ulimit -n
# số file descriptor mở tối đa cho shell hiện tại

Ứng dụng: reverse proxy mở nhiều connection — thiếu nofile gây too many open files. Chỉnh:

  • systemd: LimitNOFILE= trong unit
  • /etc/security/limits.d/*.conf cho login session (PAM)

Kiểm tra limit thực của process:

PID=$(pgrep -f nginx | head -1)
tr '\0' '\n' < /proc/$PID/limits

cgroup: nhóm process + giới hạn tài nguyên

cgroup v1 nhiều hierarchy; cgroup v2 (unified) là mặc định trên kernel mới — Docker/K8s hiện đại dựa trên v2.

# Mount và controllers (tóm tắt)
findmnt -no TARGET /sys/fs/cgroup
ls /sys/fs/cgroup | head

Ý tưởng: mỗi group có file knob như memory.max, cpu.max. systemd tạo slice (user.slice, system.slice) và scope cho service.

systemctl show nginx.service -p MemoryCurrent -p MemoryMax --no-pager

Namespace nhanh (để không nhầm với cgroup)

  • cgroup giới hạn tài nguyên.
  • namespace cô lập quan điểm (mount, PID, net, user…).

Container = cgroup + namespaces (+ capabilities, seccomp…).


nice / ionice — ưu tiên mềm

Chúng điều chỉnh scheduling chứ không hard-cap như cgroup CPU quota. Hữu ích cho batch job trên node chia sẻ nhưng không thay thế limit cho multi-tenant.


Liên hệ bài trước / sau


Câu hỏi hay gặp

1. “top hiện load average cao nhưng CPU idle?”
Uninterruptible I/O (D), hoặc runnable threads chờ CPU khác — đọc vmstat 1, iostat -xz.

2. “Container limit 512Mi nhưng free -h trong container vẫn thấy RAM host?”
free trong container thường phản ánh cgroup view tuỳ libc/tooling — đừng tin một lệnh; dùng cat /sys/fs/cgroup/memory.current (đường dẫn cgroup đổi theo runtime).

3. “Tôi nên set LimitNOFILE bao nhiêu?”
Đo từ workload + hệ số an toàn; “một tỉ” có thể làm overhead kernel; benchmark thực tế.


Bài tiếp theo trong loạt

Phần 7: Lưu trữ — disk, inode, filesystem — khi df báo còn dung lượng nhưng không ghi được file.