Cross-Layer Correlation, GKE Dashboard & Incident Timeline
Tại sao Cross-Layer Correlation là Kỹ Năng Hiếm
Phần lớn engineers debug trong một layer: "Pod bị OOM, tăng memory limit." Hoặc "DNS timeout, restart CoreDNS." Những fix này giải quyết triệu chứng ngay lập tức.
Cross-layer correlation là kỹ năng khác: kết nối dots giữa các layer khác nhau để hiểu causal chain đầy đủ. Ví dụ:
- "Pod OOM kill" chỉ là triệu chứng. Cross-layer view: trace cho thấy một endpoint nhận 10x traffic đột biến (layer: request) → metric cho thấy memory tăng tuyến tính (layer: resource) → kernel OOM kill (layer: infrastructure) → kubelet restart pod (layer: Kubernetes) → traffic bị drop trong 30 giây khi pod starting up (layer: service).
- Fix đúng: tăng memory limit + thêm HPA + rate limiting trên endpoint đó. Không phải chỉ tăng memory.
Cross-layer correlation còn khó vì ba vấn đề kỹ thuật thực sự:
Clock Skew
Trong distributed system, đồng hồ giữa các nodes và services không đồng bộ hoàn toàn. NTP synchronizes but không perfect — có thể có sai lệch vài millisecond đến vài giây.
Khi correlate events từ nhiều sources:
- Log A ghi timestamp 14:23:45.123 (từ node X)
- Log B ghi timestamp 14:23:45.098 (từ node Y)
Log B có timestamp sớm hơn 25ms. Nhưng có thể node Y's clock nhanh hơn thực tế 50ms. Ai xảy ra trước?
Cách xử lý: Không assume correlation chính xác ở millisecond precision. Dùng window ±2 giây khi correlate cross-node events.
Sampling Bias trong Tracing
Cloud Trace không sample 100% requests (chi phí quá cao). Mặc định sampling rate thấp (có thể chỉ 1% hoặc tail sampling). Điều này tạo bias:
- Incident ảnh hưởng 1% requests có thể không có trace nào để analyze
- Traces bạn có thể là "survivor bias" — các request nhanh được trace, request chậm (đang hang) chưa complete trace
- Tail-based sampling (sample traces có high latency hoặc errors) tốt hơn cho debugging nhưng cần setup
Log Lag và Ordering
Như đã đề cập ở Chapter 01, mỗi log type có latency khác nhau:
- Container stdout: 5-30 giây
- Kubelet system log: 10-60 giây
- Audit log: 1-5 phút
Khi bạn build timeline từ nhiều log sources, events trong logs có thể xuất hiện sau khi chúng thực sự xảy ra. Nếu không account cho latency, timeline sẽ sai.
Cơ Chế Trace Context Propagation
Trace ID và Span Model
Distributed tracing hoạt động bằng cách propagate trace context qua toàn bộ request path:
Client → Service A → Service B → Service C → Database
↓ ↓ ↓ ↓
TraceID SpanID(1) SpanID(2) SpanID(3)
ParentID=root ParentID=1 ParentID=2TraceID: Unique identifier cho toàn bộ request chain (128-bit, generated một lần ở entry point) SpanID: Identifier cho một unit of work trong trace ParentID: Liên kết spans thành cây
Khi Service A call Service B, Service A inject vào HTTP header:
X-Cloud-Trace-Context: TRACE_ID/SPAN_ID;o=1(Google format)- Hoặc
traceparent: 00-TRACE_ID-SPAN_ID-01(W3C format)
Service B extract header, tạo span với ParentID = SpanID của A.
Tích Hợp Trace Context với Cloud Logging
Đây là feature quan trọng nhất cho cross-layer debugging. Nếu application log có chứa trace context, Cloud Logging có thể correlate log entry với trace span:
Trong structured log JSON:
{
"message": "Processing order #12345",
"severity": "INFO",
"logging.googleapis.com/trace": "projects/PROJECT_ID/traces/TRACE_ID",
"logging.googleapis.com/spanId": "SPAN_ID",
"logging.googleapis.com/traceSampled": true
}Sau khi inject trace context vào logs, trong Logs Explorer bạn có thể:
- Click vào một log entry
- Xem "Trace" link → Jump thẳng đến Cloud Trace span tương ứng
- Trong Trace view, thấy tất cả log entries từ toàn bộ request path
Setup trong GKE application (ví dụ với Go):
import "cloud.google.com/go/logging"
// Extract trace context từ request
traceID := r.Header.Get("X-Cloud-Trace-Context")
// Inject vào logger
logger.Log(logging.Entry{
Payload: map[string]string{"message": "Processing"},
Trace: fmt.Sprintf("projects/%s/traces/%s", projectID, traceID),
})Đọc GKE Observability Dashboard
Tổng Quan Dashboard Structure
GKE Observability Dashboard trong Cloud Console được tổ chức theo hierarchy:
Cluster → Nodes → Namespaces → Workloads → Pods → ContainersMỗi level có set metrics riêng. Biết cách navigate và đọc từng chart là kỹ năng cần thiết cho debugging production.
Cluster-Level Health Signals
CPU Utilization (cluster aggregate): Phần trăm allocatable CPU đang được sử dụng. Signal đáng lo:
> 80%sustained: Cluster sắp hết capacity, Pods mới khó schedule- Spike đột ngột không tương ứng với deployment: có thể có runaway process
Memory Utilization (cluster aggregate): Tương tự. Cần phân biệt:
memory.usage(actual RSS usage) vsmemory.requests(scheduled/reserved)- Nếu actual usage >> requests: application đang consume nhiều hơn expected → OOM risk
Node Count and Status: Nếu số nodes giảm đột ngột → node failure hoặc autoscaler scale-in không expect. Nếu nodes stuck ở NotReady → infrastructure issue.
Pod Restart Count (aggregate): High restart count ở cluster level có thể chỉ ra:
- OOM issue (memory limits quá thấp)
- Liveness probe misconfiguration
- Application crashes widespread
Workload-Level Signals
Pod replica count: desired vs available. Nếu available < desired → có Pods bị Pending hoặc crash.
CPU throttling percentage: Phần trăm thời gian CPU bị throttle do limits.cpu. Đây là signal quan trọng thường bị bỏ qua:
- Throttling ≠ OOM kill, không gây restart
- Nhưng throttling gây latency increase
- Application có thể "healthy" (không crash) nhưng slow vì throttling
Cloud Monitoring → Metric:
kubernetes.io/container/cpu/limit_utilization
# Values > 1.0 nghĩa là đang bị throttleRequest vs Limit ratio: Nếu application được cấp requests.cpu = 100m nhưng thực tế dùng 500m → QoS class là Burstable, dễ bị evict khi node pressure.
Node-Level Signals trong Dashboard
Node condition summary: Heatmap của node conditions. Đỏ = có node với condition vấn đề.
Disk usage by node: Identify nodes sắp hết disk (thường là container image cache hoặc container log).
kubelet operations latency: Nếu kubelet operations (create/delete pod) chậm → có thể do containerd overloaded hoặc disk I/O slow.
Xây Dựng Incident Timeline
Tại sao Timeline Quan Trọng
Incident timeline là reconstruction của thứ tự thật sự của events dẫn đến incident. Không phải "chúng tôi phát hiện lúc 14:35", mà là "A xảy ra lúc 14:23, dẫn đến B lúc 14:25, C lúc 14:27, chúng tôi phát hiện lúc 14:35 nhưng nguồn gốc từ 14:23".
Timeline tốt:
- Cho phép xác định trigger event (điều đầu tiên thay đổi, không phải điều đầu tiên được phát hiện)
- Cho thấy propagation path (chain reaction qua các layers)
- Phân biệt cause vs symptom (điều phát hiện đầu tiên thường là symptom, không phải cause)
Nguồn Dữ Liệu Cho Timeline
Để xây dựng timeline, cần collect events từ nhiều nguồn theo thứ tự timestamp:
Nguồn 1: Kubernetes Events
kubectl get events -n NAMESPACE \
--sort-by='.firstTimestamp' \
-o custom-columns="TIME:.firstTimestamp,REASON:.reason,OBJECT:.involvedObject.name,MSG:.message" \
| grep -E "14:2[0-9]" # Filter khoảng thời gian incidentNguồn 2: Cloud Logging (structured query)
# Query logs quanh thời điểm incident với ordering
gcloud logging read \
'resource.type=("k8s_container" OR "k8s_node" OR "k8s_cluster")
AND timestamp >= "2025-06-30T14:20:00Z"
AND timestamp <= "2025-06-30T14:40:00Z"
AND (severity >= "WARNING" OR textPayload:("error" OR "fail" OR "OOM"))' \
--format=json \
| jq 'sort_by(.timestamp) | .[] | {time: .timestamp, resource: .resource.type, msg: (.textPayload // .jsonPayload.message)}'Nguồn 3: Cloud Monitoring Annotations
Marking deployment events, alerts triggered, autoscaler decisions trên metrics charts:
- GKE Deployment rollouts tự động tạo annotations trên Cloud Monitoring charts
- Alert firings được annotate
- Autoscaler scale events được log trong GKE events
Nguồn 4: Audit Logs
# Ai đã thay đổi gì trước incident?
gcloud logging read \
'logName="projects/PROJECT_ID/logs/cloudaudit.googleapis.com%2Factivity"
AND timestamp >= "2025-06-30T14:00:00Z"
AND resource.type="k8s_cluster"
AND proto_payload.method_name:"update" OR proto_payload.method_name:"patch"' \
--format=jsonConstructing the Timeline: Step by Step
Ví dụ thực: Service latency spike lúc 14:35, alert fired. Xây dựng timeline ngược:
T+0: Alert fired (14:35:00) — p99 latency > 5s
↑ tìm khi latency bắt đầu tăng
T-10: Cloud Monitoring cho thấy latency tăng bắt đầu từ 14:25:00
↑ tìm events quanh 14:25
T-15: Kubernetes Events: "Evicted Pod backend-xyz" lúc 14:24:30 (DiskPressure)
↑ tại sao DiskPressure? tìm disk usage metrics
T-20: Cloud Monitoring: disk usage trên node đó đạt 95% lúc 14:23:00
↑ tại sao disk tăng đột ngột?
T-25: Cloud Logging: container log của pod khác ghi "debug mode enabled" lúc 14:22:00
→ Pod đó bắt đầu write excessive debug logs → disk fill → DiskPressure → Pod eviction → latency spike
TRIGGER EVENT: 14:22:00 — debug mode accidentally enabled via config changeTimeline trên cho thấy alert lúc 14:35 nhưng root cause từ 14:22 với causal chain rõ ràng qua 4 layers.
Phân Biệt Causality vs Correlation
Đây là trap phổ biến nhất khi build timeline:
Correlation: Hai events xảy ra gần nhau trong thời gian.
Causation: Event A trực tiếp gây ra Event B.
Ví dụ:
- CPU spike lúc 14:22 (correlation với incident)
- Memory spike lúc 14:22 (correlation)
- Config change lúc 14:22 (correlation)
Tất cả ba đều correlate. Nhưng causal chain là: config change → debug logs enabled → disk fill → eviction → latency. CPU và memory spike là epiphenomena (hậu quả phụ), không phải nguyên nhân.
Cách test causality: Hỏi "Nếu bỏ event A, event B có còn xảy ra không?"
- Bỏ CPU spike → disk vẫn fill → incident vẫn xảy ra → CPU spike không phải cause
- Bỏ config change → không có debug logs → không có disk fill → incident không xảy ra → config change là cause
Cross-Layer Correlation Workflow
Khi nhận được incident alert, systematic workflow:
1. Alert data → xác định: WHAT đang xảy ra và từ khi nào
(GKE dashboard, Cloud Monitoring metrics)
2. Kubernetes events → xác định: CÓ event nào trong Kubernetes layer không?
(Pod eviction, node pressure, scaling events)
3. Cloud Logging → xác định: APPLICATION logs nói gì?
(error messages, stack traces, application-level events)
4. Cloud Trace → xác định: REQUEST PATH nào bị ảnh hưởng?
(latency breakdown, which service is slow)
5. Correlate theo timeline → xây dựng causal chain:
Trigger event → propagation → observable symptom → alert
6. Validate: Giả thuyết causal chain có explain toàn bộ symptoms không?
(Nếu không → có thể có multiple concurrent issues hoặc missed event)GKE Dashboard: Signals Quan Trọng Nhất
Nếu phải chọn 5 signals để luôn monitor trong production GKE:
Signal 1: Pod Availability Ratio
(desired replicas - unavailable replicas) / desired replicasXuống dưới 100% là signal đầu tiên cần investigate.
Signal 2: CPU Throttling Rate Throttling trên 30% sustained → application bị slow, cần tăng CPU limit hoặc optimize.
Signal 3: Memory Usage vs Limit Usage/Limit > 80% → OOM risk trong thời gian gần.
Signal 4: Node Count và Condition Node count giảm hoặc node với condition True (pressure) → infrastructure instability.
Signal 5: API Server Request Latency (P99) Latency > 1 giây cho list/watch operations → control plane stress, sẽ ảnh hưởng tất cả operations.
Anti-Pattern: Assume Đầu Tiên Thấy = Root Cause
Tại sao đây là sai lầm phổ biến:
Alert thường fire trên symptom, không phải cause. Alert "Pod restart rate high" fire khi pod đã restart nhiều lần — nhưng root cause có thể là memory leak bắt đầu từ 2 giờ trước, node OOM bắt đầu evict từ 1 giờ trước, và restart rate cao là hệ quả cuối cùng.
Nếu bạn fix "tăng memory limit" mà không trace back causal chain:
- Memory leak tiếp tục → memory lại đầy → OOM lại
- Bạn tiếp tục tăng limit → tăng chi phí → vẫn không fix được root cause
Quy tắc: Luôn hỏi "điều này xảy ra trước điều tôi vừa tìm thấy là gì?" — cho đến khi bạn không thể tìm thấy gì xảy ra trước nữa. Đó mới là trigger event.