Skip to content

Troubleshooting Runbook: Query Timeout, Cardinality, Ingestion Failure

Khung chẩn đoán gốc: một câu hỏi nhị phân trước khi làm bất cứ điều gì khác

Toàn bộ runbook chính thức của GMP xoay quanh một bước phân nhánh duy nhất, và bước này nên luôn là hành động đầu tiên bất kể triệu chứng ban đầu trông như thế nào: query metric up qua tab PromQL của Metrics Explorer.

promql
up{cluster="YOUR_CLUSTER", namespace="YOUR_NAMESPACE"}
  • Nếu có kết quả trả về → dữ liệu đã vào đến Monarch thành công, vấn đề nằm ở phía query (permission, client config, PromQL syntax, timeout phía client).
  • Nếu không có kết quả → dữ liệu chưa bao giờ đến được Monarch, vấn đề nằm ở phía ingestion (collector, scrape config, service account, quota).

Lý do bước này luôn phải làm trước: nó tách ngay một không gian lỗi rất lớn thành hai nhánh không giao nhau, tránh tình trạng debug sai hướng phổ biến nhất — ví dụ nghi ngờ RBAC của Grafana trong khi thực chất collector chưa từng scrape thành công target đó.

Nhánh A: Query-side — dữ liệu đã vào Monarch nhưng không đọc được

A1 — Lỗi quyền / xác thực (Forbidden, lỗi credential file)

Kiểm tra theo thứ tự: service account có role roles/monitoring.viewer chưa; nếu dùng Workload Identity Federation, binding namespace có đúng không; nếu dùng Grafana, token API đã hết hạn chưa; data source syncer có đúng project ID, endpoint, UID, token không.

A2 — Query timeout ("timeout awaiting response headers")

Đây là lỗi phổ biến nhất nhưng thường bị chẩn đoán sai là "GMP chậm". Nguyên nhân thực tế gần như luôn là cấu hình client: Grafana mặc định timeout 30 giây trong khi GMP cho phép chạy đến 120 giây. Sửa: tăng Timeout lên 120Query timeout lên 2m trong cấu hình data source Grafana trước khi kết luận query có vấn đề (chi tiết tối ưu PromQL nếu vấn đề vẫn còn sau khi sửa timeout, xem file 06).

A3 — Sai HTTP method ("no match[] parameter provided")

Cấu hình Grafana gửi POST thay vì GET. Sửa bằng cách đặt HTTP Method là GET trong data source.

A4 — Lỗi label validation ("labels other than __name__ are not supported yet")

Xảy ra khi dùng biến Grafana kiểu label_values($label). Sửa bằng cách dùng form đầy đủ label_values($metric, $label).

A5 — Quota đọc bị vượt (429: RESOURCE_EXHAUSTED: Quota exceeded for quota metric 'Time series queries')

Gửi yêu cầu tăng read quota cho Cloud Monitoring API qua Google Cloud Support. Trước khi tăng quota, kiểm tra xem có dashboard nào đang auto-refresh với interval quá ngắn không (nguyên nhân phổ biến gây tăng đột biến read request).

A6 — Đa project không đọc được dữ liệu

Tạo một metrics scope tại project trung tâm (scoping project) chứa các project cần theo dõi, rồi cấu hình Grafana dùng credential của scoping project — không dùng credential của từng project con riêng lẻ.

A7 — "series selector must specify a label matcher on monitored resource name"

Xảy ra khi query system metric của GCP (không phải Prometheus) mà thiếu label monitored_resource. Thêm filter tường minh theo monitored_resource.

A8 — Dữ liệu cumulative raw trông "sai" nhưng rate() lại đúng

Đây là hành vi được thiết kế, không phải lỗi: GMP tạo start timestamp bằng cách bỏ qua điểm ingest đầu tiên rồi trừ lùi từ các điểm sau. Chỉ ảnh hưởng query raw counter; mọi query dùng rate() cho kết quả giống hệt giữa Prometheus UI cục bộ (nếu có) và GMP. Không cần "sửa" gì — chỉ cần không dùng raw cumulative query để so sánh trực tiếp hai hệ thống.

A9 — Ratio query dao động bất thường rồi tự hết

