Điều tra CPU, bộ nhớ, ổ đĩa và mạng
Thực hiện trên server của bạn, rồi kiểm tra từng tiêu chí.
Vì sao cần học
"Server chậm" là báo cáo mơ hồ nhất bạn sẽ nhận. Phải trả lời được nhanh: chậm vì CPU, bộ nhớ, ổ đĩa hay mạng? Do tiến trình nào? Phản xạ kill -9 tiến trình nặng nhất có thể giết đúng job báo cáo cuối tháng mà kế toán đang chờ. Cách tốt hơn là giới hạn nó để dịch vụ chính có tài nguyên.
Mục tiêu
- Đọc load average, CPU, bộ nhớ, swap, I/O và socket bằng
uptime,top,vmstat,free,ps,df,ss. - Phân biệt "CPU bận" với "đang chờ I/O" (
wa) và "thiếu bộ nhớ" (swap, OOM). - Giới hạn tài nguyên của một dịch vụ bằng drop-in systemd (
CPUQuota,Nice,MemoryMax). - Ghi lại số liệu trước và sau khi xử lý.
Điều kiện tiên quyết
- Bài Tiến trình, signal và độ ưu tiên và Vận hành web service bằng systemd.
Mental model
Đi theo thứ tự USE cho từng tài nguyên: Utilization (dùng bao nhiêu), Saturation (có hàng đợi không), Errors (có lỗi không).
| Tài nguyên | Xem nhanh | Dấu hiệu bão hòa |
|---|---|---|
| CPU | top, mpstat, uptime | load average > số core, %us/%sy cao |
| Bộ nhớ | free -h, ps --sort=-rss | available thấp, swap tăng, OOM trong journalctl -k |
| Ổ đĩa | df -h, vmstat 1 | wa cao, b (tiến trình chờ I/O) > 0 |
| Mạng | ss -s, ss -tnp, ip -s link | nhiều kết nối SYN-SENT/TIME-WAIT, lỗi/drop tăng |
Load average là số tiến trình đang chạy hoặc chờ chạy (kể cả chờ I/O), trung bình 1, 5, 15 phút. So với số core: load 4 trên máy 2 core nghĩa là hàng đợi dài gấp đôi khả năng xử lý.
systemd đặt mỗi dịch vụ vào một cgroup. CPUQuota=20% giới hạn dịch vụ ở 20% của một core. MemoryMax= giới hạn bộ nhớ. Giới hạn áp dụng cho mọi tiến trình con của dịch vụ.
Thực hành (Guided Lab)
1. Chuẩn bị sự cố
Lưu vào ~/prepare-resources.sh, đọc qua, chạy sudo bash ~/prepare-resources.sh.
#!/usr/bin/env bash
# KDC lab: resources. Tạo một job báo cáo ăn hết một core CPU.
set -euo pipefail
[[ $EUID -eq 0 ]] || { echo "Chạy bằng sudo." >&2; exit 1; }
grep -qs '^KDC-LAB' /etc/kdc-lab || { echo "Không thấy marker /etc/kdc-lab; script chỉ chạy trên máy lab." >&2; exit 1; }
install -d -m 755 /opt/kdc-burn
cat > /opt/kdc-burn/kdc-burn <<'EOF'
#!/usr/bin/bash
# Monthly report job: tính toán liên tục.
while :; do :; done
EOF
chmod 755 /opt/kdc-burn/kdc-burn
rm -rf /etc/systemd/system/kdc-burn.service.d
cat > /etc/systemd/system/kdc-burn.service <<'EOF'
[Unit]
Description=KDC monthly report job
[Service]
ExecStart=/opt/kdc-burn/kdc-burn
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now kdc-burn.service
echo "Job đã chạy. Bắt đầu từ: uptime"
Giải thích lệnh và tham số
Script dùng Bash và các cấu trúc đã học ở bài tiến trình và bài shell. while :; do :; done lặp liên tục không có sleep, vì vậy cố ý chiếm một core CPU. rm -rf ...service.d xóa drop-in lab cũ để phép đo bắt đầu chưa có giới hạn.
Đọc script, lưu file rồi sudo bash ~/prepare-resources.sh trên VM lab.
2. Thu thập số liệu "trước"
nproc
uptime
top -b -n 1 | head -15
ps -eo pid,ni,%cpu,%mem,etime,comm --sort=-%cpu | head -5
vmstat 1 5
free -h
df -h /
ss -s
Giải thích lệnh và tham số
| Lệnh / tùy chọn | Ý nghĩa |
|---|---|
nproc | In số CPU logic khả dụng cho tiến trình đang chạy. |
uptime | In thời gian máy chạy và load average 1, 5, 15 phút. |
ps -eo ... --sort=-%cpu | -e chọn mọi tiến trình, -o chọn cột, --sort=-%cpu sắp xếp CPU giảm dần. %mem là tỷ lệ RAM, etime là thời gian đã chạy. |
vmstat 1 5 | Lấy số liệu với khoảng cách 1 giây, tổng 5 lần; dòng đầu thường là trung bình từ boot, các dòng sau là khoảng đo. |
ss -s | In thống kê socket tổng hợp; -s ở ss khác silent của curl. |
top -b -n 1, free -h, df -h dùng ý nghĩa đã học: snapshot batch và đơn vị dễ đọc.
Tìm tiến trình chiếm CPU và unit sở hữu nó:
pid=$(pgrep -x kdc-burn)
ps -o pid,unit,cmd -p "$pid"
systemd-cgtop -n 1 -b | head -8
Giải thích lệnh và tham số
pid=$(pgrep -x kdc-burn) lưu PID vào biến. ps ... -p "$pid" chỉ xem PID đó; cột unit cho biết dịch vụ sở hữu, cmd là dòng lệnh. systemd-cgtop -n 1 -b xem sử dụng tài nguyên theo cgroup: một lần cập nhật (-n 1), chế độ batch (-b). Nếu VM chưa có vmstat, cài package procps-ng; mpstat trong phần mental model thuộc package sysstat.
Tạo ~/kdc-labs/resources/findings.md và ghi số liệu vừa đo vào hai mục ## CPU và ## Bộ nhớ.
3. Giới hạn bằng drop-in
sudo systemctl edit kdc-burn.service cũng tạo drop-in, nhưng đặt tên override.conf. Bài này dùng tên limits.conf để rõ mục đích, nên tạo trực tiếp:
sudo install -d /etc/systemd/system/kdc-burn.service.d
sudo tee /etc/systemd/system/kdc-burn.service.d/limits.conf <<'EOF'
[Service]
CPUQuota=20%
Nice=10
EOF
sudo systemctl daemon-reload
sudo systemctl restart kdc-burn.service
systemctl show kdc-burn.service -p CPUQuotaPerSecUSec -p Nice
systemctl cat kdc-burn.service
Giải thích lệnh và tham số
systemctl show ... -p CPUQuotaPerSecUSec -p Nice in thuộc tính systemd đang dùng. systemctl cat in unit gốc và các drop-in để đối chiếu file nguồn. CPUQuota=20% giới hạn ở 20% một core, Nice=10 giảm ưu tiên; đây là cấu hình lưu trong file, không phải cờ của ps.
Drop-in sửa một phần unit mà không chạm vào file gốc, nên bản cập nhật của package không ghi đè thay đổi của bạn.
4. Số liệu "sau"
sleep 10
top -b -n 1 | head -12
ps -o pid,ni,%cpu,comm -C kdc-burn
uptime
Giải thích lệnh và tham số
sleep 10 chờ 10 giây trước khi đo. top -b -n 1 xuất một snapshot dạng batch, head -12 giữ 12 dòng đầu. ps -o pid,ni,%cpu,comm chọn cột; -C kdc-burn lọc tiến trình theo tên.
%CPU của kdc-burn quanh 20%, cột NI là 10, load average giảm dần sau vài phút. Ghi kết quả vào findings.md.
5. Bộ nhớ (tham khảo)
free -h
ps -eo pid,rss,comm --sort=-rss | head -5
journalctl -k | grep -i -E 'out of memory|oom' | tail -3
Giải thích lệnh và tham số
rss trong ps là bộ nhớ resident (KiB trên Linux); --sort=-rss xếp tiến trình dùng RSS lớn nhất lên trước. journalctl -k chỉ log kernel; grep -i -E 'out of memory|oom' tìm một trong hai mẫu không phân biệt hoa/thường. ip -s link ở bảng mental model in thống kê interface; ss -tnp xem TCP (-t), IP/port số (-n) và tiến trình (-p).
available mới là bộ nhớ còn dùng được; free thấp là bình thường vì Linux dùng RAM trống làm cache.
Tự kiểm tra (Verification)
systemctl is-active kdc-burn
ps -o pid,ni,%cpu,comm -C kdc-burn
cat ~/kdc-labs/resources/findings.md
Giải thích lệnh và tham số
systemctl is-active xem service đang chạy không. ps -o pid,ni,%cpu,comm chọn PID, nice, phần trăm CPU và tên; -C kdc-burn chỉ xem tiến trình lab. cat đọc báo cáo.
Chọn server và bấm Kiểm tra kết quả.
Lỗi thường gặp
renicehoặc giới hạn bằng tay: mất khi dịch vụ restart. Đặt trong unit.- Sửa drop-in mà quên
daemon-reloadvàrestart. - Nhìn
%CPUtrongtopvượt 100%: trên máy nhiều core, 100% là một core. - Kết luận "thiếu RAM" vì
freegần 0: xem cộtavailable.
Ghi chú production
- Giới hạn tài nguyên cho job phụ là cách bảo vệ dịch vụ chính. Kubernetes làm điều tương tự bằng
requests/limitsdựa trên cùng cơ chế cgroup (Module 13). - Lưu số liệu theo thời gian (Module 17) để trả lời "từ khi nào chậm?", thay vì chỉ có ảnh chụp lúc đang sự cố.
Dọn dẹp
sudo systemctl disable --now kdc-burn.service
sudo rm -rf /etc/systemd/system/kdc-burn.service /etc/systemd/system/kdc-burn.service.d /opt/kdc-burn
sudo systemctl daemon-reload
Giải thích lệnh và tham số
systemctl disable --now bỏ cấu hình tự chạy khi boot và dừng service ngay. daemon-reload yêu cầu systemd đọc lại unit file sau khi sửa/xóa. rm -f xóa file và không hỏi xác nhận; -r thêm xóa đệ quy thư mục cùng nội dung, nên -rf gộp hai tùy chọn này.