Skip to content

Phương Pháp Debugging Khoa Học & Mô Hình Telemetry GKE

Tại sao Trial-and-Error Fail ở Production

Khi hệ thống production bị sự cố, phản xạ tự nhiên là bắt đầu chạy lệnh ngay lập tức: kubectl get pods, kubectl logs, kubectl describe, rồi thử kubectl delete pod, rồi kubectl rollout restart. Đây là trial-and-error debugging — tiếp cận theo kiểu "thử rồi xem".

Vấn đề với trial-and-error ở production:

Thứ nhất, mỗi action có chi phí. Trong distributed system, state không phải stateless. Một kubectl delete pod có thể xóa evidence (logs trong container, state trong memory). Một kubectl rollout restart có thể che giấu root cause thật sự nếu restart giải quyết triệu chứng nhưng không giải quyết nguyên nhân.

Thứ hai, distributed system có exponential failure combinations. Với 10 microservices, mỗi service có 3 failure modes, số kết hợp tiềm năng là 3^10 = 59049. Random trial sẽ không tìm ra đúng nguyên nhân trong thời gian hợp lý.

Thứ ba, correlation không phải causation. "CPU spike lúc 14:23, rồi service down lúc 14:24" không có nghĩa là CPU spike gây ra service down. Có thể cả hai cùng là triệu chứng của một nguyên nhân thứ ba.

Giải pháp là hypothesis-driven debugging — áp dụng phương pháp khoa học vào production incident.


Hypothesis-Driven Debugging: Cơ Chế

Phương pháp gồm 3 bước lặp lại: Hypothesis → Test → Validate.

Bước 1: Formulate Hypothesis

Trước khi chạy bất kỳ command nào, đặt câu hỏi có cấu trúc:

Tôi nghĩ vấn đề là [X] vì [Y evidence đã quan sát].
Nếu [X] đúng, thì [Z] phải đúng.
Tôi sẽ test [Z] bằng cách [kiểm tra cụ thể].

Ví dụ:

Tôi nghĩ vấn đề là Pod bị OOM kill (X)
vì logs không có error message nhưng Pod restart count tăng (Y).
Nếu OOM kill đúng, thì exit code phải là 137 và kernel logs phải có OOM message (Z).
Tôi sẽ check: kubectl describe pod → Last State → Exit Code + 
gcloud logging read "resource.type=k8s_node ... oom" (cách test).

Điều quan trọng: hypothesis phải falsifiable — phải có cách để disprove nó.

Bước 2: Gather Evidence to Test

Chọn signal source phù hợp nhất với hypothesis (sẽ nói chi tiết bên dưới). Thu thập evidence theo cách không phá hủy state:

  • kubectl describekubectl logs --previous trước khi delete/restart
  • Snapshot metrics timestamp trước khi state thay đổi
  • Export events trước khi chúng expire (Kubernetes events có TTL 1 giờ mặc định)

Bước 3: Validate hoặc Reject

Sau khi test:

  • Evidence xác nhận hypothesis → có thể proceed với fix, nhưng vẫn cần hỏi "đây là proximate cause hay root cause?"
  • Evidence bác bỏ hypothesis → loại trừ X khỏi danh sách, formulate hypothesis mới
  • Evidence ambiguous → cần thêm test với signal source khác

Quan trọng: Mỗi vòng lặp thu hẹp không gian giả thuyết. Sau 3-4 vòng, bạn thường đã eliminate đủ possibilities để biết chắc root cause.


Internal Model của Từng Telemetry Source

GKE cung cấp 4 loại telemetry chính, mỗi loại có cơ chế hoạt động khác nhau, latency khác nhau, và trả lời câu hỏi khác nhau. Biết cơ chế bên trong giúp bạn chọn đúng tool thay vì mò mẫm.

1. Kubernetes Events

Events là gì: Kubernetes Event là Kubernetes object (lưu trong etcd), không phải log. Mỗi event ghi lại một điều quan trọng xảy ra với một object khác — Pod, Node, Service, etc.

