DevOps 7 — Giám sát & Observability

13 thg 7, 2026 3 lượt xem
#observability
#monitoring
#devops
#grafana
#prometheus

Mở đầu: vì sao cần "nhìn thấy" hệ thống

Khi bạn chỉ có một ứng dụng nguyên khối (monolith) chạy trên một máy chủ, việc tìm lỗi khá đơn giản: SSH vào máy, đọc một file log, xem top là gần như đủ. Nhưng hệ thống hiện đại thường gồm hàng chục đến hàng trăm dịch vụ nhỏ (microservices), chạy trên nhiều container, nhiều node, co giãn động theo tải. Một request của người dùng có thể đi qua API gateway → service xác thực → service đơn hàng → service thanh toán → cơ sở dữ liệu → hàng đợi message. Khi nó chậm hoặc lỗi, "chậm ở đâu" trở thành câu hỏi khó.

Đây chính là lý do observability (khả năng quan sát) ra đời. Bài này sẽ đi sâu từ khái niệm nền tảng đến công cụ và thực hành cụ thể: ba trụ cột logs–metrics–traces, Prometheus/Grafana, alerting, và bộ chỉ số SLI/SLO/SLA cùng error budget.

Monitoring khác Observability như thế nào

Hai từ này hay bị dùng lẫn lộn, nhưng khác nhau về tư duy.

Monitoring là việc theo dõi những thứ bạn đã biết trước là quan trọng: CPU, RAM, số lỗi HTTP 500, độ trễ trung bình. Bạn định nghĩa sẵn các câu hỏi và dựng dashboard/alert để trả lời chúng. Monitoring trả lời câu hỏi: "Hệ thống có đang khỏe theo các tiêu chí tôi đặt ra không?"

Observability là khả năng suy luận về trạng thái bên trong của hệ thống chỉ qua các tín hiệu nó phát ra (output), kể cả với những câu hỏi bạn chưa từng nghĩ tới lúc thiết kế. Nó trả lời câu hỏi: "Tại sao đúng nhóm người dùng ở khu vực X, dùng phiên bản app Y, vào khung giờ Z lại gặp lỗi?" — một câu hỏi mà bạn không thể dựng sẵn dashboard cho mọi tổ hợp.

Nói ngắn gọn: monitoring là tập con của observability. Monitoring báo cho bạn biết có gì đó sai; observability giúp bạn điều tra để hiểu vì sao sai mà không cần deploy lại code để thêm log.

Ba trụ cột của Observability

Observability được xây trên ba loại dữ liệu (telemetry) bổ trợ cho nhau. Không trụ cột nào tự nó đủ.

Trụ cộtBản chất dữ liệuTrả lời câu hỏiCông cụ phổ biếnĐặc tính chi phí
LogsBản ghi sự kiện rời rạc, có dấu thời gian"Chính xác chuyện gì đã xảy ra ở thời điểm đó?"ELK (Elasticsearch + Logstash + Kibana), LokiKhối lượng lớn, tốn lưu trữ
MetricsSố liệu đo dạng chuỗi thời gian (time-series)"Xu hướng/định lượng thế nào theo thời gian?"Prometheus, Thanos, VictoriaMetricsRẻ, nén tốt, query nhanh
TracesHành trình một request qua nhiều dịch vụ"Request đi qua đâu, chậm ở khâu nào?"OpenTelemetry, Jaeger, Tempo, ZipkinThường lấy mẫu (sampling)

Logs — nhật ký sự kiện

Log là dòng văn bản ghi lại một sự kiện cụ thể. Vấn đề lớn nhất trong hệ phân tán là log nằm rải rác trên hàng trăm container, mà container thì sinh ra và biến mất liên tục. Hai nguyên tắc cốt lõi:

1. Log có cấu trúc (structured logging). Thay vì in chuỗi tự do, hãy in JSON để máy có thể truy vấn theo trường:

{"ts":"2026-06-30T10:15:02Z","level":"error","service":"payment",
 "trace_id":"a1b2c3","user_id":"u-991","msg":"charge failed",
 "amount":250000,"gateway":"vnpay","err":"timeout"}

trace_id trong log là chìa khóa để nối log với trace (xem phần dưới).

2. Tập trung hóa (centralized logging). Agent (Filebeat, Fluent Bit, Promtail...) thu log từ mọi node và đẩy về một nơi. Hai lựa chọn phổ biến:

  • ELK Stack: Elasticsearch lưu và đánh chỉ mục toàn văn (full-text), Kibana để xem. Mạnh khi cần tìm kiếm tự do, nhưng tốn tài nguyên.
  • Grafana Loki: chỉ đánh chỉ mục theo nhãn (label) chứ không index toàn văn, nên rẻ hơn nhiều. Triết lý của Loki là "giống Prometheus nhưng cho log".

