Skip to content

Observability Stack — Telemetry Phân Tầng & Mental Model

Vì sao phải có một mental model trước khi bật bất kỳ signal nào

Sai lầm phổ biến nhất khi tiếp cận observability GKE không phải là thiếu công cụ — GKE và Google Cloud Observability cung cấp dư thừa công cụ — mà là bật signal mà không có một mô hình tinh thần về cấu trúc của chúng. Kết quả là hai thái cực đều tệ: hoặc bật tất cả mọi thứ (control plane metric, kube-state-metric, cAdvisor, audit Data Access, application metric high-cardinality) rồi nhận hóa đơn observability vượt cả compute mà chẳng query đến 80% trong số đó; hoặc chỉ dựa vào những thứ bật mặc định rồi mù hoàn toàn khi sự cố nằm ở tầng không được quan sát.

File này không dạy cách bật một metric cụ thể — các file sau làm điều đó. Mục tiêu ở đây là cài đặt mental model: telemetry trên GKE được tổ chức thành ba tầng, mỗi tầng có một chủ thể sinh ra, một bộ signal đặc trưng, một cơ chế thu thập, và một mô hình chi phí riêng; và có ba loại signal — metric, log, trace — mỗi loại trả lời một kiểu câu hỏi khác nhau và có đặc tính chi phí khác nhau. Khi bạn nội tâm hóa được mô hình hai chiều này (tầng × loại signal), mọi quyết định "bật gì, lưu bao lâu, alert trên cái nào" trở nên có nguyên tắc thay vì tùy hứng.

Theo tài liệu Observability for GKE, GKE được thiết kế để tích hợp chặt với Google Cloud Observability (Cloud Monitoring, Cloud Logging, Cloud Trace) và Google Cloud Managed Service for Prometheus. Điểm cần hiểu sâu là sự tích hợp này không phải một tính năng đơn lẻ mà là một tập hợp các đường ống telemetry song song, mỗi đường phục vụ một tầng và một loại signal. Hiểu các đường ống này khớp với nhau ra sao là điều kiện để thiết kế một hệ quan sát mạch lạc.

Internal model: ba tầng telemetry

Tầng 1 — Control plane (Google quản lý, bạn opt-in quan sát)

Control plane — API server, scheduler, controller-manager, etcd — chạy trong project do Google quản lý, không nằm trong project của bạn (Chương 5). Bạn không SSH vào được, không scrape trực tiếp được endpoint /metrics của chúng như Prometheus thông thường. Thay vào đó, GKE phơi bày một tập metric chọn lọc của control plane qua Managed Service for Prometheus khi bạn opt-in.

Đặc tính quan trọng của tầng này:

  • Bạn không sinh ra signal, bạn chỉ bật/tắt việc thu nó. Control plane luôn phát metric nội bộ; câu hỏi duy nhất là bạn có cho GKE đẩy chúng vào Cloud Monitoring hay không.
  • Mặc định tắt (trừ một phần nhỏ trong system metric). Lý do là chi phí: control plane metric như apiserver_request_duration_seconds có nhiều label (verb, group, version, scope, code), tạo nhiều time series. Google để bạn quyết định có trả phí cho chúng không.
  • Đây là tầng dễ bị bỏ quên nhất. Nhiều đội monitor workload rất kỹ nhưng chưa từng bật control plane metric, nên khi kubectl chậm hay Pod kẹt Pending vì scheduler, họ không có dữ liệu để biết nguyên nhân.

Tầng 2 — System (node, kubelet, container — agent GKE thu tự động)

Mỗi node GKE chạy các agent thu thập telemetry hạ tầng: metric agent (đẩy system metric), logging agent (fluent-bit, đẩy log), và — khi bật — collector của Managed Service for Prometheus. Tầng này bao gồm:

  • System metrics: CPU/memory/disk của node, ephemeral storage, network, Pod/container resource ở mức tổng hợp. Bật mặc định trên Standard và luôn bật trên Autopilot.
  • kube-state-metrics (kube_*): trạng thái của Kubernetes object — Pod phase, Deployment replica, HPA target. Đây không phải metric tài nguyên mà là metric trạng thái khai báo của API object.
  • cAdvisor/kubelet (container_*): metric tài nguyên ở mức container, gồm cả container_cpu_cfs_throttled_periods_total để phát hiện CPU throttling.
  • DCGM (DCGM_FI_*): metric GPU khi node có GPU và bật Google-managed driver.