Nguyên nhân tổ hợp: memory pressure gây throttle node khi nhiều query song song tương tự chạy cùng lúc; dữ liệu đến trễ 3-7 giây; sự khác biệt tạm thời giữa các replica; region tạm thời không khả dụng. Giảm thiểu bằng: gộp các rule tương tự thành một rule aggregation duy nhất; chạy query lookback dài theo giờ thay vì theo phút; đặt for: tối thiểu gấp 2 lần evaluation interval; dùng offset tối thiểu gấp 2 lần lookback dài nhất; group theo location; ưu tiên tính tỷ lệ lỗi thay vì tỷ lệ thành công; tách numerator/denominator (xem file 06).

Nhánh B: Ingestion-side — dữ liệu chưa từng đến Monarch

B1 — Kiểm tra log collector đầu tiên

bash
kubectl logs -f -n gmp-system -l app.kubernetes.io/part-of=gmp
kubectl logs -f -n gmp-system -l app.kubernetes.io/name=collector -c prometheus

# GKE Autopilot dùng namespace khác:
kubectl logs -f -n gke-gmp-system -l app.kubernetes.io/part-of=gmp

B2 — Bật target status để xem chi tiết endpoint (chỉ tạm thời — xem file 02)

bash
kubectl -n NAMESPACE_NAME describe podmonitorings/POD_MONITORING_NAME

Tìm field Status.Endpoint Statuses. Nếu field này thiếu hoặc lỗi thời: collector không tiếp cận được target trên cùng node, hoặc selector không match Pod nào.

B3 — Collectors Fraction < 1

Nghĩa là chỉ một phần collector tiếp cận được (ví dụ 0.5 = 50%). Kiểm tra:

bash
kubectl -n gmp-system get pods --selector="app.kubernetes.io/name=collector"
kubectl -n gmp-system describe pods/collector-<id>

Kiểm tra log operator, xác nhận collector Pod healthy và mạng thông suốt.

B4 — Target unhealthy

Xem field Status.Endpoint Statuses.Unhealthy Targets, đọc Last Error. Xác nhận scrape endpoint thực sự đang chạy bằng port-forward thủ công:

bash
kubectl port-forward "$(kubectl get pods -l app.kubernetes.io/name=redis -n test -o jsonpath='{.items[0].metadata.name}')" -n test 9121
# Truy cập localhost:9121/metrics để xác nhận exporter trả về dữ liệu

B5 — 401 Unauthorized / x509: certificate signed by unknown authority

Cấu hình sai loại authorization trong ScrapeEndpoint của PodMonitoring — kiểm tra lại HTTPClientConfig.

B6 — Quota ingest bị vượt (429: Quota exceeded for quota metric 'Time series ingestion requests')

Quota mặc định là 100.000 sample/giây — thường bị chạm ngay ở giai đoạn triển khai ban đầu khi bật GMP trên nhiều cluster cùng lúc mà chưa áp dụng content filtering (file 05). Yêu cầu tăng quota qua Google Cloud Support nếu volume hợp lý và đã được filter đúng mức.

B7 — Thiếu quyền service account của node

bash
gcloud compute instances describe NODE_NAME --format="json" | jq .serviceAccounts

Xác nhận node có access scope Monitoring API. Nếu dùng service account chuyên dụng, gán roles/monitoring.metricWriter.

B8 — "failed calling webhook ... EOF" khi tạo PodMonitoring

Cấu hình PodMonitoring/ClusterPodMonitoring không khớp spec API. Rà soát lại theo PodMonitoring CRD Reference.

B9 — "scrape timeout greater than scrape interval"

Sửa timeout nhỏ hơn interval trong ScrapeEndpoint (xem file 02).

B10 — Thiếu # TYPE metadata ("no metadata found for metric name")

Một số thư viện (ví dụ VictoriaMetrics trước v1.28.0) cố ý bỏ dòng TYPE. Đổi sang thư viện exporter tương thích chuẩn Prometheus text format đầy đủ.

B11 — Time-series collision ("Points were written more frequently than maximum sampling period", "Points must be written in order")

