Vấn Đề Khiến Tôi Mất Ngủ Lúc 3 Giờ Sáng
Vài tháng sau khi đưa hệ thống microservices lên production, tôi bắt đầu nhận được phàn nàn từ người dùng — trang web load chậm, API timeout, kết nối bị ngắt giữa chừng. CPU và RAM trông hoàn toàn bình thường trên Zabbix. Disk I/O? Không có gì bất thường. Chẳng tìm ra nguyên nhân rõ ràng nào.
Hóa ra các server đang âm thầm bão hòa băng thông mạng trong giờ cao điểm. Packet bị drop, TCP retransmit tăng vọt, mà chúng tôi không hề hay biết. Hệ thống giám sát lúc đó đơn giản là không thu thập được network-layer metrics với đủ độ chi tiết và tốc độ cần thiết.
Trải nghiệm đó buộc tôi phải xây lại toàn bộ observability stack từ đầu — Prometheus và Grafana, tập trung đặc biệt vào mạng. Ba tháng sau: không còn những đợt chậm bí ẩn nữa, và alert bắn trước khi người dùng nhận ra vấn đề từ hai đến bốn phút.
Nguyên Nhân Gốc Rễ: Điều Hầu Hết Các Monitoring Setup Bỏ Sót
Giám sát hệ thống thông thường chỉ bao gồm CPU, memory và disk. Mạng thì được xử lý qua loa — băng thông vào/ra, có thể thêm ping latency. Vậy là quá ít để chẩn đoán vấn đề thực sự. Bạn cần những metrics như:
- TCP retransmit — giá trị cao cho thấy tắc nghẽn hoặc mất packet ở upstream
- Network error và drop theo từng interface — vấn đề driver, cáp kém, NIC cấu hình sai
- Trạng thái kết nối — quá nhiều socket TIME_WAIT hoặc CLOSE_WAIT có thể làm cạn kiệt ephemeral port
- Mức sử dụng băng thông theo từng interface — không chỉ tổng thể, mà là xu hướng từng interface theo thời gian
- Độ sâu socket queue — receive/send buffer overflow sẽ âm thầm mất dữ liệu
Linux đã phơi bày tất cả thông tin này qua /proc/net/ và /proc/sys/net/. node_exporter của Prometheus thu thập tự động. Bạn chỉ cần kết nối đúng cách.
So Sánh Các Giải Pháp: Dùng Gì và Tại Sao
Lựa chọn 1: netdata
Netdata cài nhanh và có dashboard đẹp sẵn. Tôi đã dùng nó từ đầu. Vấn đề là: nó được tối ưu cho việc xem real-time, không phải lưu trữ dài hạn hay tích hợp alerting. Việc tương quan sự kiện mạng với application log trở nên rất khó khi không có ngôn ngữ truy vấn thực sự.
Lựa chọn 2: Telegraf + InfluxDB + Grafana (TIG Stack)
Đây là lựa chọn tốt, đặc biệt nếu bạn đã dùng InfluxDB. Telegraf có plugin network input mạnh. Nhưng license của InfluxDB thay đổi vào năm 2023, và chi phí vận hành thêm một time-series DB riêng bên cạnh Prometheus không đáng với chúng tôi.
Lựa chọn 3: Prometheus + node_exporter + Grafana (Khuyến nghị)
Đây là thứ tôi gắn bó. node_exporter được duy trì bởi chính dự án Prometheus — nó cung cấp hàng trăm Linux kernel metric bao gồm toàn bộ network stats, và tích hợp nguyên bản với Grafana và Alertmanager. PromQL cho bạn sự linh hoạt để xây dựng bất kỳ query nào cần thiết, từ theo dõi băng thông đơn giản đến tính toán tỷ lệ retransmit phức tạp.
Cách Tốt Nhất: Hướng Dẫn Từng Bước
Bước 1: Cài node_exporter trên Linux Host
Tải bản release mới nhất từ GitHub và chạy như một systemd service:
# Tải về và giải nén
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.1/node_exporter-1.8.1.linux-amd64.tar.gz
tar xvf node_exporter-1.8.1.linux-amd64.tar.gz
sudo mv node_exporter-1.8.1.linux-amd64/node_exporter /usr/local/bin/
# Tạo systemd service
sudo useradd --no-create-home --shell /bin/false node_exporter
cat <<EOF | sudo tee /etc/systemd/system/node_exporter.service
[Unit]
Description=Prometheus Node Exporter
After=network.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter \\
--collector.netstat \\
--collector.netdev \\
--collector.conntrack \\
--collector.sockstat
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
Kiểm tra xem service đã chạy và đang cung cấp metrics chưa:
curl http://localhost:9100/metrics | grep node_network
Bước 2: Cấu Hình Prometheus để Scrape node_exporter
Thêm scrape job vào prometheus.yml:
scrape_configs:
- job_name: 'linux-nodes'
scrape_interval: 15s
static_configs:
- targets:
- '192.168.1.10:9100'
- '192.168.1.11:9100'
labels:
env: 'production'
region: 'ap-northeast-1'
Reload Prometheus sau khi chỉnh sửa:
sudo systemctl reload prometheus
# Hoặc qua HTTP API:
curl -X POST http://localhost:9090/-/reload
Bước 3: Các Network Metric Quan Trọng Cần Query
Đây là những PromQL query tôi dùng đầu tiên khi chẩn đoán sự cố mạng:
Băng thông nhận/gửi theo từng interface (bytes/giây):
rate(node_network_receive_bytes_total{device!~"lo|veth.*"}[5m]) * 8
Tỷ lệ packet drop (nghiêm trọng — nên gần bằng không):
rate(node_network_receive_drop_total[5m])
rate(node_network_transmit_drop_total[5m])
Tỷ lệ TCP retransmit:
rate(node_netstat_Tcp_RetransSegs[5m])
Kết nối đang hoạt động theo trạng thái (TIME_WAIT, ESTABLISHED, v.v.):
node_sockstat_TCP_tw # TIME_WAIT
node_sockstat_TCP_inuse # Kết nối ESTABLISHED
node_sockstat_sockets_used # Tổng số socket đang dùng
Lỗi NIC — hữu ích để phát hiện vấn đề phần cứng hoặc driver:
rate(node_network_receive_errs_total[5m])
rate(node_network_transmit_errs_total[5m])
Bước 4: Xây Dựng Grafana Dashboard
Không cần xây từ đầu — hãy import dashboard ID 1860 (Node Exporter Full) từ thư viện chính thức của Grafana. Dashboard này bao gồm hầu hết Linux system metric kể cả mạng, và là nền tảng tốt để bạn tùy chỉnh thêm.
Với dashboard tập trung vào mạng, hãy xây các panel dựa trên cấu hình sau:
- Panel 1 — Băng thông theo interface: Dùng query
rate(node_network_receive_bytes_total), kiểu hiển thị: Time series, đơn vị: bytes/giây - Panel 2 — Tỷ lệ Drop/Error: Chồng drop nhận và drop gửi, đường ngưỡng tại 1 pkt/giây
- Panel 3 — TCP retransmit: Single stat hiển thị tỷ lệ 5 phút, màu đỏ khi vượt 10/giây
- Panel 4 — Trạng thái socket: Gauge cho TIME_WAIT với ngưỡng tại 10.000
Bước 5: Thiết Lập Alerting Rule
Tạo file network_alerts.yml vào thư mục cấu hình Prometheus:
groups:
- name: network
rules:
- alert: HighPacketDropRate
expr: rate(node_network_receive_drop_total[5m]) > 10
for: 2m
labels:
severity: warning
annotations:
summary: "Tỷ lệ packet drop cao trên {{ $labels.instance }}"
description: "Interface {{ $labels.device }} đang drop {{ $value | humanize }} packets/giây"
- alert: HighTCPRetransmits
expr: rate(node_netstat_Tcp_RetransSegs[5m]) > 50
for: 3m
labels:
severity: critical
annotations:
summary: "TCP retransmit bùng phát trên {{ $labels.instance }}"
- alert: NetworkInterfaceSaturated
expr: |
rate(node_network_transmit_bytes_total{device!~"lo|veth.*"}[5m]) * 8
/ node_network_speed_bytes{device!~"lo|veth.*"} > 0.85
for: 5m
labels:
severity: warning
annotations:
summary: "NIC sắp bão hòa trên {{ $labels.instance }} / {{ $labels.device }}"
- alert: TooManyTimeWaitSockets
expr: node_sockstat_TCP_tw > 15000
for: 10m
labels:
severity: warning
annotations:
summary: "Quá nhiều socket TIME_WAIT — có thể bị rò rỉ kết nối"
Tham chiếu file này trong prometheus.yml:
rule_files:
- "/etc/prometheus/network_alerts.yml"
Kinh Nghiệm Thực Tế Khi Vận Hành
Loại Trừ Virtual Interface Khỏi Network Panel
Docker và systemd-networkd tạo ra hàng chục interface veth, br-, và docker0. Chúng sẽ làm rối mọi dashboard. Loại trừ chúng bằng regex trong query:
rate(node_network_receive_bytes_total{device!~"lo|veth.*|br-.*|docker.*"}[5m])
Tương Quan Packet Drop với System Load
Khi packet drop tăng đột biến, câu hỏi đầu tiên là: lỗi NIC hay lỗi CPU? Thời gian CPU softirq cao đi kèm với packet drop thường có nghĩa là interrupt handler không xử lý kịp. Lúc đó, hãy kiểm tra NIC interrupt affinity hoặc bật RSS (Receive Side Scaling):
# Kiểm tra phân phối interrupt trên các CPU
cat /proc/interrupts | grep eth0
# Đặt interrupt affinity (ví dụ: phân tán IRQ của eth0 sang các core 0-3)
echo 0f > /proc/irq/$(grep eth0 /proc/interrupts | awk '{print $1}' | tr -d ':')/smp_affinity
Theo Dõi Tình Trạng Cạn Kiệt Conntrack Table
Trên server bận, bảng theo dõi kết nối netfilter bị đầy và âm thầm drop các kết nối mới. Đây là một trong những chế độ lỗi khó chịu nhất tôi từng gặp — không có thông báo lỗi rõ ràng, chỉ là các request bị hỏng một cách bí ẩn. Hãy theo dõi tỷ lệ sử dụng:
# Cảnh báo nếu vượt 80%
node_nf_conntrack_entries / node_nf_conntrack_entries_limit
Liên tục vượt 70%? Hãy tăng giới hạn lên:
sysctl -w net.netfilter.nf_conntrack_max=262144
echo 'net.netfilter.nf_conntrack_max = 262144' >> /etc/sysctl.d/99-conntrack.conf
Dùng Recording Rule cho Query Nặng
Network metric sinh ra cardinality cao rất nhanh — nhiều interface trên nhiều host. Hãy tính trước các query tốn kém dưới dạng recording rule để dashboard Grafana luôn phản hồi nhanh:
groups:
- name: network_recording
interval: 30s
rules:
- record: instance:node_network_transmit_bytes:rate5m
expr: sum by (instance) (rate(node_network_transmit_bytes_total{device!~"lo|veth.*"}[5m]))
Stack Trông Như Thế Nào Sau Vài Tháng
Vận hành stack này vài tháng thay đổi cách bạn nhìn về hạ tầng. Không chỉ là phản ứng với sự cố nhanh hơn — bạn bắt đầu lập kế hoạch năng lực thực sự. Tôi có thể thấy server nào sắp bão hòa băng thông NIC trước một tuần, phát hiện dịch vụ có pattern TCP retransmit bất thường sau khi deploy, và theo dõi xem kernel update có làm thay đổi hành vi mạng không.
node_exporter bao quát chiều rộng, PromQL cho bạn sự linh hoạt để cắt lát theo bất kỳ chiều nào cần thiết, và Grafana kết nối tất cả lại một cách trực quan. Toàn bộ stack chạy trên một VM 2-vCPU/4GB xử lý scrape từ hơn 20 node mà không hề vã mồ hôi — hoàn toàn xứng đáng với chi phí setup ban đầu.