Đặc tính quan trọng: agent thu tự động, bạn không cần instrument gì, nhưng phần lớn các gói (kube-state, cAdvisor, DCGM) là opt-in theo gói vì chúng làm tăng lượng sample ingest. System metric cơ bản miễn phí trong hạn mức; các gói mở rộng đi qua Managed Service for Prometheus và tính phí theo sample.

Tầng 3 — Workload (application — chỉ tồn tại nếu bạn instrument)

Đây là tầng quan trọng nhất về mặt nghiệp vụ và cũng là tầng bạn chịu trách nhiệm hoàn toàn:

  • Application metrics: số request, error rate, latency, queue depth, business metric. Chỉ tồn tại nếu code của bạn expose một endpoint /metrics (Prometheus) hoặc đẩy metric qua OpenTelemetry/Cloud Monitoring API.
  • Workload logs: stdout/stderr của container, được logging agent thu và đẩy lên Cloud Logging. Đây là thứ duy nhất ở tầng này gần như "miễn phí có sẵn" — chỉ cần app ghi ra stdout.
  • Distributed traces: đường đi của một request qua nhiều service, chỉ tồn tại nếu app được instrument bằng OpenTelemetry SDK hoặc auto-instrumentation.

Đặc tính quyết định: observability tầng này không bật được bằng một flag cluster (trừ workload log). Nó là kết quả của một kỷ luật engineering — instrument code, expose metric, propagate trace context. Đây là lý do nhiều cluster có system metric đầy đủ nhưng vẫn "mù nghiệp vụ": họ biết node có bao nhiêu CPU rảnh nhưng không biết tỷ lệ checkout thất bại của ứng dụng thương mại điện tử là bao nhiêu.

Internal model: ba loại signal và mô hình chi phí

Cắt ngang ba tầng là ba loại signal. Hiểu đặc tính của từng loại quyết định bạn nên dùng loại nào cho mục đích gì.

Metric — time series, rẻ, tốt cho alerting và xu hướng

Metric là một chuỗi số theo thời gian, định danh bởi tên + bộ label. Đặc tính:

  • Nén cực tốt và rẻ để lưu. Một time series là một dãy (timestamp, value); lưu hàng triệu điểm rất hiệu quả. Đây là signal lý tưởng cho alerting (ngưỡng, percentile) và quan sát xu hướng dài hạn.
  • Chi phí tỷ lệ với cardinality, không phải số điểm. Managed Service for Prometheus tính phí theo số sample ingest, mà số sample ≈ số time series × tần suất scrape. Mỗi tổ hợp label duy nhất là một series mới. Đây là gốc rễ của cardinality explosion: thêm một label user_id với một triệu giá trị biến một metric thành một triệu series.
  • Mất chi tiết sự kiện đơn lẻ. Metric cho bạn "tỷ lệ lỗi 5%" nhưng không cho biết request cụ thể nào lỗi và vì sao. Đó là việc của log/trace.

Log — sự kiện rời rạc, đắt, tốt cho forensics

Log là bản ghi văn bản (hoặc JSON) của một sự kiện tại một thời điểm. Đặc tính:

  • Giàu chi tiết, đắt để lưu. Mỗi log entry có thể vài KB; ở quy mô hàng tỷ entry/ngày, Cloud Logging ingest hàng TB. Chi phí tính theo volume ingest, đây là hạng mục dễ bùng nổ nhất.
  • Không thể thiếu cho forensics và audit. Khi cần biết chính xác "chuyện gì đã xảy ra lúc 03:17", chỉ log trả lời được. Audit log (ai làm gì) bắt buộc cho compliance.
  • Khó dùng cho alerting trực tiếp. Alert trên log (log-based metric) hoạt động nhưng kém hiệu quả hơn alert trên metric. Tốt nhất là chuyển pattern log lặp lại thành metric.