Cơ chế tạo event: Các component của Kubernetes (kubelet, scheduler, controller manager) ghi event thông qua EventRecorder interface. EventRecorder gọi API server để tạo Event object. Event object chứa:

  • involvedObject: Object bị ảnh hưởng (Pod, Node, etc.)
  • reason: String ngắn, machine-readable (ví dụ: Failed, Pulling, BackOff)
  • message: Human-readable description
  • type: Normal hoặc Warning
  • firstTimestamp / lastTimestamp / count: Event có thể được aggregated — nếu cùng event xảy ra nhiều lần, Kubernetes không tạo nhiều object mà tăng count

TTL của Events: Mặc định, Kubernetes Events chỉ được lưu 1 giờ (configurable qua --event-ttl của API server). Sau đó bị garbage collected. Điều này có hệ quả quan trọng: nếu incident xảy ra 2 giờ trước, events đã biến mất.

Trong GKE: Events được export sang Cloud Logging tự động. Truy vấn:

resource.type="k8s_cluster"
logName="projects/PROJECT_ID/logs/events"

Câu hỏi Events trả lời tốt:

  • Pod bị schedule fail vì lý do gì? (FailedScheduling)
  • Image pull fail vì sao? (Failed với message về registry)
  • Liveness probe fail khi nào? (Unhealthy)
  • Node bị evict vì điều kiện gì? (Evicted)

Câu hỏi Events KHÔNG trả lời tốt: Performance trends, memory usage over time, request latency.


2. Cloud Logging — Internal Pipeline

Log types trong GKE: GKE tự động collect nhiều loại log, mỗi loại qua pipeline khác nhau:

Log TypeResource TypeNguồnLatency điển hình
Container logs (stdout/stderr)k8s_containerKubelet → logging agent (Fluentbit) → Cloud Logging5-30 giây
Kubelet system logsk8s_nodesystemd journal → logging agent10-60 giây
Audit logscloudaudit.googleapis.comAPI server → Cloud Audit Logs1-5 phút
GKE cluster eventsk8s_clusterController → API server → Logging5-30 giây
Control plane component logsk8s_control_plane_componentGKE managed, bạn cần bật1-5 phút

Latency có ý nghĩa gì cho debugging: Khi bạn tìm log của một crash xảy ra lúc 14:23:45, log có thể chưa xuất hiện trong Cloud Logging cho đến 14:23:50 đến 14:24:15. Khi correlation across signals, luôn trừ ra latency window này.

Log Router và exclusions: Mọi log đi qua Cloud Logging Log Router trước khi được lưu. Nếu team đã cấu hình exclusion filters (để giảm cost), một số logs có thể không xuất hiện. Trong debugging, luôn kiểm tra Log Router exclusions trước khi kết luận "log không tồn tại".

Câu hỏi Logging trả lời tốt:

  • Application error message là gì? (stack trace, error string)
  • Kubelet log ghi gì khi node bị pressure?
  • API server audit log cho thấy ai/gì thay đổi resource?
  • Sequence of events theo thứ tự thời gian chính xác (với timestamp nanosecond)?

3. Cloud Monitoring — Metrics Pipeline

Metrics pipeline trong GKE: Cloud Monitoring thu thập metrics từ nhiều nguồn theo cơ chế khác nhau:

GKE system metrics (resource type k8s_container, k8s_node, k8s_pod): Kubelet expose metrics endpoint (metrics API, cAdvisor endpoint). GKE managed agent (metric-agent) scrape và push sang Monitoring. Granularity mặc định: 60 giây.

kube-state-metrics: Deployment riêng trong cluster, watch Kubernetes API objects và expose metric về object state (ví dụ: kube_pod_status_phase{phase="Pending"}, kube_node_status_condition). Đây là metrics về state của Kubernetes objects, không phải resource consumption.