Metrics — số liệu chuỗi thời gian

Metric là một con số đo được tại một thời điểm, gắn nhãn, ví dụ http_requests_total{service="order",status="500"}. Vì chỉ là số, metric nén rất tốt và truy vấn cực nhanh, lý tưởng cho dashboard và alert.

Prometheus là chuẩn de-facto trong thế giới cloud-native. Điểm đặc trưng là pull model: thay vì ứng dụng tự đẩy số liệu đi, Prometheus chủ động cào (scrape) endpoint /metrics của từng dịch vụ theo chu kỳ. Lợi ích: Prometheus biết chính xác target nào đang sống (nếu scrape thất bại thì target "down"), và phía ứng dụng không cần biết server giám sát ở đâu.

Cấu hình scrape tối thiểu:

# prometheus.yml
global:
  scrape_interval: 15s
scrape_configs:
  - job_name: 'order-service'
    static_configs:
      - targets: ['order-service:8080']

Có bốn loại metric cơ bản: Counter (chỉ tăng, ví dụ tổng số request), Gauge (lên xuống tự do, ví dụ số kết nối hiện tại), Histogram (phân phối giá trị theo các "rổ", ví dụ phân bố độ trễ), và Summary (tương tự histogram nhưng tính quantile phía client).

Giới thiệu PromQL. Ngôn ngữ truy vấn của Prometheus rất mạnh. Vài ví dụ thực dụng:

# Tỷ lệ request lỗi 5xx trong 5 phút qua
sum(rate(http_requests_total{status=~"5.."}[5m]))
  / sum(rate(http_requests_total[5m]))

# Độ trễ phân vị 95 (p95) tính từ histogram
histogram_quantile(0.95,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le))

Hàm rate() tính tốc độ tăng trung bình mỗi giây của một counter trong cửa sổ thời gian — đây là hàm bạn sẽ dùng nhiều nhất.

Traces — dấu vết phân tán

Trace theo dõi một request xuyên suốt nhiều dịch vụ. Mỗi chặng công việc là một span; các span nối với nhau qua một trace_id chung tạo thành cây thể hiện toàn bộ hành trình. Nhờ trace bạn nhìn thấy: request mất 800ms, trong đó 600ms nằm ở một truy vấn DB chậm — điều mà metric tổng hợp không chỉ ra được.

OpenTelemetry (OTel) là chuẩn mở (vendor-neutral) để sinh và thu telemetry, gồm SDK cho ứng dụng và Collector để nhận/xử lý/chuyển tiếp dữ liệu. Backend hiển thị trace phổ biến là Jaeger hoặc Grafana Tempo.

Để trace hoạt động xuyên dịch vụ, mỗi service phải truyền bối cảnh (context propagation) — thường qua header traceparent (chuẩn W3C Trace Context) — cho dịch vụ kế tiếp. Vì lưu mọi trace rất tốn kém, người ta dùng sampling: chỉ giữ lại một tỷ lệ (ví dụ 1–10%), nhưng thường ưu tiên giữ trọn các trace bị lỗi hoặc chậm bất thường.

Sơ đồ luồng thu thập telemetry

Dưới đây là cách dữ liệu chảy từ các dịch vụ về các backend giám sát và lên màn hình vận hành.

Lưu ý sự khác biệt về mũi tên: metric được Prometheus kéo về (pull), còn log và trace được đẩy đi (push) tới agent/collector. Grafana đứng ở tầng trên cùng, đọc cả ba nguồn để cho phép kỹ sư nhảy qua lại giữa metric → log → trace của cùng một sự cố.

Bốn tín hiệu vàng và phương pháp RED/USE

Đo cái gì cho đúng? Đừng đo tất cả mọi thứ — hãy đo cái thật sự phản ánh trải nghiệm người dùng. Google SRE đề xuất bốn tín hiệu vàng (four golden signals):

  • Latency (độ trễ): thời gian xử lý một request. Quan trọng: tách riêng độ trễ của request thành côngthất bại, vì lỗi nhanh có thể che lấp thành công chậm.
  • Traffic (lưu lượng): mức nhu cầu lên hệ thống, ví dụ số request/giây.
  • Errors (lỗi): tỷ lệ request thất bại (lỗi rõ ràng như 5xx, hoặc sai về mặt nghiệp vụ).
  • Saturation (mức bão hòa): hệ thống "đầy" đến đâu — CPU, bộ nhớ, hàng đợi. Đây là chỉ báo sớm cho thấy sắp quá tải.

Có hai khung tư duy bổ sung phổ biến:

  • Phương pháp RED (cho dịch vụ, hướng request): Rate (số request/s), Errors (số lỗi/s), Duration (phân phối độ trễ). Rất hợp với microservices.
  • Phương pháp USE (cho tài nguyên, hướng phần cứng): Utilization (mức sử dụng), Saturation (mức bão hòa/chờ), Errors (lỗi thiết bị). Hợp để soi CPU, đĩa, mạng.

