Lab 9.1 - Xây dựng hệ thống Centralized Logging với Fluent Bit, Loki và Grafana
Phần 1 - Tổng quan về Logging trong Kubernetes
Sau khi hoàn thành Lab 8, chúng ta đã xây dựng được một hệ thống Monitoring và Alerting hoàn chỉnh.
Khi hệ thống gặp sự cố, Prometheus sẽ thu thập Metrics, Alert Rule sẽ phát hiện bất thường và Alertmanager sẽ gửi cảnh báo đến DevOps.
Ví dụ:
Alert
HighHTTP5xxRate
Severity: Critical
Lúc này, DevOps đã biết rằng hệ thống đang có vấn đề.
Nhưng một câu hỏi quan trọng vẫn chưa có lời giải:
Điều gì đã gây ra sự cố?
Để trả lời câu hỏi đó, chúng ta cần đến Logs.
Mục tiêu của phần này
Sau phần này, bạn sẽ hiểu:
- Logs là gì?
- Vì sao Kubernetes cần Centralized Logging?
- Kiến trúc Logging trong Kubernetes.
- Vai trò của Fluent Bit, Loki và Grafana.
- Quy trình điều tra sự cố trong môi trường Production.
Monitoring chỉ cho biết "Có vấn đề"
Hãy quay lại tình huống thực tế của hệ thống Todo.
Một buổi sáng, Product Owner gửi tin nhắn:
"Người dùng phản ánh API tạo Todo rất chậm."
DevOps mở Grafana.
Dashboard hiển thị:
CPU: 35%
Memory: 52%
Pod Restart: 0
Request Latency: 5.2s
HTTP 500: Tăng mạnh
Nhìn vào Dashboard, chúng ta biết:
- Ứng dụng đang phản hồi chậm.
- Số lượng lỗi HTTP 500 đang tăng.
- Người dùng thực sự đang bị ảnh hưởng.
Tuy nhiên Dashboard không thể cho biết:
- Exception nào đã xảy ra?
- Database có bị timeout không?
- API nào gây lỗi?
- Stack Trace là gì?
- Có lỗi NullPointerException hay không?
Nói cách khác:
Metrics chỉ cho biết điều gì đang xảy ra, nhưng không cho biết tại sao điều đó xảy ra.
Dùng kubectl logs có đủ không?
Khi mới làm quen với Kubernetes, hầu hết chúng ta đều sử dụng:
kubectl logs <pod-name>
Ví dụ:
kubectl logs todo-backend-7f9f8d9c6d-abc12 -n todo-app
Kết quả:
2026-08-05 09:15:01 INFO Application started
2026-08-05 09:15:08 INFO GET /api/todos
2026-08-05 09:15:10 ERROR Database connection timeout
Cách này hoạt động rất tốt khi hệ thống còn nhỏ.
Ví dụ:
Frontend
Backend
PostgreSQL
Chỉ có vài Pod nên việc kiểm tra log khá đơn giản.
Vấn đề trong môi trường Production
Hãy tưởng tượng hệ thống phát triển sau vài tháng.
20 Microservices
↓
120 Pods
↓
10 Kubernetes Nodes
Một Alert xuất hiện:
HTTP 500 tăng cao
Lúc này DevOps sẽ phải:
kubectl logs pod-1
kubectl logs pod-2
kubectl logs pod-3
...
kubectl logs pod-120
Không ai muốn làm điều đó.
Khó khăn còn lớn hơn khi:
- Pod liên tục được tạo mới.
- Pod cũ đã bị xóa.
- Ứng dụng chạy trên nhiều Node khác nhau.
- Một request đi qua nhiều Microservice.
Việc tìm log thủ công gần như không còn khả thi.
Centralized Logging là gì?
Để giải quyết vấn đề này, chúng ta cần tập trung toàn bộ log của hệ thống về một nơi duy nhất.
Đó chính là Centralized Logging.
Thay vì đăng nhập vào từng máy chủ hoặc từng Pod để xem log, DevOps chỉ cần mở một giao diện duy nhất và tìm kiếm log của toàn bộ hệ thống.
Mô hình này có thể hình dung như sau:
Pod A
│
Pod B
│
Pod C
│
Pod D
│
▼
Centralized Logging
│
▼
Grafana
Dù hệ thống có 10 Pod hay 10.000 Pod, cách tìm log vẫn hoàn toàn giống nhau.
Logging trong Kubernetes hoạt động như thế nào?
Một điểm rất khác giữa Kubernetes và các hệ thống truyền thống là:
Container không nên ghi log ra file.
Thay vào đó, ứng dụng nên ghi log trực tiếp ra:
- stdout
- stderr
Ví dụ với Spring Boot:
log.info("Create Todo successfully");
log.error("Database connection timeout");
Khi ứng dụng chạy trong Container, các log này sẽ xuất hiện trên Console:
INFO Create Todo successfully
ERROR Database connection timeout
Container Runtime (Docker hoặc containerd) sẽ tự động lưu các log này trên Node.
Luồng hoạt động:
Spring Boot
│
stdout / stderr
│
Container Runtime
│
/var/log/containers
│
Log Collector
Chính vì vậy, trong Kubernetes chúng ta không cần tự tạo file log như:
application.log
server.log
error.log
Việc ghi log ra Console là đủ.
Vì sao không nên ghi log vào file trong Container?
Đây là một sai lầm khá phổ biến khi mới làm việc với Docker và Kubernetes.
Ví dụ:
/app/logs/application.log
Thoạt nhìn có vẻ hợp lý.
Tuy nhiên khi Pod bị xóa:
kubectl delete pod todo-backend
Container cũng bị xóa theo.
Toàn bộ file log sẽ biến mất.
Trong khi đó, nếu ghi log ra stdout, Log Collector sẽ gửi log tới hệ thống lưu trữ ngay sau khi log được sinh ra.
Nhờ đó log vẫn được lưu giữ ngay cả khi Pod không còn tồn tại.
Kiến trúc Logging trong Lab này
Trong Lab 9, chúng ta sẽ xây dựng hệ thống Logging theo kiến trúc sau:
Spring Boot
│
stdout / stderr
│
Kubernetes Node
│
Fluent Bit
│
Loki
│
Grafana
│
Search & Analysis
Mỗi thành phần đều có một vai trò riêng.
Fluent Bit
Fluent Bit là Log Collector.
Nó chạy trên mỗi Kubernetes Node dưới dạng DaemonSet.
Nhiệm vụ của Fluent Bit:
- Theo dõi log của tất cả Container trên Node.
- Đọc log mới ngay khi được tạo.
- Thêm Metadata của Kubernetes.
- Gửi log tới Loki.
Ví dụ:
Log ban đầu:
ERROR Database connection timeout
Sau khi Fluent Bit xử lý:
{
"namespace": "todo-app",
"pod": "todo-backend-6f9b4d7f7d-abc12",
"container": "backend",
"level": "ERROR",
"message": "Database connection timeout"
}
Nhờ có Metadata này, chúng ta có thể tìm kiếm log theo:
- Namespace.
- Pod.
- Container.
- Node.
- Label của ứng dụng.
Loki
Loki là hệ thống lưu trữ và tìm kiếm log do Grafana Labs phát triển.
Khác với các hệ thống truyền thống như Elasticsearch, Loki không đánh chỉ mục toàn bộ nội dung log.
Thay vào đó, Loki chỉ đánh chỉ mục các Label như:
namespace="todo-app"
app="todo-backend"
container="backend"
Điều này giúp Loki:
- Sử dụng ít tài nguyên hơn.
- Tiết kiệm dung lượng lưu trữ.
- Tối ưu cho môi trường Kubernetes.
Grafana
Grafana không chỉ hiển thị Dashboard Metrics.
Sau khi kết nối với Loki, Grafana còn cho phép:
- Tìm kiếm log.
- Lọc log theo Namespace, Pod hoặc Container.
- Phân tích log theo thời gian.
- Liên kết trực tiếp giữa Metrics và Logs.
Ví dụ:
Dashboard cho thấy Request Latency tăng.
Chỉ với một cú nhấp chuột, DevOps có thể chuyển sang xem log của Pod tương ứng và tìm ra nguyên nhân.
Từ Metrics đến Root Cause
Đây chính là quy trình điều tra sự cố trong thực tế.
Người dùng báo lỗi
│
▼
Alertmanager gửi cảnh báo
│
▼
Grafana Dashboard
│
▼
Request Latency tăng
│
▼
Mở Logs trên Grafana
│
▼
ERROR Database connection timeout
│
▼
Xác định nguyên nhân gốc
│
▼
Khắc phục sự cố
Thay vì mất hàng chục phút để SSH vào từng máy chủ và kiểm tra log thủ công, DevOps chỉ cần vài phút để xác định nguyên nhân.
Những gì chúng ta sẽ xây dựng trong Lab 9
Trong các phần tiếp theo của Lab, chúng ta sẽ lần lượt:
- Triển khai Loki bằng Helm.
- Triển khai Fluent Bit dưới dạng DaemonSet.
- Thu thập log từ tất cả Pod trong Kubernetes.
- Kết nối Loki với Grafana.
- Sử dụng LogQL để tìm kiếm log.
- Điều tra một sự cố thực tế của ứng dụng Todo.
- Kết hợp Metrics + Alerts + Logs để hoàn thiện hệ thống Observability.
Sau khi hoàn thành Lab 9, bạn sẽ có một nền tảng Logging tương tự như cách nhiều hệ thống Kubernetes Production đang vận hành, nơi mọi log của ứng dụng đều được thu thập, lưu trữ và tra cứu tập trung từ một giao diện duy nhất.
All Rights Reserved