Managed Prometheus (GMP): Nếu enabled, có thể scrape bất kỳ endpoint Prometheus nào trong cluster. Granularity có thể xuống đến 15 giây.

Resolution vs Freshness:

  • 60-giây resolution có nghĩa là spike ngắn (< 60s) có thể không xuất hiện trong chart
  • Khi debugging "sự kiện xảy ra lúc 14:23:45", metric chart chỉ có điểm tại 14:23:00 và 14:24:00
  • Để hiểu chi tiết trong khoảng thời gian đó, cần correlate với logs

Câu hỏi Monitoring trả lời tốt:

  • Memory usage có xu hướng tăng dần trước incident không? (trend)
  • CPU throttling bắt đầu khi nào, kéo dài bao lâu?
  • Request count giảm bao nhiêu phần trăm và từ thời điểm nào?
  • Node có bao nhiêu Pods đang chạy? (kube-state-metrics)

Câu hỏi Monitoring KHÔNG trả lời tốt: Error messages cụ thể, request path, causal chain.


4. Cloud Trace — Distributed Tracing Model

Trace propagation mechanism: Distributed tracing hoạt động bằng cách inject trace context vào mọi network request. Context này (trace ID + span ID) được forward qua tất cả downstream calls. Kết quả là một "trace" gồm nhiều "span" từ nhiều service, tạo thành cây biểu diễn request lifecycle toàn bộ.

Trong GKE, trace context thường được propagate qua:

  • HTTP header: X-Cloud-Trace-Context (Google format) hoặc traceparent (W3C format)
  • gRPC metadata
  • Cloud Tasks / Pub/Sub message attributes

Sampling: Không phải mọi request đều được trace (chi phí cao). Mặc định Cloud Trace sample một tỷ lệ nhất định. Điều này có nghĩa là incident ảnh hưởng 100 request/giây có thể chỉ có 10-50 traces mỗi giây để phân tích.

Tích hợp với Cloud Logging: Cloud Trace inject logging.googleapis.com/trace field vào structured logs nếu được cấu hình đúng. Điều này cho phép bạn click vào một trace span và thấy logs tương ứng từ cùng request đó.

Câu hỏi Trace trả lời tốt:

  • Request bị chậm ở service nào trong chuỗi call?
  • Latency breakdown theo từng hop (frontend → backend → database)?
  • Call nào bị timeout và từ service nào?

Câu hỏi Trace KHÔNG trả lời tốt: Infrastructure-level issues (node OOM, disk pressure), events không phải trong request path.


Signal Hierarchy và Chiến Lược Chọn Signal

Breadth-First vs Depth-First

Breadth-first: Bắt đầu với signals có coverage rộng nhất để xác định "vấn đề ở domain nào?" trước.

1. kubectl get pods --all-namespaces → Phát hiện pods nào có vấn đề
2. GKE Observability Dashboard → Cluster health tổng quát
3. Events → Clues về lý do gần nhất

Depth-first: Khi đã biết domain (ví dụ: "Pod X đang CrashLoopBackOff"), đi sâu vào domain đó:

1. kubectl describe pod X → Events cụ thể
2. kubectl logs X --previous → Logs của lần crash trước
3. Cloud Logging: kubelet logs trên node đó tại thời điểm crash
4. Cloud Monitoring: memory usage của Pod X trong 1 giờ trước

Signal Selection Matrix

Tình huốngSignal đầu tiênSignal thứ hai
Pod không startKubernetes Eventskubelet logs (Cloud Logging)
Pod crash liên tụckubectl logs --previousCloud Monitoring (memory trend)
Service unreachableDNS test từ trong podNetwork policy audit
Node NotReadyNode conditions (kubectl describe node)Kubelet logs, node-problem-detector
High latency (no error)Cloud Trace (latency breakdown)Application logs với timing
Memory leakCloud Monitoring (memory trend)Application heap dumps
Intermittent failuresCloud Logging (error patterns)Cloud Monitoring (error rate)