Trace — đường đi request, tốt cho latency breakdown

Trace ghi lại hành trình của một request qua các service, mỗi chặng là một span với thời gian bắt đầu/kết thúc. Đặc tính:

  • Công cụ duy nhất trả lời "độ trễ này phát sinh ở đâu trong chuỗi gọi". Khi service A gọi B gọi C, trace cho biết 200ms latency nằm ở chặng nào.
  • Phải sampling. Trace mọi request là không khả thi về chi phí và overhead; thường sample 1–10% hoặc dùng tail-based sampling để giữ trace của request lỗi/chậm.
  • Yêu cầu context propagation. Trace chỉ liền mạch nếu mọi service truyền trace header (W3C traceparent) qua các lời gọi. Một service không propagate làm đứt trace.

Ba loại signal này bổ sung nhau, không thay thế nhau. Mô hình tinh thần đúng: metric phát hiện vấn đề (cái gì bất thường), log/trace chẩn đoán vấn đề (vì sao, ở đâu). Một hệ quan sát trưởng thành dùng metric để alert, rồi nhảy sang log và trace để điều tra — và bước nhảy đó chỉ mượt khi mọi signal chia sẻ resource label chung.

Resource label nhất quán — nền tảng của correlation

Đây là khái niệm quan trọng nhất của cả chương, và là lý do kỹ thuật khiến tích hợp native GKE ↔ Google Cloud Observability có giá trị lớn. Mọi telemetry sinh ra trong GKE — bất kể tầng nào, loại signal nào — được gắn một bộ resource label nhất quán.

Theo tài liệu Managed Service for Prometheus, mọi metric tự động nhận các nhãn dành riêng: project_id, location, cluster, namespace, job, instance. Tương tự, log entry trong Cloud Logging mang resource.type=k8s_container với các nhãn cluster_name, namespace_name, pod_name, container_name. Trace mang service name và resource attribute tương ứng.

Hệ quả thực tiễn của sự nhất quán này:

  • Bạn có thể nhảy từ một điểm bất thường trên metric sang đúng log của Pod đó. Thấy container_memory_working_set_bytes của Pod checkout-7d9f tăng vọt rồi Pod biến mất? Lọc log Cloud Logging theo cùng pod_name=checkout-7d9f để thấy dòng OOMKilled và stack trace cuối cùng.
  • Bạn có thể join metric workload với metric hạ tầng. Vì cả application metric (qua PodMonitoring) và cAdvisor metric đều mang namespace/pod, bạn có thể tương quan "latency app tăng" với "container bị throttle" trên cùng một Pod.
  • Tránh xung đột nhãn. Nếu metric ứng dụng của bạn tự định nghĩa một nhãn trùng tên nhãn dành riêng (ví dụ cluster), Managed Service for Prometheus tự thêm tiền tố exported_ (thành exported_cluster) để không ghi đè nhãn hệ thống — một chi tiết cần biết khi viết PromQL.

Khi xây dựng self-managed stack (file 08), thử thách lớn nhất chính là tái tạo sự nhất quán nhãn này thủ công — đảm bảo Elasticsearch, Prometheus tự quản, Jaeger đều gắn cùng cluster/namespace/pod. Mất nhất quán nhãn = mất khả năng correlate = mất phần lớn giá trị của observability.

Production architecture patterns

Pattern 1 — Fully managed (mặc định khuyến nghị cho đa số)

Dùng toàn bộ stack Google: system + control plane metric vào Cloud Monitoring/Managed Prometheus, log vào Cloud Logging, trace vào Cloud Trace qua Managed OpenTelemetry. Ưu điểm: zero ops cho observability infra, resource label nhất quán tự động, tích hợp dashboard sẵn. Đây là lựa chọn đúng cho phần lớn tổ chức vì nó loại bỏ một hệ thống stateful phức tạp phải tự vận hành.

