Chiến lược giám sát toàn diện: Kết hợp Prometheus, Grafana và Loki cho hệ thống container
Trong bối cảnh kiến trúc hiện đại dựa trên các microservice và container hóa, việc quản lý cơ sở hạ tầng không còn đơn thuần là kiểm tra xem máy chủ có đang chạy hay không. Kỹ sư phần mềm và sysadmin cần một cái nhìn sâu sắc về hiệu năng, hành vi của ứng dụng và các vấn đề về logic xảy ra trong thời gian thực. Bài viết này sẽ hướng dẫn bạn xây dựng một giải pháp giám sát hoàn chỉnh sử dụng ba trụ cột chính: Prometheus để thu thập metric, Grafana để trực quan hóa dữ liệu và Loki để quản lý logs, tất cả được đóng gói trong môi trường Docker Compose để dễ dàng triển khai và mở rộng.
Khái niệm cốt lõi về hệ sinh thái quan sát
Trước khi đi vào cài đặt cụ thể, chúng ta cần hiểu rõ vai trò của từng thành phần. Prometheus đóng vai trò là hệ thống cơ sở dữ liệu time-series, chịu trách nhiệm pull (kéo) dữ liệu định kỳ từ các target như node_exporter hoặc ứng dụng của bạn qua các endpoint dạng /metrics. Dữ liệu này mang tính số liệu, giúp phân tích xu hướng sử dụng tài nguyên. Trong khi đó, Grafana đóng vai trò là bộ não trực quan, lấy dữ liệu từ Prometheus để vẽ biểu đồ, dashboard, và thiết lập cảnh báo. Một điểm yếu thường thấy của Prometheus là không có khả năng lưu trữ logs tốt, vì vậy chúng ta cần Loki. Loki là hệ thống lưu trữ logs tập trung, hoạt động tương tự như Elasticsearch nhưng nhẹ hơn và chi phí thấp hơn, được thiết kế để làm việc đồng bộ với Grafana. Cuối cùng, chúng ta cần một bộ thu thập logs như Promtail để đọc log file từ container và đẩy lên Loki.
Cấu trúc dự án và tệp cấu hình cơ bản
Để bắt đầu, chúng ta sẽ tạo một thư mục dự án mới và thiết lập cấu trúc tệp tin đơn giản. Bạn cần tạo một tệp docker-compose.yml để định nghĩa toàn bộ các dịch vụ sẽ chạy song song. Việc này giúp đảm bảo rằng Prometheus, Grafana, Loki, Promtail và các exporter cần thiết được khởi tạo cùng một lúc với các biến môi trường và port mapping chuẩn xác.
Tiếp theo, chúng ta cần định cấu hình Prometheus. File prometheus.yml sẽ là trái tim của quá trình thu thập dữ liệu. Trong file này, bạn cần khai báo các job để scrape dữ liệu. Job đầu tiên là scrape chính nó để tự giám sát, job thứ hai là node_exporter để lấy thông tin phần cứng của máy chủ, và các job khác sẽ dành cho ứng dụng của bạn. Cấu hình này cho phép bạn tùy chỉnh khoảng thời gian scrape, thời gian timeout và các label để phân biệt nguồn dữ liệu.
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets: ['node:9100']
- job_name: 'app-metrics'
static_configs:
- targets: ['localhost:8080']
labels:
service: 'backend-api'
Cấu hình Loki và Promtail để thu thập nhật ký
Sau khi đã thiết lập được phần metric, bước tiếp theo là xử lý logs. Loki không tự động đọc log file từ hệ thống mà cần một tác nhân thu thập. Promtail chính là tác nhân đó. Bạn cần tạo một tệp config.yaml cho Promtail để chỉ định các đường dẫn log cần đọc và ánh xạ chúng vào các stream của Loki. Việc quan trọng nhất ở đây là cấu hình các label động dựa trên tên file log hoặc container name, giúp bạn dễ dàng lọc và tìm kiếm sau này trên Grafana.
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: system
static_configs:
- targets:
- /var/log
labels:
job: varlogs
__path__: /var/log/*log
- job_name: container-logs
static_configs:
- targets:
- /var/lib/docker/containers/*/*-stdout.log
labels:
job: container-logs
__path__: /var/lib/docker/containers/*/*-stdout.log
Khi Promtail được cấu hình đúng, nó sẽ bắt đầu đọc nội dung log từ các file được chỉ định và đẩy về Loki. Loki sẽ lưu trữ các log này theo dạng stream, sử dụng các label để nhóm các log có cùng nguồn gốc, giúp việc truy vấn trở nên hiệu quả và ít tốn tài nguyên hơn so với các hệ thống log truyền thống lưu trữ toàn văn bản.
Triển khai bằng Docker Compose
Bây giờ là lúc hội tụ tất cả các thành phần lại bằng Docker Compose. Đây là bước quan trọng để đảm bảo tính nhất quán giữa các dịch vụ. Bạn cần khai báo các hình (image) công khai từ Docker Hub cho Grafana, Prometheus, Loki, Promtail và Node Exporter. Lưu ý về việc mount volume: bạn cần map volume cho Prometheus để lưu dữ liệu time-series bền vững, map volume cho Loki để lưu trữ logs, và map volume cho Promtail để lưu file positions.yaml nhằm ghi nhận vị trí đọc log hiện tại, tránh việc đọc lại các log cũ khi container khởi động lại.
version: '3'
services:
prometheus:
image: prom/prometheus:latest
ports:
- 9090:9090
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
loki:
image: grafana/loki:latest
ports:
- 3100:3100
volumes:
- loki_data:/loki
promtail:
image: grafana/promtail:latest
volumes:
- /var/log:/var/log
- /var/lib/docker/containers:/var/lib/docker/containers
- ./promtail-config.yml:/etc/promtail/config.yml
command:
- --config.file=/etc/promtail/config.yml
grafana:
image: grafana/grafana:latest
ports:
- 3000:3000
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
node_exporter:
image: prom/node-exporter:latest
ports:
- 9100:9100
command:
- '--path.rootfs=/host'
volumes:
- /:/host:ro,rslave
volumes:
prometheus_data:
loki_data:
grafana_data:
Khi chạy lệnh docker-compose up -d, toàn bộ hệ sinh thái sẽ hoạt động. Bạn có thể truy cập Grafana qua địa chỉ localhost:3000 với tài khoản mặc định là admin và password admin. Từ giao diện quản trị của Grafana, bạn cần thêm nguồn dữ liệu (Data Source). Đầu tiên là thêm Prometheus với URL là http://prometheus:9090, sau đó thêm Loki với URL là http://loki:3100. Việc này kết nối Grafana với hai kho dữ liệu của bạn.
Xây dựng Dashboard hiệu quả và cảnh báo thông minh
Sau khi kết nối nguồn dữ liệu, sức mạnh thực sự của Grafana mới bắt đầu. Bạn có thể tạo Dashboard mới, thêm panel và chọn nguồn dữ liệu tương ứng. Với Prometheus, bạn sử dụng PromQL để truy vấn. Ví dụ, để xem sử dụng CPU, bạn có thể dùng câu lệnh rate(node_cpu_seconds_total{mode="user"}[5m]). Với Loki, bạn sử dụng LogQL. Để xem các lỗi trong log, bạn có thể dùng câu lệnh {job="container-logs"} |= "error". Sự kết hợp này cho phép bạn tạo ra một trang tổng quan duy nhất, nơi biểu đồ CPU tăng vọt đi kèm ngay bên dưới là dòng log lỗi xuất hiện tại cùng thời điểm đó, giúp nguyên nhân sự cố được xác định nhanh chóng.
Đặc biệt, bạn không nên chỉ dừng lại ở việc xem dữ liệu. Hãy thiết lập các cảnh báo (Alerting) trong Prometheus hoặc trực tiếp trên Grafana. Ví dụ, nếu tỉ lệ lỗi HTTP 5xx tăng lên quá 5% trong vòng 5 phút, hoặc nếu container bị restart liên tục, hệ thống sẽ gửi thông báo qua Telegram, Email hoặc Slack. Điều này giúp đội ngũ vận hành phản ứng chủ động trước khi sự cố lan rộng, đảm bảo tính sẵn sàng cao cho dịch vụ.
Tóm lại, việc tích hợp Prometheus, Grafana và Loki tạo nên một nền tảng giám sát vững chắc, cân bằng giữa chi phí và hiệu năng. Bằng cách áp dụng quy trình cấu hình chi tiết như trên, bạn sẽ có được tầm nhìn toàn cảnh về hạ tầng container của mình, từ các chỉ số phần cứng thô sơ cho đến các dòng nhật ký phức tạp của ứng dụng, giúp nâng cao chất lượng vận hành và độ ổn định của hệ thống.