Framework Thu Thập Thông Tin Trước Khi Hành Động

Trước khi chạy bất kỳ mutating command nào (delete, restart, scale), thu thập bộ thông tin cơ bản sau. Đây là "evidence snapshot" để đảm bảo không mất thông tin sau khi state thay đổi:

bash
# 1. Pod overview
kubectl get pods -n NAMESPACE -o wide

# 2. Pod details (events, resource usage, probe config)
kubectl describe pod POD_NAME -n NAMESPACE > /tmp/pod-describe.txt

# 3. Current logs
kubectl logs POD_NAME -n NAMESPACE --tail=200 > /tmp/pod-logs-current.txt

# 4. Previous container logs (nếu đã restart)
kubectl logs POD_NAME -n NAMESPACE --previous --tail=200 > /tmp/pod-logs-previous.txt 2>/dev/null

# 5. Node state
kubectl describe node NODE_NAME > /tmp/node-describe.txt

# 6. Recent events (trước khi expire)
kubectl get events -n NAMESPACE --sort-by='.lastTimestamp' > /tmp/events.txt

# 7. Resource quotas và limits
kubectl describe resourcequota -n NAMESPACE 2>/dev/null
kubectl top pods -n NAMESPACE 2>/dev/null

Sau khi có bộ này, bạn có thể phân tích cẩn thận và formulate hypothesis trước khi bất kỳ action nào.


Thời Gian và Ordering: Pitfall Phổ Biến

Clock Skew

Trong distributed system, đồng hồ giữa các node không hoàn toàn đồng bộ. Sai lệch thường là vài millisecond, nhưng có thể lên đến vài giây nếu NTP bị vấn đề. Khi correlate logs từ nhiều pods trên nhiều nodes, timestamp không thể tin tuyệt đối ở mức millisecond.

Log Lag

Như đã đề cập, Cloud Logging có latency 5-60 giây tùy loại. Khi build timeline, ghi chú latency của mỗi signal source. Một event trong Kubernetes xảy ra lúc T có thể xuất hiện trong Cloud Logging lúc T+30s.

GKE Event Aggregation

Kubernetes aggregate events giống nhau thành một object với count tăng dần. firstTimestamp cho biết lần đầu tiên, lastTimestamp cho biết lần gần nhất. Nếu bạn chỉ nhìn vào lastTimestamp, bạn có thể miss rằng pattern đã bắt đầu từ sớm hơn nhiều.

bash
# Xem cả firstTimestamp và lastTimestamp của events
kubectl get events -n NAMESPACE -o json | jq '.items[] | {reason: .reason, firstTime: .firstTimestamp, lastTime: .lastTimestamp, count: .count, message: .message}'

Constraints và Giới Hạn Thật

Cloud Logging retention: Mặc định 30 ngày cho _Default bucket. Sau 30 ngày, log bị xóa trừ khi có log bucket với retention dài hơn. Incidents xảy ra hơn 30 ngày trước không thể debug qua Logging.

Kubernetes Events TTL: 1 giờ mặc định (GKE thay đổi được nhưng thường giữ default). Events hữu ích nhất cho "trong 1 giờ qua có gì xảy ra với Pod/Node này".

Metrics resolution: 60 giây cho system metrics. Không thể debug event xảy ra trong 10 giây bằng Cloud Monitoring system metrics.

Trace sampling: Nếu sampling rate là 1%, một số incidents ảnh hưởng ít request có thể không có trace nào. Khi debugging latency spike ngắn, cần tăng sampling rate trước (nếu có thể dự đoán), hoặc chấp nhận chỉ có partial view.

Control plane logs: Trong GKE, control plane components (API server, scheduler, controller manager, etcd) chạy trên infrastructure do Google quản lý. Logs có thể được enable qua GKE Control Plane Logging, nhưng không phải mặc định và có cost. Nếu chưa bật, bạn không thể debug API server issues sau khi xảy ra.


References