Một mẹo: RED nhìn từ phía người dùng gọi vào, USE nhìn từ phía tài nguyên bên trong. Kết hợp cả hai cho bức tranh đầy đủ.

Dashboard với Grafana

Grafana là công cụ trực quan hóa hàng đầu, có thể cắm vào nhiều nguồn (Prometheus, Loki, Tempo, Elasticsearch...). Vài nguyên tắc làm dashboard tốt:

  • Mỗi dashboard phục vụ một mục đích. Một dashboard tổng quan cho lãnh đạo (SLO, traffic), một dashboard chi tiết cho on-call (per-service RED), một cho hạ tầng (USE).
  • Đặt số quan trọng nhất ở trên cùng, bên trái — nơi mắt nhìn vào trước.
  • Dùng biến (template variables) để chọn service/environment thay vì sao chép dashboard.
  • Liên kết chéo (correlation): cấu hình để từ một điểm tăng vọt trên đồ thị metric có thể click thẳng sang log/trace tương ứng cùng khoảng thời gian. Đây là sức mạnh thực sự của observability.

Hãy cảnh giác với "wall of graphs" — màn hình 50 biểu đồ trông oách nhưng không ai đọc nổi khi sự cố xảy ra. Ít mà đúng thì hơn.

Alerting — cảnh báo đúng lúc, đúng việc

Dashboard chỉ hữu ích khi có người nhìn. Alert mới là thứ chủ động đánh thức bạn dậy. Trong hệ Prometheus, luật cảnh báo được định nghĩa rồi gửi tới Alertmanager để gom nhóm, chặn lặp (deduplicate), tạm tắt (silence) và định tuyến tới Slack/Email/PagerDuty.

# alert rule
groups:
  - name: availability
    rules:
      - alert: HighErrorRate
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[5m]))
            / sum(rate(http_requests_total[5m])) > 0.05
        for: 10m
        labels: { severity: critical }
        annotations:
          summary: "Tỷ lệ lỗi 5xx vượt 5% trong 10 phút"

Lưu ý mệnh đề for: 10m: điều kiện phải đúng liên tục 10 phút mới bắn alert, tránh báo động giả do nhiễu nhất thời.

Tránh alert fatigue (mệt mỏi vì cảnh báo). Đây là tử huyệt của nhiều đội. Nếu mỗi đêm bị đánh thức 20 lần bởi cảnh báo vô nghĩa, kỹ sư sẽ học cách phớt lờ — và rồi bỏ lỡ cái cảnh báo thật. Nguyên tắc:

  • Mọi alert phải hành động được (actionable). Nếu nhận alert mà chẳng phải làm gì, hãy xóa nó.
  • Cảnh báo theo triệu chứng, không theo nguyên nhân. Báo "người dùng đang gặp lỗi" (triệu chứng), đừng báo "CPU node-7 cao" (nguyên nhân, có thể vô hại).
  • Phân tầng mức độ: critical (đánh thức người ngay) vs warning (xem vào giờ hành chính).
  • Gắn runbook (hướng dẫn xử lý) vào mỗi alert để người trực biết làm gì.

SLI, SLO, SLA và Error Budget

Đây là bộ khái niệm nền tảng của SRE, giúp chuyển "độ tin cậy" từ cảm tính sang định lượng.

  • SLI (Service Level Indicator): một chỉ số đo thực tế về chất lượng. Ví dụ: "tỷ lệ request thành công trong tháng" = 99,95%. SLI là sự thật được đo.
  • SLO (Service Level Objective): mục tiêu nội bộ cho SLI. Ví dụ: "tỷ lệ thành công ≥ 99,9% mỗi tháng". SLO là cam kết đội tự đặt ra.
  • SLA (Service Level Agreement): cam kết với khách hàng kèm hậu quả (thường là tài chính). Ví dụ: "nếu uptime < 99,5%, hoàn 10% phí". SLA luôn lỏng hơn SLO để có vùng đệm.

Quan hệ thực hành: SLI ≤ đo lường thực → so với SLO (mục tiêu) → SLA (hợp đồng) lỏng hơn SLO.

Error budget (ngân sách lỗi) là khái niệm tinh tế và quan trọng nhất. Nếu SLO là 99,9% thành công, thì 0,1% còn lại chính là "ngân sách" cho phép hỏng. Với một tháng (~43.200 phút), 0,1% tương đương khoảng 43 phút được phép downtime/lỗi.

Error budget biến mâu thuẫn kinh điển giữa Dev (muốn release nhanh) và Ops (muốn ổn định) thành một con số chung:

  • Còn ngân sách → cứ mạnh dạn deploy tính năng mới, chấp nhận rủi ro.
  • Cạn ngân sách → đóng băng tính năng, dồn lực vào ổn định cho tới khi hồi phục.

