Khi chỉ có một VPS, đọc log bằng `journalctl`, `tail` hoặc `docker logs` vẫn khá ổn. Nhưng khi số máy tăng, việc SSH từng VPS để tìm lỗi trở nên chậm và dễ bỏ sót. Grafana Loki lưu log tập trung theo mô hình time-series, còn Grafana Alloy thu thập log từ file, systemd journal hoặc container rồi gửi về Loki. Bài viết này hướng dẫn kiến trúc triển khai đơn giản, cách cấu hình Alloy đọc file log, gửi về Loki và truy vấn trong Grafana, đồng thời lưu ý về bảo mật, label và retention để tránh biến hệ thống log thành một điểm rủi ro mới.
Khi hạ tầng có một VPS, việc SSH vào máy rồi chạy journalctl, tail -f hoặc docker logs vẫn khá nhanh. Nhưng từ vài VPS trở lên, sự cố thường không nằm trên một máy duy nhất: reverse proxy lỗi ở máy A, ứng dụng lỗi ở máy B, database cảnh báo ở máy C.
Lúc đó, log tập trung giúp bạn trả lời nhanh các câu hỏi:
- lỗi bắt đầu lúc nào;
- lỗi xuất hiện trên máy nào;
- cùng một request có gây lỗi ở nhiều service không;
- trước khi CPU/RAM tăng đã có log bất thường nào;
- deployment mới có tạo error pattern mới không.
Một stack phổ biến gồm:
- Grafana Alloy: collector thu log từ file, journal, Docker và nhiều nguồn khác;
- Grafana Loki: lưu và truy vấn log;
- Grafana: giao diện tìm kiếm, dashboard và alert.
Grafana hiện khuyến nghị Alloy cho việc thu thập telemetry; Grafana Agent đã kết thúc vòng đời hỗ trợ từ năm 2025, vì vậy bài này dùng Alloy thay vì hướng dẫn cũ dựa trên Promtail/Agent.
Nếu bạn đã dùng metric monitoring, có thể xem thêm bài Giám sát VPS bằng Prometheus, Node Exporter và Grafana. Metric và log bổ sung cho nhau: metric cho biết có vấn đề, log giúp hiểu vì sao.
Loki khác Elasticsearch thế nào?
Loki không lập index toàn bộ nội dung log theo cách search engine truyền thống thường làm. Thay vào đó, Loki tập trung index label của log stream, còn nội dung dòng log vẫn được lưu và truy vấn bằng LogQL.
Cách tiếp cận này có thể giảm chi phí index cho nhiều workload log, nhưng đổi lại bạn phải thiết kế label hợp lý.
Một nguyên tắc quan trọng:
Label nên có cardinality thấp và mô tả nguồn log, không nên chứa giá trị biến đổi gần như vô hạn.
Ví dụ label tốt:
host="web-01";env="prod";service="nginx";region="hanoi".
Label không tốt:
request_id;user_id;- full URL có query string;
- timestamp;
- IP client động với số lượng rất lớn.
Các giá trị thay đổi mạnh nên nằm trong nội dung log và được parse khi truy vấn thay vì biến thành label.
Kiến trúc log tập trung đơn giản
Ví dụ:
VPS web-01 ─┐
VPS api-01 ─┼─ Alloy ───────┐
VPS db-01 ─┘ │
↓
Loki
↓
Grafana
Có hai mô hình chính:
Alloy chạy trên từng VPS
Mỗi VPS cài Alloy và gửi log về Loki trung tâm.
Ưu điểm:
- đọc được file local và journal trực tiếp;
- dễ thêm label theo hostname;
- không cần mount filesystem từ xa.
Alloy tập trung
Collector ở một nơi nhận syslog hoặc API từ nhiều máy.
Phù hợp khi hệ thống của bạn đã chuẩn hóa log shipping theo network.
Với VPS Linux thông thường, cài Alloy trên từng máy thường dễ hiểu hơn.
Loki có authentication mặc định không?
Grafana Docs lưu ý Loki không tích hợp sẵn authentication layer theo kiểu một admin dashboard hoàn chỉnh.
Điều đó có nghĩa bạn không nên public thẳng port Loki ra Internet mà không có lớp bảo vệ.
Các lựa chọn an toàn hơn:
- private network;
- Tailscale/WireGuard;
- reverse proxy có authentication;
- firewall allow đúng IP Alloy/Grafana;
- Cloudflare Tunnel + Access cho giao diện phù hợp.
Bạn có thể tham khảo bài Dùng Cloudflare Tunnel trên VPS nếu cần xuất bản Grafana qua lớp truy cập riêng thay vì mở trực tiếp port quản trị.
Cài Loki bằng Docker cho lab hoặc môi trường nhỏ
Grafana cung cấp hướng dẫn chạy Loki bằng Docker/Docker Compose để thử nghiệm hoặc môi trường nhỏ.
Tạo thư mục:
mkdir -p /opt/loki
cd /opt/loki
Ví dụ lấy config chính thức tương ứng phiên bản bạn chọn:
wget https://raw.githubusercontent.com/grafana/loki/v3.7.0/cmd/loki/loki-local-config.yaml -O loki-config.yaml
Chạy Loki:
docker run -d \
--name loki \
--restart unless-stopped \
-v /opt/loki:/mnt/config \
-p 127.0.0.1:3100:3100 \
grafana/loki:3.7.0 \
-config.file=/mnt/config/loki-config.yaml
Điểm đáng chú ý ở ví dụ trên là port được bind vào 127.0.0.1, không phải 0.0.0.0.
Kiểm tra readiness:
curl http://127.0.0.1:3100/ready
Nếu cần Alloy từ VPS khác gửi log vào Loki, hãy dùng private IP/reverse proxy phù hợp thay vì public port 3100 trực tiếp.
Với môi trường production lớn, Grafana khuyến nghị các mô hình triển khai production phù hợp hơn thay vì Docker đơn giản trên một node. Đừng áp mô hình lab cho hệ thống log dung lượng lớn mà chưa tính storage và HA.
Cài Grafana Alloy
Grafana Alloy có package/binary cho Linux. Với production, nên dùng repository/package chính thức và cố định phiên bản theo quy trình cập nhật của bạn.
Sau khi cài, kiểm tra:
alloy --version
Alloy sử dụng file cấu hình riêng, thường được quản lý qua systemd khi cài bằng package.
Cấu hình Alloy đọc file log
Grafana Alloy có ba component rất hữu ích cho file log:
local.file_match— tìm file bằng glob;loki.source.file— đọc log;loki.write— gửi log tới Loki.
Ví dụ:
local.file_match "nginx_logs" {
path_targets = [
{
"__path__" = "/var/log/nginx/*.log",
"job" = "nginx",
"host" = constants.hostname,
},
]
}
loki.source.file "nginx" {
targets = local.file_match.nginx_logs.targets
forward_to = [loki.write.central.receiver]
}
loki.write "central" {
endpoint {
url = "http://10.10.0.20:3100/loki/api/v1/push"
}
}
Thay 10.10.0.20 bằng địa chỉ Loki thực tế trong private network.
Grafana Docs khuyến nghị dùng local.file_match hoặc file matching tích hợp để khám phá file theo glob, sau đó loki.source.file đọc các dòng mới và forward tới loki.write.
Đọc systemd journal
Với service chạy bằng systemd, Alloy có source cho journal.
Use case:
- SSH auth;
- Nginx service;
- app chạy systemd;
- Docker daemon;
- kernel/service error.
Một cấu hình thực tế thường thêm label:
- hostname;
- service;
- environment.
Không cần biến mọi field journal thành label.
Thu log Docker
Nếu ứng dụng chạy container, có vài cách:
- Alloy đọc Docker source;
- Alloy đọc file JSON log của Docker;
- Loki Docker logging driver.
Grafana hiện định hướng Alloy là collector chính có mức hỗ trợ tốt hơn Docker logging plugin riêng.
Nếu bạn chạy nhiều container trên một VPS, nên kết hợp với bài Giới hạn CPU và RAM cho Docker trên VPS để tránh một workload lỗi vừa ngốn tài nguyên vừa spam log.
Thêm Grafana và kết nối Loki data source
Trong Grafana:
- vào Connections;
- thêm Loki data source;
- nhập URL Loki;
- Save & test.
Nếu Grafana và Loki cùng host:
http://127.0.0.1:3100
Nếu Grafana chạy trong Docker riêng, 127.0.0.1 là container Grafana chứ không phải host. Khi đó cần dùng Docker network hoặc hostname phù hợp.
Truy vấn log bằng LogQL
Ví dụ lấy toàn bộ log Nginx:
{job="nginx"}
Tìm error:
{job="nginx"} |= "error"
Tìm 500 response nếu access log chứa status:
{job="nginx"} |= " 500 "
Lọc theo host:
{job="nginx", host="web-01"}
LogQL có thể parse JSON, logfmt, regexp và nhiều pipeline stage khác, nhưng nên bắt đầu từ label đơn giản rồi mới parse sâu.
Vì sao label cardinality quá cao là vấn đề?
Nếu mỗi request tạo một label mới như request_id, Loki phải quản lý rất nhiều stream.
Điều này có thể làm:
- tăng memory;
- tăng index overhead;
- query chậm hơn;
- hệ thống khó scale.
Hãy dùng label cho thuộc tính ổn định của nguồn log, còn field chi tiết để trong log body.
Retention: log không nên lưu vô hạn
Nếu giữ log vô hạn, storage sẽ tăng liên tục.
Bạn cần xác định:
- log ứng dụng giữ bao lâu;
- access log cần bao lâu;
- security log cần bao lâu;
- yêu cầu audit/compliance;
- tốc độ tăng GB/ngày.
Ví dụ:
- dev/staging: 7–14 ngày;
- production thông thường: 30–90 ngày;
- audit: tùy chính sách doanh nghiệp.
Đây chỉ là ví dụ, không phải chuẩn bắt buộc.
Theo dõi chính Loki storage để tránh lặp lại tình huống VPS đầy disk. Nếu cần, xem bài VPS Ubuntu bị đầy ổ đĩa.
Đừng gửi secret vào log
Centralized logging làm tăng blast radius nếu log chứa secret.
Không nên log:
- password;
- API key;
- access token;
- session cookie;
- Authorization header;
- private key;
- dữ liệu cá nhân không cần thiết.
Nếu app hiện đang log request body toàn bộ, hãy kiểm tra ngay trước khi gom log tập trung.
Grafana Alloy có pipeline xử lý và các component giúp relabel/process log, nhưng tốt nhất vẫn là không sinh secret vào log ngay từ ứng dụng.
Mô hình nhiều VPS
Ví dụ bạn có:
web-01
web-02
api-01
db-01
monitor-01
Alloy trên từng máy thêm label:
host=web-01
env=prod
service=nginx
Khi có sự cố, bạn có thể truy vấn:
{env="prod", service="nginx"} |= "upstream timed out"
và xem lỗi có xảy ra trên một web node hay toàn bộ cụm.
Đây là giá trị lớn nhất của log tập trung so với SSH từng máy.
Kết hợp metric và log
Một workflow xử lý sự cố tốt:
- Grafana alert CPU tăng;
- mở dashboard metric;
- xác định host
api-01; - mở log cùng time range;
- thấy worker retry liên tục;
- rollback release hoặc sửa downstream dependency.
Metric cho bạn triệu chứng, log cho bạn context.
Sai lầm thường gặp
Public port Loki trực tiếp
Loki không nên được xem như một web app có auth sẵn. Hãy đặt private network hoặc lớp auth phía trước.
Gắn request ID làm label
High cardinality sẽ tạo rất nhiều stream.
Không có retention
Storage tăng không kiểm soát rồi làm chính monitoring server đầy disk.
Gom log nhưng không chuẩn hóa hostname/service
Sau này query sẽ rất khó khi mỗi máy dùng naming khác nhau.
Log secret
Centralized logging khiến secret bị nhân rộng tới collector, storage, dashboard và backup.
Checklist triển khai
- Xác định VPS nào gửi log.
- Chọn label ổn định: host, env, service.
- Không dùng high-cardinality label.
- Loki không public trực tiếp ra Internet.
- Alloy đọc đúng file/journal cần thiết.
- Test
loki.writetới endpoint. - Grafana kết nối Loki thành công.
- Có retention policy.
- Theo dõi disk usage của Loki.
- Kiểm tra log không chứa secret.
FAQ
Loki có thay thế Prometheus không?
Không. Prometheus lưu metric, Loki lưu log. Hai hệ thống bổ sung cho nhau.
Grafana Alloy có thay Promtail không?
Grafana hiện hướng dẫn Alloy là collector telemetry chính cho log, metric và trace. Với triển khai mới, Alloy là lựa chọn nên ưu tiên.
Loki có cần Elasticsearch không?
Không. Loki là hệ thống log riêng, không yêu cầu Elasticsearch để lưu và query log.
Có nên cài Loki trên cùng VPS ứng dụng không?
Có thể cho lab hoặc hệ thống nhỏ, nhưng production nên cân nhắc tách monitoring/logging để sự cố app server không làm mất luôn dữ liệu quan sát.
Có thể thu log Docker bằng Alloy không?
Có. Alloy có component dành cho Docker và nhiều nguồn log khác.
Kết luận
Grafana Loki và Alloy giúp biến việc điều tra log từ “SSH từng VPS” thành một luồng quan sát tập trung. Hãy bắt đầu bằng một vài nguồn log quan trọng, giữ label đơn giản, bảo vệ endpoint Loki, thiết lập retention và chỉ thu dữ liệu thực sự hữu ích.
Nếu hạ tầng của bạn đã có nhiều VPS cho web, API, database hoặc worker, log tập trung là bước tự nhiên tiếp theo sau monitoring metric. Bạn có thể tham khảo các dịch vụ VPS tại HUONG CLOUD và lựa chọn tài nguyên phù hợp với workload cũng như nhu cầu lưu log thực tế.
Nguồn tham khảo
- Grafana Loki Docs — Install Loki: https://grafana.com/docs/loki/latest/setup/install/
- Grafana Alloy Docs — Monitor logs from a local file: https://grafana.com/docs/alloy/latest/monitor/monitor-logs-from-file/
- Grafana Alloy Docs — Loki components: https://grafana.com/docs/alloy/latest/reference/components/loki/
- Grafana Loki Docs — Get started: https://grafana.com/docs/loki/latest/get-started/
Kết luận
Nếu chưa chắc cấu hình hoặc loại dịch vụ nào phù hợp, hãy gửi nhu cầu thực tế để đội ngũ hỗ trợ tư vấn trước khi mua.
Chưa biết nên chọn gói nào?
Xem bảng giá VPS hoặc liên hệ đội ngũ hỗ trợ để chọn cấu hình phù hợp.
Xem bảng giá VPS →