Chọn ELK, Loki hay log của cloud

4 câu hỏi phỏng vấn~25 phútTừ khóa: full-text index, label index, Loki, LogQL, Elastic Cloud, Amazon OpenSearch Service, CloudWatch Logs, Azure Monitor Log Analytics, Grafana Cloud, ingest cost, retention, ops burden, dual write, migration, vendor lock-in

Bài cuối phần log: chọn công cụ. Công ty mình có ba nhóm: team shop-app 4 người mới khởi nghiệp, một khách hàng doanh nghiệp đòi on-prem và tìm full-text log audit, và một nhánh chạy toàn bộ trên Kubernetes. Mỗi nhóm nên chọn cái gì?

Không có đáp án chung; mỗi lựa chọn đổi một thứ lấy một thứ. Bài 17.11 đã bàn câu "đang dùng Loki có nên chuyển ELK" trong K8s; ở đây mình làm khung quyết định rộng hơn, cho cả VM và cloud.

1. Bài toán

A. shop-app startup: 4 dev, 3 VM trên AWS, ~20GB log/ngày, không có người chuyên ops
B. Khách doanh nghiệp: on-prem, không ra Internet, log audit 1 năm, tìm full-text, phân quyền chặt
C. Nhánh K8s: 40 service, ~300GB log/ngày, đã có Prometheus + Grafana + Tempo

2. Vấn đề

3. Giải pháp: so sánh

ELK / OpenSearchLokiLog của cloud (CloudWatch, Azure Log Analytics)
IndexIndex mọi field (inverted index)Chỉ index label; nội dung nén thành chunkDo dịch vụ quản lý
QueryFull-text, aggregation mạnh, KQL/DSL/ES|QLLogQL: chọn stream theo label rồi grep/parseLogs Insights / KQL (Azure) khá mạnh
Tìm "kim trong đống rơm" khắp mọi logRất nhanhChậm nếu label rộngTrung bình
Chi phí lưuCao (index lớn, SSD)Thấp (object storage)Trả theo GB ingest + GB lưu; ingest thường đắt
Công vận hànhCao nếu tự chạyTrung bìnhGần như không
ScaleTốt nhưng cần sizing shardTốt, tách read/writeTự động
On-premCóCóKhông
Hợp vớiFull-text, security/SIEM, audit, phân tíchHệ đã dùng Grafana, log lớn, tìm theo service/timeTeam nhỏ, đã ở một cloud

Managed:

Dịch vụLà gìLưu ý
Elastic CloudElasticsearch + Kibana do Elastic chạy trên AWS/GCP/Azure; có bản serverlessĐủ tính năng nhất; trả theo tài nguyên
Amazon OpenSearch ServiceOpenSearch managed, có Serverless và OpenSearch IngestionIAM, VPC; vẫn phải chọn instance và shard (bản không serverless)
CloudWatch LogsLog có sẵn của AWSIngest ~0.5 USD/GB (tùy vùng), có lớp Infrequent Access
Azure Monitor Log AnalyticsLog + KQL của AzureCó gói Basic/Auxiliary logs rẻ hơn cho log ít truy vấn
Grafana Cloud LogsLoki managedHợp nếu đã dùng Grafana Cloud cho metric/trace

4. Code từng bước: giữ app trung lập với backend

Mấu chốt để đổi được về sau: app chỉ ghi JSON ra stdout/file, mọi việc gửi đi do shipper lo.

Bước 1: app (giống 19.7, không thêm appender gửi thẳng ES)

logging:
  structured:
    format:
      console: ecs

Bước 2: shipper gửi hai nơi khi chuyển đổi (Fluent Bit trên VM)