Nó cũng chống lại cám dỗ "đuổi theo 100%": độ tin cậy tuyệt đối là cực kỳ đắt đỏ và thường không cần thiết — người dùng không phân biệt nổi 99,99% với 100%, trong khi chi phí thì khác biệt khổng lồ.

Health check và uptime

Lớp cơ bản nhất của giám sát là health check — một endpoint cho biết dịch vụ còn sống và sẵn sàng phục vụ không. Trong Kubernetes, có hai loại probe quan trọng (chủ đề được đào sâu ở bài về container/orchestration):

  • Liveness probe: "Tiến trình có còn sống không?" Nếu fail, Kubernetes khởi động lại container.
  • Readiness probe: "Đã sẵn sàng nhận traffic chưa?" Nếu fail, Kubernetes ngừng gửi traffic nhưng không restart — hữu ích lúc khởi động hoặc khi DB tạm mất.
# Kubernetes pod
livenessProbe:
  httpGet: { path: /healthz, port: 8080 }
  initialDelaySeconds: 10
  periodSeconds: 10
readinessProbe:
  httpGet: { path: /ready, port: 8080 }
  periodSeconds: 5

Một thiết kế tốt: /healthz chỉ kiểm tra tiến trình nội bộ, còn /ready kiểm tra cả các phụ thuộc thiết yếu (DB, cache). Uptime là tỷ lệ thời gian dịch vụ ở trạng thái khỏe; các công cụ blackbox (Prometheus Blackbox Exporter, hoặc dịch vụ ngoài như UptimeRobot) thăm dò định kỳ từ bên ngoài để xác nhận góc nhìn của người dùng thực, bổ sung cho giám sát nội bộ.

Tóm tắt

Observability là khả năng hiểu trạng thái bên trong hệ thống qua tín hiệu nó phát ra, vượt xa monitoring vốn chỉ theo dõi những thứ đã biết trước. Nó dựa trên ba trụ cột: logs (sự kiện chi tiết, nên có cấu trúc và tập trung qua ELK/Loki), metrics (chuỗi thời gian, Prometheus với pull model và PromQL), và traces (hành trình request phân tán, OpenTelemetry + Jaeger/Tempo). Hãy ưu tiên đo bốn tín hiệu vàng (latency, traffic, errors, saturation) cùng khung RED cho dịch vụ và USE cho tài nguyên. Grafana hợp nhất ba nguồn này thành dashboard có khả năng liên kết chéo, còn Alertmanager lo cảnh báo — với kỷ luật "actionable, theo triệu chứng" để tránh alert fatigue. Cuối cùng, bộ SLI/SLO/SLA + error budget biến độ tin cậy thành con số có thể quản trị, cân bằng tốc độ phát triển và sự ổn định. Health/readiness probe và đo uptime là lớp nền đảm bảo dịch vụ luôn ở trạng thái phục vụ được.

Tự kiểm tra

  1. Phân biệt monitoring và observability bằng ví dụ một câu hỏi mà monitoring trả lời được nhưng observability mới giải quyết trọn vẹn.
  2. Vì sao Prometheus dùng pull model lại có lợi cho việc phát hiện target "chết"? Khác gì so với cách log và trace được thu thập?
  3. Bốn tín hiệu vàng là gì? RED và USE khác nhau ở góc nhìn nào, và mỗi khung hợp với loại đối tượng nào?
  4. Nếu SLO là 99,9% trong một tháng, error budget xấp xỉ bao nhiêu phút, và đội nên hành xử ra sao khi ngân sách gần cạn?
  5. Kể ba kỹ thuật cụ thể để tránh alert fatigue.
  6. trace_id trong log có cấu trúc giúp ích gì cho việc liên kết giữa ba trụ cột khi điều tra sự cố?

Đọc tiếp

DevOps 8 — Bảo mật & SRE

Bài viết liên quan

API là bề mặt tấn công chính của hệ thống dữ liệu hiện đại. Bài đi qua toàn bộ OWASP API Security Top 10 (2023) từ BOLA/IDOR tới quản lý inventory, biện pháp phòng thủ cốt lõi (authz mọi tầng, rate limit, schema, API gateway), khác biệt REST/GraphQL/gRPC, và bối cảnh Open Banking ngân hàng.

13 thg 7, 2026 3

Continuous Integration/Delivery/Deployment, cấu trúc pipeline, ví dụ GitHub Actions và chiến lược release.

13 thg 7, 2026 3

Container vs máy ảo, image/layer, Dockerfile, volume, network, Docker Compose và best practices.

13 thg 7, 2026 3

Mô hình Git, các lệnh cốt lõi, nhánh & merge, workflow nhóm (Git Flow, trunk-based) và Pull Request.

13 thg 7, 2026 3