Nguyên nhân thường gặp: chạy HA pair không đúng cách (2 collector cùng ghi một series); relabeling rule vô tình xóa mất label job/instance khiến hai series khác nhau trông giống hệt nhau; scrape interval dưới 5 giây (giới hạn tối thiểu của Monarch). Sửa: giảm về 1 replica hoặc dùng cơ chế HA đúng chuẩn (--export.ha.backend=kube, xem file 07); rà soát lại relabeling rule; tăng interval lên tối thiểu 5s.

B12 — Vượt giới hạn label descriptor ("metric would have over PER_PROJECT_LIMIT labels")

Xem phân tích đầy đủ ở file 04. Chẩn đoán bằng metricDescriptors.list, sửa exporter/relabeling rule, sau đó xóa descriptor rác bằng metricDescriptors.delete.

B13 — Metric descriptor quota cạn kiệt (giới hạn 25.000/project)

Dấu hiệu: trang Metrics Management cho thấy số metric inactive vượt xa số active. Nguyên nhân gốc hầu như luôn là metric name nhúng dữ liệu định danh thay vì dùng label (chi tiết ví dụ cụ thể ở file 04).

B14 — Metric biến mất từ target chạy ngắn hạn

Job/Pod hoàn thành trước 5 phút — không đủ thời gian để được scrape ổn định (liên quan filterRunning, xem file 02). Sửa: kéo dài thời gian chạy job tối thiểu 5 phút, hoặc chuyển sang log-based metric nếu tần suất sự kiện thấp.

B15 — OOM ở collector hoặc operator

Collector OOM: bật vertical pod autoscaling cho collector DaemonSet. Operator OOM trên cluster lớn: tắt tính năng target status (đã bật để debug ở B2 — nhớ tắt lại).

B16 — "Monitored resource has too many time series" (HTTP 503)

Đây là biểu hiện của cơ chế Monarch Quarantiner — phân tích đầy đủ nguyên nhân và thứ tự khắc phục ở file 04. Có thể yêu cầu Cloud Customer Care kiểm tra "Monarch Quarantiner hospitalization logs" để xác nhận.

B17 — Duplicate histogram bucket

"Distribution explicit_buckets.bounds entry 1 has value 1 which is less than entry 0 which is 1" — hai điểm histogram với cùng tập label trên cùng một /metrics endpoint. Sửa exporter để đảm bảo giá trị label mặc định (ví dụ label rỗng bị hiểu là "unknown") không trùng với một tổ hợp label khác đã tồn tại.

B18 — Không lỗi nhưng cũng không có metric nào

Checklist đầy đủ theo tài liệu chính thức: PodMonitoring trỏ đúng tên port đã khai báo trong Deployment; label selector khớp giữa Deployment và PodMonitoring; endpoint truy cập thủ công được; PodMonitoring nằm đúng namespace ứng dụng (không phải gmp-system/gke-gmp-system); tên metric/label không có dấu _ ở đầu; không có filter nào vô tình loại bỏ toàn bộ dữ liệu; nếu chạy ngoài Google Cloud, project/location được set tường minh (không phải global); metric thuộc một trong bốn kiểu Prometheus chuẩn (Info/Stateset/GaugeHistogram của OpenMetrics bị âm thầm loại bỏ).

Checklist tổng hợp theo thứ tự thực hiện

  1. Query up trong Metrics Explorer PromQL tab → xác định nhánh A hay B
  2. Nhánh A: kiểm tra permission → timeout client → HTTP method → label validation → quota đọc → metrics scope đa project
  3. Nhánh B: đọc log collector → bật target status tạm thời → kiểm tra collectors fraction → port-forward xác nhận exporter → kiểm tra service account permission → kiểm tra quota ingest
  4. Nếu nghi ngờ cardinality: mở trang Metrics Management, so sánh active vs inactive metric descriptor, kiểm tra label cardinality theo metric
  5. Nếu nghi ngờ cost: query Metric Ingestion Attribution theo namespace/workload (xem file 05)
  6. Đảm bảo firewall cho phép cả POSTGET đến monitoring.googleapis.com
  7. Tắt lại mọi tính năng debug tạm thời (target status) sau khi kết thúc điều tra

Tham khảo chính thức