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 describevàkubectl logs --previoustrướ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 descriptiontype:NormalhoặcWarningfirstTimestamp/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ăngcount
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? (
Failedvớ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 Type | Resource Type | Nguồn | Latency điển hình |
|---|---|---|---|
| Container logs (stdout/stderr) | k8s_container | Kubelet → logging agent (Fluentbit) → Cloud Logging | 5-30 giây |
| Kubelet system logs | k8s_node | systemd journal → logging agent | 10-60 giây |
| Audit logs | cloudaudit.googleapis.com | API server → Cloud Audit Logs | 1-5 phút |
| GKE cluster events | k8s_cluster | Controller → API server → Logging | 5-30 giây |
| Control plane component logs | k8s_control_plane_component | GKE managed, bạn cần bật | 1-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ặctraceparent(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ấtDepth-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ướcSignal Selection Matrix
| Tình huống | Signal đầu tiên | Signal thứ hai |
|---|---|---|
| Pod không start | Kubernetes Events | kubelet logs (Cloud Logging) |
| Pod crash liên tục | kubectl logs --previous | Cloud Monitoring (memory trend) |
| Service unreachable | DNS test từ trong pod | Network policy audit |
| Node NotReady | Node conditions (kubectl describe node) | Kubelet logs, node-problem-detector |
| High latency (no error) | Cloud Trace (latency breakdown) | Application logs với timing |
| Memory leak | Cloud Monitoring (memory trend) | Application heap dumps |
| Intermittent failures | Cloud 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:
# 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/nullSau 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.
# 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.