[INPUT]
    Name   tail
    Path   /var/log/shop/*.json
    Parser json
    Tag    shop.*
[OUTPUT]
    Name   opensearch
    Match  shop.*
    Host   ${OS_HOST}
    Port   443
    tls    On
    AWS_Auth On
    AWS_Region ap-southeast-1
    Index  logs-shop-prod
    Suppress_Type_Name On
[OUTPUT]
    Name   loki
    Match  shop.*
    Host   ${LOKI_HOST}
    labels service=$service['name'], env=$service['environment']
    tls    On
    http_user   ${LOKI_USER}
    http_passwd ${LOKI_TOKEN}

Bước 3: so cùng một câu hỏi trên hai bên

# ES/OpenSearch (KQL):  service.name:payment-service and log.level:error and message:"timeout"
# Loki (LogQL):         {service="payment-service"} | json | log_level="ERROR" |= "timeout"
# CloudWatch Insights:  fields @timestamp, message | filter `service.name`="payment-service" and `log.level`="ERROR" and message like /timeout/

Bước 4: đo trước khi quyết

curl -s -H "Authorization: ApiKey $ES_API_KEY" "$ES_URL/_cat/indices/logs-shop-*?v&h=index,docs.count,pri.store.size&s=index"
# so: GB/ngày thực lưu, thời gian query 5 câu hay dùng nhất, giờ công vận hành/tháng

5. Cách hoạt động: cây quyết định

Bắt buộc on-prem / không ra Internet?
 ├─ có ─► cần full-text, audit, SIEM? ─ có ─► ELK hoặc OpenSearch tự chạy (B)
 │                                     └ không ─► Loki tự chạy (rẻ, nhẹ hơn)
 └─ không ─► có người chuyên vận hành search cluster?
             ├─ không ─► team nhỏ, log < ~50GB/ngày? ─ có ─► log của cloud (A: CloudWatch)
             │                                       └ không ─► managed: Grafana Cloud / Elastic Cloud
             └─ có ─► đã dùng Grafana + Prometheus + Tempo, tìm theo service/time là chính?
                      ├─ có ─► Loki (C), thêm ELK riêng cho audit nếu cần
                      └─ không ─► Elastic Cloud / Amazon OpenSearch Service

6. So sánh: ba nhóm của bạn

NhómChọnLý doĐánh đổi
A. StartupCloudWatch Logs (hoặc Grafana Cloud free tier)Không ai phải vận hành; agent CloudWatch có sẵnIngest đắt khi lớn; đặt retention, drop DEBUG ngay
B. Doanh nghiệp on-premOpenSearch (hoặc ES có subscription) 3+ nodeFull-text, DLS/FLS, audit, không cần InternetCần người vận hành (19.11)
C. K8s 300GB/ngàyLoki trên object storageRẻ, cùng Grafana với metric/traceTìm full-text toàn bộ chậm; label phải thiết kế kỹ (17.10)

7. Khi nào nên dùng / không nên dùng

Hóa đơn CloudWatch Logs tháng này của team startup nhảy lên gấp ba. Mình nghi ingest chứ không phải lưu trữ. Kiểm tra và giảm kiểu gì?

Bạn nghi đúng hướng: với CloudWatch, phần ingest thường chiếm phần lớn hóa đơn.

Thêm alarm trên IncomingBytes để lần sau biết trong ngày, không đợi cuối tháng.

Vậy mình dùng Loki cho log app hằng ngày, còn đẩy log audit sang OpenSearch có ổn không, hay là phức tạp quá?

Ổn, và khá phổ biến, miễn là bạn giữ kỷ luật:

Nếu log audit rất ít và chỉ cần khi kiểm toán, có khi S3 + Object Lock + Athena là đủ, không cần cả OpenSearch.

Phỏng vấn hỏi chọn giải pháp log tập trung thì trả lời sao?

Q1. ELK và Loki khác nhau căn bản ở đâu?

🇻🇳 Tiếng Việt:

ELK index toàn bộ nội dung nên tìm full-text và aggregation rất mạnh, nhưng lưu trữ và vận hành đắt. Loki chỉ index label như service và môi trường, nội dung nén trên object storage, nên rẻ và đơn giản, nhưng tìm chuỗi trên khoảng rộng thì chậm. Tôi chọn ELK khi cần full-text, audit hay security; chọn Loki khi đã dùng Grafana và chủ yếu tìm theo service và thời gian.

🇬🇧 English:

ELK indexes the full content, so full-text search and aggregations are powerful, but storage and operations are expensive. Loki indexes only labels like service and environment and stores compressed content on object storage, so it is cheap and simple, but searching strings across a wide range is slower. I pick ELK for full-text, audit or security needs, and Loki when we are already on Grafana and mostly search by service and time.

Q2. Khi nào nên dùng log managed của cloud?

🇻🇳 Tiếng Việt:

Khi team nhỏ, không có người chuyên vận hành cluster, đã ở một cloud và lượng log vừa phải. Đổi lại phải kiểm soát chi phí ingest bằng mức log, filter và retention, và chấp nhận query yếu hơn hoặc lock-in. Tôi giữ app chỉ ghi JSON ra stdout để có thể đổi backend sau này.

🇬🇧 English:

When the team is small, has nobody dedicated to running a cluster, is already on one cloud, and log volume is moderate. The trade-off is controlling ingest cost through log levels, filters and retention, and accepting weaker queries or lock-in. I keep applications writing JSON to stdout so we can change the backend later.

Q3. Bạn chuyển từ hệ log này sang hệ khác thế nào?

🇻🇳 Tiếng Việt:

Cho shipper ghi song song cả hai nơi vài tuần, dựng lại dashboard và alert trên hệ mới, so kết quả các query quan trọng, rồi tắt hệ cũ. Log lịch sử thường để hết retention hoặc giữ snapshot thay vì migrate. Việc này dễ nếu app chưa từng gắn chặt với backend.

🇬🇧 English:

I have the shipper dual-write to both systems for a few weeks, rebuild dashboards and alerts on the new one, compare results for key queries, then switch off the old one. Historical logs usually age out or stay in snapshots rather than being migrated. This is easy as long as the application was never coupled to the backend.

Cách nhớ ngắn gọn

Tổng kết chương 19: Observability

BàiÝ chínhTình huống trên shop-appCông cụ
19.1 Log, metric, trace4 tín hiệu; JSON log; traceId nối; cardinality và chi phíCheckout chậm, log 12 Pod trộn lẫnStructured logging, MDC
19.2 SLI, SLO, alertĐo trải nghiệm user, error budget, burn rate40 alert CPU/tuần, bỏ sót lỗi paymentRecording rule, Alertmanager
19.3 Prometheus & GrafanaPull model, PromQL, histogram_quantilePrometheus OOM vì label IDPrometheus, Grafana
19.4 OpenTelemetrySDK/agent, Collector, sampling, W3C traceparentChuyển Zipkin → TempoOTel, Tempo
19.5 Profiling JVMContinuous profiling, flame graphBản 3.2 tốn CPUPyroscope, JFR
19.6 Incident & postmortemVai trò, mitigate trước, blamelessPayment 502 sau deployRunbook, rollback
19.7 ELK tổng quanThành phần Elastic Stack; ES vs OpenSearchSSH grep log trên 3 VMES, Kibana, Filebeat, docker-compose
19.8 Elasticsearch bên trongShard, replica, node role, health, data streamCluster yellow_cat, allocation explain, template
19.9 Đưa log vàoChọn shipper, Logstash, ingest pipeline, Kafka, multilineNginx text, app cũ, ES bảo trìFilebeat, Logstash, Kafka
19.10 Kibana & dashboardKQL, saved search, dashboard, alert, quyềnTìm đơn ORD-1042 qua 3 serviceDiscover, Lens, Alerting
19.11 Vận hành ELKILM/ISM, sizing, heap, watermark, snapshot, bảo mật, chi phíĐĩa 95%, index read-onlyILM, SLM, S3, API key
19.12 Chọn công cụ logELK vs Loki vs cloud, managed, chuyển đổiStartup, on-prem, K8sElastic Cloud, OpenSearch Service, CloudWatch, Loki

Tự kiểm tra

Vì sao Loki rẻ hơn ELK?

Chỉ index label, nội dung nén trên object storage.

Retention mặc định của CloudWatch log group?

Giữ mãi mãi; phải tự đặt.

Khách đòi on-prem + full-text audit: chọn gì?

ELK hoặc OpenSearch tự vận hành.

Làm sao để sau này đổi backend log dễ?

App chỉ ghi JSON ra stdout/file, shipper lo việc gửi; dùng chung schema ECS.

Có nên migrate log cũ khi chuyển hệ?

Thường không; để hết retention hoặc giữ snapshot.