Rule Evaluator: Recording Rules & Alert Evaluation Ở Quy Mô
Rule Evaluator là gì, và vì sao nó không phải là Alertmanager
File 01 đã mô tả tổng quan Rule Evaluator như "một Deployment riêng biệt tính toán trước kết quả query phức tạp". Ở phần này, ta cần làm rõ một điểm dễ gây nhầm lẫn nghiêm trọng: Rule Evaluator chỉ chịu trách nhiệm evaluate PromQL expression theo interval và ghi kết quả trở lại Monarch (đối với recording rule) hoặc phát alert (đối với alerting rule) — nó không lưu trữ, không dedupe, không route notification.
Theo tài liệu chính thức về managed rule evaluation, Rule Evaluator chạy như "single-replica Deployment với resource request/limit cố định" (Managed rule evaluation and alerting). Đây là một quyết định thiết kế quan trọng cần hiểu đúng: single-replica nghĩa là không có HA tự động ở tầng evaluation — nếu Rule Evaluator Pod bị OOM kill hoặc crash, mọi recording rule và alerting rule ngừng evaluate cho đến khi Pod được reschedule. Với recording rule, hệ quả là gap dữ liệu tạm thời trong metric đã tính trước. Với alerting rule, hệ quả nghiêm trọng hơn: một sự cố thật có thể không được phát hiện trong khoảng thời gian Rule Evaluator down, bất kể alerting policy có "đúng" đến đâu.
Điều này dẫn đến hai hành động vận hành cụ thể: (1) luôn đặt Cloud Monitoring alerting policy giám sát chính uptime của Rule Evaluator Deployment như một "meta-alert" — alert canh alert; (2) không coi Rule Evaluator resource limit là cố định vĩnh viễn — tài liệu ghi nhận nhu cầu triển khai Vertical Pod Autoscaler khi khối lượng rule lớn khiến Pod OOM thường xuyên.
Nơi output của rule đi về đâu
Với recording rule, kết quả được ghi ngược trở lại Monarch như một metric mới, trở thành time series có thể query như bất kỳ metric nào khác. Với alerting rule, kết quả fired alert được forward đến local Alertmanager triển khai trong cluster, cấu hình qua OperatorConfig — đây khác với self-hosted Prometheus tiêu chuẩn nơi Alertmanager thường tích hợp sẵn. Managed collection không tự động cung cấp Alertmanager; bạn phải tự triển khai nó trong mỗi cluster, và nếu muốn tập trung alert từ nhiều cluster vào một Alertmanager, phải tự dựng kết nối qua Kubernetes Endpoints resource trỏ chéo cluster — GMP không cung cấp cơ chế native cho việc này.
Đây là điểm khác biệt cần lưu ý so với alerting của Cloud Monitoring thuần túy (đã nói ở Chương 39, phần 4): alerting rule kiểu Prometheus (alert:, for:, labels:, annotations:) evaluate và route qua đường Alertmanager riêng, song song với Cloud Monitoring Alerting Policy chứ không tự động hợp nhất. Nhiều tổ chức vô tình duy trì hai hệ thống alerting độc lập (Prometheus-style alerting rule và Cloud Monitoring alerting policy) mà không nhận ra, dẫn đến alert trùng lặp hoặc — tệ hơn — một sự cố chỉ được một trong hai hệ thống bắt được vì rule chỉ tồn tại ở một phía.
Ba loại resource: Rules, ClusterRules, GlobalRules — khác biệt về scope, không phải cú pháp
Cả ba resource dùng chung cú pháp PromQL bên trong (groups, rules, record/alert, expr, for), nhưng khác biệt về phạm vi dữ liệu được filter khi evaluate — và đây chính là phần dễ gây lỗi thiết kế reliability nhất.
Rules — namespace-scoped, mặc định nên dùng
Theo tài liệu chính thức: "Alerting và recording rule định nghĩa trong Rules được scope theo project_id, cluster, và namespace của chính resource đó" (Managed rule evaluation and alerting). Nghĩa là một Rules object đặt trong namespace checkout chỉ evaluate trên dữ liệu thuộc namespace checkout, cluster hiện tại, project hiện tại — dù expression bên trong không viết filter label tường minh nào. Bộ lọc scope được Rule Evaluator tự động áp thêm vào trước khi gửi query đến Monarch.
ClusterRules — cluster-scoped
Filter chỉ theo project_id và cluster, bỏ qua namespace — evaluate trên toàn bộ namespace trong cluster. Tài liệu khuyến nghị dùng loại này cho "horizontal metrics" — dữ liệu không thuộc về một namespace cụ thể, ví dụ metric của service mesh (Istio/Anthos Service Mesh) đo lường traffic đi qua nhiều namespace, hoặc rule cần tính tỷ lệ lỗi tổng của toàn cluster.
GlobalRules — không giới hạn label, phạm vi toàn metrics scope
Đây là loại rộng nhất: "chọn toàn bộ dữ liệu trong metrics scope đang truy vấn mà không giới hạn label nào". Tài liệu nhấn mạnh rõ ràng: GlobalRules chỉ nên dùng cho các trường hợp hiếm — tính SLO toàn cục xuyên nhiều project, hoặc rule cần dữ liệu xuyên cluster trong cùng một project. Nó bắt buộc phải dùng khi alert trên metric của Cloud Monitoring gốc (system metric của GKE, VM) — vì các metric này không mang label cluster/namespace theo mô hình Prometheus.
Bảng quyết định
| Tiêu chí | Rules | ClusterRules | GlobalRules |
|---|---|---|---|
| Scope filter tự động | project + cluster + namespace | project + cluster | Không filter, toàn metrics scope |
| Ai nên deploy | Application team, mỗi namespace | Platform team, một lần mỗi cluster | Hiếm khi, chỉ SRE/platform lead |
| Use case điển hình | Recording rule cho service riêng, alert SLO của một service | Metric service mesh, tổng error rate cluster | SLO xuyên project, alert trên GKE system metric |
| Rủi ro reliability | Thấp — scope hẹp, ít khả năng lẫn dữ liệu | Trung bình | Cao nếu không cẩn thận label |
Nguyên tắc vận hành được tài liệu nêu rõ: "strongly recommend using Rules and ClusterRules whenever possible" vì độ tin cậy cao hơn và khớp tự nhiên với mô hình triển khai/tenancy của Kubernetes. GlobalRules nên được xem như ngoại lệ có kiểm soát, không phải công cụ mặc định — càng nhiều rule dùng GlobalRules, phạm vi dữ liệu Rule Evaluator phải quét mỗi lần evaluate càng lớn, kéo theo chi phí query nội bộ và rủi ro timeout ngay trong chính quá trình evaluate rule.
Cạm bẫy phổ biến nhất: aggregate away cluster/namespace khi dùng GlobalRules
Đây là anti-pattern quan trọng nhất trong toàn bộ phần rule evaluation, vì hậu quả của nó không xuất hiện ngay mà chỉ lộ ra khi cần debug một alert xuyên cluster. Khi viết một GlobalRules recording rule như:
groups:
- name: global_error_budget
rules:
- record: service:error_ratio:global
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))Nếu bạn không giữ lại by (cluster, namespace) trong sum(), kết quả sinh ra là một con số duy nhất, gộp toàn bộ organization, mất hoàn toàn khả năng biết cluster nào hay namespace nào đang gây ra tỷ lệ lỗi cao. Best practice chính thức yêu cầu: "preserve cluster and namespace labels in results to maintain query performance" (Evaluation of rules and alerts with managed collection), và tài liệu nói rõ việc xóa cả hai label này cùng lúc là "strongly discouraged". Lý do sâu xa không chỉ là mất thông tin debug — kết quả sau aggregation mất label định danh sẽ làm giảm khả năng downstream query filter hiệu quả (không còn tận dụng được cơ chế đẩy filter xuống zone/leaf đã nói ở file 01), khiến các query dùng lại recording rule này chậm hơn dự kiến.
Còn với project_id, khuyến nghị khác một chút: chỉ giữ lại label này khi thực sự cần thiết, vì giữ project_id trong kết quả GlobalRules đòi hỏi service account của Rule Evaluator phải có quyền ghi (roles/monitoring.metricWriter) trên từng project mà kết quả cần được attribute vào — một gánh nặng cấp quyền không nhỏ nếu metrics scope của bạn trải rộng hàng chục project.
Cơ chế multi-project: queryProjectID và quyền hạn hai chiều
Khi một GlobalRules evaluate xuyên nhiều project, Rule Evaluator cần chạy trong ngữ cảnh của một project có multi-project metrics scope (khái niệm đã nói ở file 01), hoặc được cấu hình tường minh queryProjectID trỏ đến project scoping đó. Quyền hạn cần thiết là hai chiều và không đối xứng:
- Đọc: service account cần
roles/monitoring.viewertrên project scoping (để root mixer cho phép fan-out sang các project được monitor). - Ghi: service account cần
roles/monitoring.metricWriterriêng trên từng project nơi kết quả recording rule cần được ghi trở lại.
Sai lầm phổ biến là chỉ cấp quyền đọc mà quên quyền ghi trên các project con — dẫn đến hiện tượng "rule evaluate được, alert vẫn fire đúng, nhưng recording rule kết quả biến mất" vì write bị từ chối âm thầm (log lỗi Permission monitoring.timeSeries.create denied chỉ xuất hiện trong log Rule Evaluator, không hiển thị ở đâu khác).
Recording rule: công cụ giảm chi phí query, không phải giảm chi phí ingest
Một hiểu lầm phổ biến là coi recording rule như cách "tiết kiệm cost GMP". Thực tế recording rule tạo thêm một metric mới, tức thêm time series mới cần lưu trữ (dù thường cardinality thấp hơn nhiều so với raw metric vì đã aggregate). Giá trị thực sự của recording rule nằm ở việc giảm chi phí tính toán tại thời điểm query — dashboard hoặc alerting policy dùng lại metric đã pre-compute thay vì phải chạy lại phép rate() + sum by() phức tạp mỗi lần load, vốn có thể chạm vào hàng triệu raw sample nếu chạy trực tiếp trên metric gốc.
Nguyên tắc quyết định khi nào cần recording rule: nếu một PromQL expression (1) được dùng lại ở nhiều dashboard/alerting policy, và (2) bản thân expression đó tốn kém về mặt tính toán (nhiều phép rate() lồng nhau, join qua nhiều metric, subquery) — hãy pre-compute nó bằng recording rule. Nếu một query chỉ chạy một lần, việc thêm recording rule chỉ làm tăng cardinality mà không mang lại lợi ích tương xứng.
ConfigMap size limit và nhu cầu bật gzip
Một giới hạn vận hành ít được biết đến: cấu hình rule (bao gồm toàn bộ Rules/ClusterRules/GlobalRules được compile) được Rule Evaluator nạp thông qua ConfigMap, và ConfigMap trong Kubernetes có giới hạn kích thước cứng (khoảng 1MiB, giới hạn của etcd object). Khi tổ chức có hàng trăm rule group phức tạp, tài liệu ghi nhận khả năng chạm giới hạn này, và khuyến nghị bật gzip compression cho cấu hình rule như một giải pháp giảm kích thước trước khi buộc phải tách rule ra kiến trúc khác (ví dụ chia nhỏ theo cluster thay vì gom hết vào GlobalRules).