Pattern 2 — Hybrid (managed metric + self-managed log analytics)

Giữ metric/trace trên managed stack (rẻ, ít ops) nhưng đẩy log sang Elastic/OpenSearch tự quản để có khả năng full-text search và log analytics nâng cao mà Cloud Logging không cung cấp. Phổ biến ở tổ chức có nhu cầu phân tích log sâu (security analytics, log-heavy debugging). Đánh đổi: phải tự đảm bảo nhãn nhất quán và vận hành cluster Elastic.

Pattern 3 — Fully self-managed (data sovereignty / multi-cloud / anti-lock-in)

Prometheus + Thanos/Mimir, Loki/Elastic, Jaeger/Tempo — toàn bộ tự vận hành trên GKE. Chỉ hợp lý khi có ràng buộc cứng: data không được rời cluster, multi-cloud cần một pane of glass thống nhất, hoặc yêu cầu compliance đặc thù. Chi phí vận hành cao và đây là quyết định cần biện minh rõ ràng (file 08).

Common mistakes / anti-patterns

  • Bật mọi gói metric "cho chắc". Bật control plane + kube-state đầy đủ + cAdvisor + DCGM + application high-cardinality ngay từ đầu mà chưa biết sẽ query cái gì. Hệ quả ở scale: hóa đơn Managed Prometheus tăng theo số sample, và phần lớn series không bao giờ được nhìn. Đúng: bật theo nhu cầu — system + control plane trước, thêm gói khi có câu hỏi cụ thể cần trả lời.

  • Nhầm metric với log. Cố nhồi thông tin chi tiết (request ID, payload) vào label metric để "đỡ phải xem log". Đây là con đường nhanh nhất tới cardinality explosion. Đúng: metric cho số liệu tổng hợp bounded, log cho chi tiết per-event.

  • Bỏ qua tầng workload. Có đầy đủ system/control plane metric nhưng không instrument application, nên biết mọi thứ về hạ tầng mà không biết gì về hành vi nghiệp vụ. Khi user phàn nàn "checkout chậm", không có metric nào của riêng checkout để nhìn. Đúng: mỗi service quan trọng phải expose golden signal (file 04).

  • Self-managed mà không tái tạo nhãn nhất quán. Dựng Elastic + Prometheus tự quản nhưng mỗi hệ gắn nhãn khác nhau, nên không correlate được. Mất đúng thứ giá trị nhất của observability. Đúng: chuẩn hóa resource label across toàn stack ngay từ thiết kế.

GCP-native implementation guidance

Kiểm tra cấu hình observability hiện tại của cluster:

bash
# Xem cấu hình monitoring/logging packages đang bật
gcloud container clusters describe CLUSTER_NAME \
  --location=LOCATION \
  --format="yaml(monitoringConfig, loggingConfig)"

Bật một bộ tối thiểu hợp lý cho production (system + control plane + log đầy đủ):

bash
gcloud container clusters update CLUSTER_NAME \
  --location=LOCATION \
  --monitoring=SYSTEM,API_SERVER,SCHEDULER,CONTROLLER_MANAGER \
  --logging=SYSTEM,WORKLOAD

Kiểm tra một metric đã chảy vào Cloud Monitoring chưa, qua PromQL trong Cloud Monitoring (Metrics Explorer → PromQL):

promql
# Số request API server theo mã trả về (cần bật API_SERVER)
sum by (code) (rate(apiserver_request_total[5m]))

Điểm cần nhớ: mọi metric trên đều mang resource label cluster, location, namespace tự động — đó là sợi chỉ để correlate với log và trace trong các file sau.

Official references


Tóm lại: observability GKE là một ma trận hai chiều — ba tầng (control plane / system / workload) nhân ba loại signal (metric / log / trace), tất cả khâu lại bằng resource label nhất quán. Nắm ma trận này, bạn biết bật gì, lưu bao lâu, alert trên cái nào, và quan trọng nhất là biết nhìn ô nào khi một incident xảy ra. Các file tiếp theo đi sâu vào từng ô của ma trận này.