Bắt đầu nhanh: Triển khai hoàn tất trong 5 phút
Sáu tháng trước, đội ngũ hạ tầng của chúng tôi đã gỡ bỏ hoàn toàn một cụm Elasticsearch gồm 3 node – hệ thống vốn ngốn tới 48 GB RAM chỉ để duy trì bộ nhớ đệm cho search index. Thay thế vào đó, chúng tôi triển khai Grafana Loki và Rsyslog. Kiến trúc mới xử lý mượt mà khoảng 8.500 sự kiện syslog mỗi giây từ hơn 120 thiết bị mạng—bao gồm switch Cisco Catalyst 9300, cụm FortiGate 200F và router biên MikroTik CCR—trong khi chỉ tiêu tốn chưa đầy 4 GB RAM.
Bạn hoàn toàn có thể dựng một pipeline thu thập log tương tự trên Ubuntu 22.04 hoặc 24.04 LTS chỉ trong vài phút bằng Docker Compose.
Bước 1: Triển khai Loki và Grafana
Đầu tiên, hãy tạo một thư mục dự án có tên network-logging và lưu tệp docker-compose.yml sau:
version: "3.8"
services:
loki:
image: grafana/loki:2.9.4
container_name: loki
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
volumes:
- ./loki-data:/loki
restart: unless-stopped
promtail:
image: grafana/promtail:2.9.4
container_name: promtail
volumes:
- /var/log/network:/var/log/network:ro
- ./promtail-config.yaml:/etc/promtail/config.yaml:ro
command: -config.file=/etc/promtail/config.yaml
restart: unless-stopped
grafana:
image: grafana/grafana:10.4.1
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=adminpass
restart: unless-stopped
Bước 2: Gắn Rsyslog vào cổng UDP/TCP 514
Tiếp theo, cấu hình Rsyslog ở cấp hệ điều hành (host) để tiếp nhận lưu lượng mạng gửi đến. Hãy dán đoạn cấu hình sau vào tệp mới tại /etc/rsyslog.d/10-network-input.conf:
module(load="imudp")
input(type="imudp" port="514")
module(load="imtcp")
input(type="imtcp" port="514")
# Phân tách log nhận được theo IP thiết bị: /var/log/network/<DEVICE_IP>/syslog.log
template(name="NetLogPath" type="string" string="/var/log/network/%fromhost-ip%/syslog.log")
*.* ?NetLogPath
& stop
Thiết lập quyền truy cập thư mục và khởi động lại dịch vụ:
sudo mkdir -p /var/log/network
sudo chmod -R 755 /var/log/network
sudo systemctl restart rsyslog
Bước 3: Trỏ Promtail đến các tệp Syslog
Promtail sẽ theo dõi (tail) các tệp log thô trên đĩa, gắn thêm nhãn metadata và đẩy các batch nén dữ liệu vào Loki. Lưu cấu hình này thành promtail-config.yaml trong thư mục dự án của bạn:
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: network_syslog
static_configs:
- targets:
- localhost
labels:
job: network_devices
__path__: /var/log/network/*/*.log
pipeline_stages:
- regex:
expression: '^/var/log/network/(?P<device_ip>[^/]+)/.*\.log$'
source: filename
- labels:
device_ip: ""
Khởi chạy các container:
docker compose up -d
Mở Grafana tại http://<your-server-ip>:3000. Đăng nhập với tài khoản admin / adminpass, thêm Loki (http://loki:3100) làm nguồn dữ liệu (data source), sau đó truy vấn luồng log với câu lệnh {job="network_devices"}.
Đi sâu vào chi tiết: Kiến trúc và Cơ chế Pipeline
Các công cụ truyền thống như Elasticsearch hay OpenSearch thường phân tích cú pháp chuỗi văn bản nhận được thành các inverted index. Cách tiếp cận này hiệu quả cho các câu truy vấn tìm kiếm tùy biến. Tuy nhiên, nó nhanh chóng bộc lộ điểm yếu khi các firewall phát sinh tới 40.000 sự kiện drop gói tin mỗi giây trong các đợt rà quét diện rộng trên Internet. Mức sử dụng RAM tăng vọt, ổ cứng nghẽn I/O liên tục, và việc duy trì cụm máy chủ biến thành một công việc toàn thời gian đầy áp lực.
Tại sao nên dùng Rsyslog làm cổng tiếp nhận tuyến đầu?
Rsyslog được viết bằng C và hoạt động sát tầng kernel ở không gian người dùng (user space). Nhờ đó, nó có khả năng tiếp nhận các gói UDP tần suất cao hiệu quả hơn rất nhiều so với các collector viết bằng Java hay Go như Logstash hay Vector. Ngay cả khi một switch truy cập bị hiện tượng link flapping dữ dội, Rsyslog vẫn lưu giữ các dòng log an toàn trong bộ đệm vòng (ring buffer) trên RAM mà không làm quá tải các nhân CPU.
Triết lý của Loki: Đánh chỉ mục nhãn, không đánh chỉ mục nội dung
Loki đảo ngược hoàn toàn mô hình đánh chỉ mục truyền thống. Nó giữ nguyên phần thân log, nén gzip thành từng chunk rồi ghi trực tiếp xuống đĩa hoặc lưu trữ tương thích S3. Loki chỉ đánh chỉ mục các nhãn metadata của luồng: job, device_ip và environment.
Lựa chọn thiết kế này đã giúp chúng tôi giảm dung lượng lưu trữ từ 1,2 TB xuống chỉ còn khoảng 140 GB mỗi tháng. Tốc độ truy vấn vẫn rất nhanh do Grafana phân tán việc lọc theo kiểu grep song song qua các ranh giới chunk dữ liệu.
Hướng dẫn cấu hình thiết bị
Cấu hình các thiết bị mạng của bạn để chuyển tiếp sự kiện về máy chủ Ubuntu qua cổng 514:
# Cisco IOS / IOS-XE
logging host 192.168.10.50 transport udp port 514
logging trap informational
logging facility local6
logging source-interface GigabitEthernet0/0
# Fortinet FortiGate (CLI)
config log syslogd setting
set status enable
set server "192.168.10.50"
set mode udp
set port 514
set facility local7
set format default
end
# MikroTik RouterOS v7
/system logging action add name=central-syslog target=remote remote=192.168.10.50 remote-port=514 src-address=192.168.10.1
/system logging add action=central-syslog topics=critical,error,warning,info
Sử dụng nâng cao: Phân tích cú pháp và Cảnh báo với LogQL
Các luồng log văn bản thô sẽ phát huy sức mạnh vượt trội khi bạn phân tích cú pháp và lọc chúng theo yêu cầu ngay trong Grafana.
Trích xuất trường dữ liệu khi đọc (Extract on Read)
Các dòng syslog của Cisco tuân theo định dạng rất rõ ràng: %FACILITY-SEVERITY-MNEMONIC: Description. Thay vì phải định nghĩa schema mapping từ trước, bạn có thể phân tích các trường ngay tại thời điểm truy vấn bằng pattern matching trong LogQL:
{device_ip="192.168.10.1"}
|= "%LINK-3-UPDOWN:"
| pattern "<_> %LINK-3-UPDOWN: Interface <interface>, changed state to <status>"
Câu truy vấn này trích xuất trực tiếp các trường interface và status trong tích tắc. Bạn có thể đưa thẳng chúng vào một panel dạng bảng (table panel) trên Grafana để nhận diện các cổng mạng đang bị chập chờn (flapping) trong toàn bộ khu vực campus.
Tạo chuỗi số liệu (Metric Stream) từ log thô
Bạn cũng có thể tổng hợp log thô thành các chuỗi thời gian (time series) tương tự như Prometheus:
sum by (device_ip) (
rate({job="network_devices"} |= "action=deny" [1m])
)
Biểu thức này tính toán số lượng gói tin bị firewall drop mỗi giây trên từng thiết bị. Bất kỳ sự tăng đột biến nào cũng sẽ giúp phát hiện các cuộc quét mã độc nội bộ hay tấn công brute-force ở vùng biên chỉ trong vài giây.
Cấu hình quy tắc cảnh báo thời gian thực
Phát hiện sự cố định tuyến tức thì bằng cách thêm quy tắc cảnh báo vào cấu hình Loki của bạn:
groups:
- name: network-alerts
rules:
- alert: BGPNeighborDown
expr: |
count_over_time({job="network_devices"} |= "%BGP-5-ADJCHANGE:" |= "Down" [2m]) > 0
for: 0m
labels:
severity: critical
annotations:
summary: "Phiên BGP peer bị ngắt kết nối trên {{ $labels.device_ip }}"
Kinh nghiệm thực tế: Gia cố và Tối ưu hóa cho Production
Vận hành pipeline này trong môi trường thực tế đã làm lộ ra ba điểm nghẽn hiệu năng mà bạn nên xử lý sớm.
1. Tránh sử dụng nhãn có độ biến thiên cao (High-Cardinality Labels)
Tuyệt đối không trích xuất các giá trị động như địa chỉ IP client từ xa, địa chỉ MAC hay cổng TCP thành các nhãn trong Promtail. Loki tạo ra một stream chỉ mục riêng biệt cho mỗi tổ hợp nhãn duy nhất. Mười nghìn địa chỉ IP client riêng biệt sẽ nhanh chóng tạo ra mười nghìn stream, khiến chỉ mục của Loki phình to bất thường và kéo tụt tốc độ tìm kiếm. Hãy chỉ dùng các nhãn có độ biến thiên thấp như site, role và device_ip.
2. Tối ưu bộ đệm Socket UDP cho Rsyslog
Khi có lưu lượng đột biến, Linux kernel sẽ âm thầm drop các gói tin UDP gửi đến nếu bộ đệm nhận (receive buffer) của hệ điều hành bị bão hòa. Kiểm tra số lượng gói tin bị drop bằng lệnh sau:
netstat -su | grep "receive errors"
Nếu con số này liên tục tăng, hãy nâng bộ đệm nhận của kernel lên 25 MB trong /etc/sysctl.d/99-syslog.conf:
net.core.rmem_default = 26214400
net.core.rmem_max = 26214400
Áp dụng giá trị sysctl mới mà không cần khởi động lại máy chủ:
sudo sysctl -p /etc/sysctl.d/99-syslog.conf
3. Thiết lập chính sách lưu trữ (Retention) trong Compactor
Các thiết bị mạng tạo ra khối lượng log vận hành khổng lồ. Hãy đặt khoảng thời gian lưu trữ rõ ràng trong loki-config.yaml để dọn dẹp các chunk cũ và giải phóng dung lượng ổ đĩa:
compactor:
working_directory: /loki/compactor
compactor_ring:
kvstore:
store: inmemory
retention_enabled: true
schema_config:
configs:
- from: 2024-01-01
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
retention_period: 30d
Cấu hình này giữ cho dung lượng ổ cứng NVMe luôn trong tầm kiểm soát, đồng thời vẫn bảo đảm 30 ngày lưu trữ dữ liệu kiểm toán sạch sẽ, dễ tra cứu để phục vụ tuân thủ quy định.

