Monitoring & Observability: Prometheus, Grafana và CloudWatch
Danh Mục Bài Viết
- 1. Observability là gì và tại sao cần đến 3 công cụ?
- 2. Prometheus: Pull-based metrics và PromQL thực chiến
- 3. Grafana: Từ dashboard cơ bản đến alert thông minh
- 4. AWS CloudWatch: Khi hạ tầng là AWS
- 5. Kết hợp ba công cụ: Architecture thực tế
- 6. Lỗi thường gặp và cách tránh
- 7. FAQ
- 8. Sau cùng, monitoring là văn hóa
Production deploy xong, team ăn mừng — rồi 3 giờ sáng nhận alert "service down". Chạy vào xem log, không hiểu gì. Không biết CPU lên từ lúc nào, không biết request latency tăng từ bao giờ, không biết lỗi bắt đầu ở đâu. Đó là lúc mình hiểu: deploy được chưa đủ, phải nhìn thấy được hệ thống đang làm gì.
Observability là gì và tại sao cần đến 3 công cụ?
Nhiều người nhầm lẫn giữa monitoring và observability. Monitoring là bạn đặt trước câu hỏi rồi theo dõi — ví dụ "CPU có vượt 80% không?". Observability là khả năng trả lời bất kỳ câu hỏi nào về hệ thống, kể cả những câu chưa nghĩ đến trước.
Ba trụ cột của observability là metrics, logs, và traces. Prometheus chuyên về metrics — time-series data dạng số. Grafana là lớp visualization, ghép mọi nguồn dữ liệu lại thành dashboard. AWS CloudWatch phủ toàn bộ hạ tầng AWS — từ EC2, RDS, Lambda đến API Gateway — và tích hợp sẵn với alerting, log aggregation.
Khổ nỗi là không có công cụ nào làm tốt cả ba thứ cùng lúc. Prometheus mạnh về pull-based metrics nhưng không phải cloud-native cho AWS. CloudWatch có sẵn nhưng query language (CloudWatch Metrics Insights) kém linh hoạt hơn PromQL. Grafana thì không thu thập gì cả — nó chỉ visualize. Bộ ba này bổ sung nhau, không phải cạnh tranh nhau.
Prometheus: Pull-based metrics và PromQL thực chiến
Prometheus hoạt động theo mô hình pull — nó chủ động scrape metrics từ các target thay vì các target push vào. Điều này nghe có vẻ bất tiện nhưng lại giúp Prometheus biết chính xác target nào đang "sống" hay không.
Cấu hình cơ bản trong prometheus.yml:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'app-backend'
static_configs:
- targets: ['app-server:8080']
metrics_path: '/actuator/prometheus' # Spring Boot
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093']
rule_files:
- "alert_rules.yml"
Prometheus dùng exporters để thu thập metrics từ các hệ thống khác nhau. Node Exporter cho metrics máy chủ (CPU, RAM, disk), Blackbox Exporter để probe HTTP/TCP endpoint, JMX Exporter cho JVM. Với Kubernetes, bạn cần thêm kube-state-metrics và metrics-server.
PromQL — ngôn ngữ query của Prometheus — ban đầu trông khó nhằn nhưng thực ra rất logic. Một vài query mình dùng thường xuyên:
# CPU usage theo node (%)
100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Request rate per second (HTTP 5xx)
rate(http_requests_total{status=~"5.."}[5m])
# P99 latency
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
# Memory available
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100
Mẹo xương máu: Đừng dùng
iratecho dashboard — nó quá nhạy cảm với spike ngắn. Dùngratevới window 5m hoặc 10m cho dashboard ổn định hơn.iratechỉ hợp khi debug realtime.
Grafana: Từ dashboard cơ bản đến alert thông minh
Grafana connect được với hàng chục data source — Prometheus, CloudWatch, Loki, Elasticsearch, PostgreSQL, và nhiều hơn. Điểm mạnh của Grafana là unified view: một dashboard có thể hiện metrics từ Prometheus bên cạnh logs từ Loki và traces từ Tempo.
Thêm Prometheus làm data source trong Grafana:
# grafana.ini hoặc qua UI: Configuration > Data Sources
Name: Prometheus
Type: Prometheus
URL: http://prometheus:9090
Scrape interval: 15s
Mình thường import sẵn các dashboard từ Grafana Dashboard Library thay vì xây từ đầu. Dashboard ID 1860 (Node Exporter Full) và 315 (Kubernetes cluster monitoring) là hai cái đầu tiên mình cài trên mọi hệ thống mới.
Grafana Alerting (từ v8 trở lên) đã thay thế hẳn Alertmanager cũ. Cấu hình alert rule trực tiếp trên dashboard, rồi route notification qua contact points — Slack, PagerDuty, email, webhook. Một alert rule ví dụ:
# Alert khi P99 latency > 2s trong 5 phút liên tục
Condition: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 2
For: 5m
Labels: severity=critical, team=backend
Annotations:
summary: "High P99 latency on {{ $labels.instance }}"
description: "P99 latency is {{ $value | humanizeDuration }}"
Nói thật thì alert fatigue là vấn đề thực sự. Mình đã có giai đoạn mọi người ignore hết alert vì quá nhiều false positive. Bài học: chỉ alert những thứ cần action ngay, còn lại để vào warning dashboard.
AWS CloudWatch: Khi hạ tầng là AWS
CloudWatch là lựa chọn tự nhiên khi dùng AWS vì nó tích hợp sẵn — không cần cài thêm gì, Lambda, RDS, ECS, ALB đều đẩy metrics vào CloudWatch tự động. Thêm vào đó, CloudWatch Logs Insights cho phép query log aggregated từ nhiều service cùng lúc.
Một số metrics CloudWatch quan trọng cần theo dõi:
- EC2: CPUUtilization, NetworkIn/Out, StatusCheckFailed
- RDS: DatabaseConnections, FreeStorageSpace, ReadLatency, WriteLatency
- ALB: TargetResponseTime, HTTPCode_Target_5XX_Count, UnHealthyHostCount
- Lambda: Duration, Errors, Throttles, ConcurrentExecutions
Đưa CloudWatch metrics vào Grafana bằng CloudWatch data source — cần cấu hình IAM role với quyền cloudwatch:GetMetricData, cloudwatch:ListMetrics. Sau đó trong Grafana bạn có thể query CloudWatch metrics với syntax quen thuộc.
CloudWatch Alarms tích hợp trực tiếp với SNS để gửi notification. Tuy nhiên với hệ thống phức tạp, mình thường prefer route mọi alert qua Grafana Alerting để có unified alert management hơn là dùng CloudWatch Alarms riêng lẻ.
Kết hợp ba công cụ: Architecture thực tế
Dưới đây là setup mình đang dùng cho production trên EKS:
# Cài Prometheus stack bằng Helm (bao gồm cả Grafana và Alertmanager)
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --namespace monitoring --create-namespace --set grafana.adminPassword=your-secure-password --set prometheus.prometheusSpec.retention=30d --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=50Gi
Sau khi cài, Grafana đã có sẵn dashboard cho Kubernetes cluster. Tiếp theo thêm CloudWatch data source để pull metrics từ AWS services. Kết quả là một Grafana dashboard duy nhất hiển thị cả metrics từ các pod Kubernetes (qua Prometheus) lẫn metrics từ RDS, ALB (qua CloudWatch).
Kinh nghiệm: Đặt retention của Prometheus ở 30 ngày, với dữ liệu dài hạn hơn thì dùng Thanos hoặc push sang CloudWatch Metrics (bằng AWS Distro for OpenTelemetry — ADOT). Prometheus không thiết kế để lưu long-term data.
Lỗi thường gặp và cách tránh
1. Cardinality explosion — Prometheus chậm bất thường hoặc OOM. Nguyên nhân thường là label có quá nhiều giá trị unique (ví dụ: dùng user_id làm label). PromQL query topk(10, count by (__name__)({__name__=~".+"})) giúp tìm metric nào đang gây vấn đề.
2. Grafana dashboard không load — Thường do query timeout. Kiểm tra time range: query với range 90 ngày trên data 1 triệu series sẽ rất chậm. Dùng $__rate_interval thay vì hardcode window như [5m] để Grafana tự tính interval phù hợp với time range đang chọn.
3. Alert không gửi được — Debug theo thứ tự: (1) Alert rule đã fire chưa? (2) Contact point đã test được chưa? (3) Notification policy đúng chưa? Grafana có trang "Alert history" rất tiện để trace.
4. CloudWatch cost tăng đột biến — GetMetricData API có giá theo số API call. Khi Grafana refresh quá thường xuyên với nhiều dashboard mở cùng lúc, cost có thể bất ngờ tăng. Đặt minimum refresh interval 1 phút cho CloudWatch panels.
FAQ
Q: Prometheus hay CloudWatch — nên chọn cái nào cho hệ thống trên AWS?A: Không phải lựa chọn either/or. CloudWatch là bắt buộc cho AWS managed services (RDS, Lambda, ALB) vì bạn không thể cài exporter vào đó. Prometheus phù hợp cho application metrics và Kubernetes workloads. Dùng cả hai và ghép vào Grafana là setup phổ biến nhất.
Q: Grafana Cloud vs self-hosted Grafana?A: Grafana Cloud miễn phí cho đến 10k active series và 50GB logs — đủ dùng cho team nhỏ. Self-hosted cho toàn quyền kiểm soát, không lo data ra ngoài, nhưng phải tự vận hành. Mình thường recommend self-hosted khi team đã có người DevOps chuyên trách.
Q: Cần cài thêm gì để monitor ứng dụng Node.js/Python?A: Với Node.js dùng thư viện
prom-client, với Python dùngprometheus_client. Expose metrics endpoint/metricsrồi thêm vào scrape config của Prometheus. Quan trọng là instrument từ code: đo latency, error rate, và throughput của business logic — không chỉ dựa vào system metrics.
Sau cùng, monitoring là văn hóa
Mình từng ở trong team có dashboard đẹp nhưng không ai nhìn. Và ở team khác có dashboard xấu nhưng mọi người vào xem mỗi sáng trước khi làm việc. Công cụ chỉ là điều kiện cần — điều kiện đủ là team thực sự dùng nó để ra quyết định.
Bắt đầu nhỏ: 3 metrics quan trọng nhất của service là gì? Đặt alert cho chúng. Khi alert fire, xem lại có đúng không, điều chỉnh threshold. Dần dần bạn sẽ có hệ thống monitoring phản ánh đúng sức khỏe thực tế của hệ thống, không phải bộ sưu tập dashboard để ngắm.
