Thanos giải quyết vấn đề gì mà Prometheus không làm được?
Mình từng chạy Prometheus cho 3 cụm Kubernetes riêng lẻ. Mỗi cụm có Grafana riêng, alert riêng. Khi khách hàng hỏi “metrics tháng trước của service X trên production là bao nhiêu?” — mình phải mở 3 tab, tìm từng cụm, copy-paste số liệu vào Excel. Mất 20 phút cho một câu hỏi đơn giản.
Prometheus mặc định chỉ giữ 15 ngày data và không có cách nào xem toàn bộ cluster trong một chỗ. Thanos sinh ra để xử lý đúng 2 cái đau đầu đó.
Quick Start: Thanos chạy được trong 10 phút
Cách nhanh nhất để thử là dùng Docker Compose với MinIO làm object storage giả lập S3. Không cần AWS, không cần account gì cả.
Bước 1: Tạo file cấu hình bucket
mkdir -p ~/thanos-demo && cd ~/thanos-demo
cat > bucket.yaml <<EOF
type: S3
config:
bucket: thanos
endpoint: minio:9000
access_key: minioadmin
secret_key: minioadmin
insecure: true
EOF
Bước 2: Docker Compose toàn bộ stack
# docker-compose.yml
version: '3.8'
services:
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data
prometheus:
image: prom/prometheus:latest
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.max-block-duration=2h'
- '--storage.tsdb.min-block-duration=2h'
- '--web.enable-lifecycle'
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
ports:
- "9090:9090"
thanos-sidecar:
image: thanosio/thanos:latest
command:
- sidecar
- --tsdb.path=/prometheus
- --prometheus.url=http://prometheus:9090
- --objstore.config-file=/bucket.yaml
- --http-address=0.0.0.0:10902
- --grpc-address=0.0.0.0:10901
volumes:
- prometheus_data:/prometheus
- ./bucket.yaml:/bucket.yaml
depends_on:
- prometheus
- minio
thanos-store:
image: thanosio/thanos:latest
command:
- store
- --objstore.config-file=/bucket.yaml
- --http-address=0.0.0.0:10902
- --grpc-address=0.0.0.0:10901
volumes:
- ./bucket.yaml:/bucket.yaml
depends_on:
- minio
thanos-query:
image: thanosio/thanos:latest
command:
- query
- --http-address=0.0.0.0:9091
- --endpoint=thanos-sidecar:10901
- --endpoint=thanos-store:10901
ports:
- "9091:9091"
depends_on:
- thanos-sidecar
- thanos-store
volumes:
minio_data:
prometheus_data:
Bước 3: Tạo prometheus.yml tối thiểu
# prometheus.yml
global:
scrape_interval: 15s
external_labels:
cluster: 'demo'
replica: '0'
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
Bước 4: Khởi động và tạo bucket MinIO
# Khởi động toàn bộ stack
docker compose up -d
# Tạo bucket 'thanos' trên MinIO (dùng mc client)
docker run --rm --network host \
minio/mc alias set local http://localhost:9000 minioadmin minioadmin
docker run --rm --network host \
minio/mc mb local/thanos
Xong. Mở http://localhost:9091 — đây là Thanos Query UI. PromQL gõ ở đây sẽ kéo data từ cả Prometheus đang chạy lẫn lịch sử đã lưu trên MinIO, trong suốt với người dùng.
Kiến trúc Thanos: Từng component làm gì?
Thanos không thay thế Prometheus — nó bổ sung bên trên. Mình hay giải thích cho đồng nghiệp theo cách này: Prometheus là kho nhỏ tại chỗ, Thanos là hệ thống kho trung tâm kết nối tất cả lại.
Sidecar — cầu nối Prometheus và Object Storage
Chạy cùng pod với Prometheus. Có 2 nhiệm vụ: expose gRPC endpoint để Thanos Query kéo data real-time, và upload block data 2 giờ một lần lên S3/MinIO.
Lưu ý quan trọng: Phải set --storage.tsdb.max-block-duration=2h trên Prometheus để Sidecar chỉ upload block đã đóng hoàn chỉnh — không đụng vào block đang ghi dở.
Store Gateway — cửa vào kho lưu trữ lịch sử
Query cần data cũ hơn 15 ngày? Nó hỏi Store Gateway. Component này kéo block từ S3, nạp index vào bộ nhớ, rồi trả kết quả về. Data thực tế không lưu local — chỉ cache index để tìm kiếm nhanh.
Query — điểm truy vấn duy nhất
Grafana và người dùng đều trỏ vào đây. Thanos Query biết tự quyết định: hỏi Sidecar cho data mới, hỏi Store Gateway cho data cũ. Nếu có nhiều replica Prometheus cùng scrape một target, nó tự deduplicate — không cần can thiệp thủ công.
Compactor — dọn dẹp và tiết kiệm chi phí
Chạy độc lập theo định kỳ. Nhiệm vụ: gom các block nhỏ thành block lớn, và downsampling data cũ. Block từ 1 năm trước không cần granularity 15 giây — downsampling xuống 1 giờ là đủ để xem trend.
Triển khai thực tế trên Kubernetes với nhiều cluster
Đây là phần mình dùng nhiều nhất trong thực tế. Mỗi cluster chạy Prometheus + Sidecar riêng, tất cả đẩy lên cùng một S3 bucket. Thanos Query đặt ở cluster trung tâm, kết nối tất cả Sidecar qua gRPC.
External labels — bắt buộc phải có
# Cluster Production
global:
external_labels:
cluster: 'production-sg'
region: 'ap-southeast-1'
---
# Cluster Staging
global:
external_labels:
cluster: 'staging-sg'
region: 'ap-southeast-1'
Thiếu external_labels là lỗi phổ biến nhất khi mới dùng Thanos. Data từ 2 cluster đổ vào cùng S3 bucket mà không có label phân biệt — Query không biết dedup thế nào, kết quả truy vấn bị nhân đôi, alert lên nhầm. Đừng bỏ qua bước này.
Kết nối nhiều cluster vào một Thanos Query
# Thanos Query kết nối Sidecar từ nhiều cluster
thanos query \
--http-address=0.0.0.0:9091 \
--endpoint=prod-sidecar.monitoring.svc:10901 \
--endpoint=staging-sidecar.monitoring.svc:10901 \
--endpoint=thanos-store.monitoring.svc:10901 \
--query.replica-label=replica
Trước khi có setup này, mình phải SSH vào từng server để kiểm tra. Giờ một Grafana dashboard với datasource trỏ vào Thanos Query, filter theo label cluster là thấy hết — production lẫn staging, trong cùng một biểu đồ.
Cấu hình lưu trữ dài hạn trên AWS S3 thực tế
# bucket-s3.yaml cho production
type: S3
config:
bucket: company-thanos-metrics
endpoint: s3.ap-southeast-1.amazonaws.com
region: ap-southeast-1
# Dùng IAM Role thay vì hardcode key nếu chạy trên EC2/EKS
access_key: ${AWS_ACCESS_KEY_ID}
secret_key: ${AWS_SECRET_ACCESS_KEY}
Thêm Compactor để giảm chi phí storage
thanos compact \
--data-dir=/tmp/thanos-compact \
--objstore.config-file=/bucket-s3.yaml \
--retention.resolution-raw=30d \
--retention.resolution-5m=90d \
--retention.resolution-1h=1y \
--wait
Config trên giữ data thô 30 ngày, downsampled 5 phút trong 90 ngày, downsampled 1 giờ trong 1 năm. Mình đo thực tế trên một hệ thống ~500k active series: chi phí S3 giảm khoảng 65% sau khi bật Compactor với downsampling — so với giữ nguyên 15-second resolution cho cả năm.
Tips thực tế từ kinh nghiệm vận hành
1. Monitor chính Thanos bằng Prometheus
Thanos expose /metrics ở port 10902. Thêm vào scrape config để biết khi nào Compactor bị stuck hay Store Gateway không sync được block mới — tốt hơn là ngồi đợi khách hàng báo.
scrape_configs:
- job_name: 'thanos-components'
static_configs:
- targets:
- 'thanos-query:10902'
- 'thanos-store:10902'
- 'thanos-sidecar:10902'
2. Rút ngắn retention Prometheus sau khi có Thanos
# Prometheus chỉ cần giữ 2-7 ngày, phần còn lại Thanos lo
prometheus \
--storage.tsdb.retention.time=7d \
--storage.tsdb.max-block-duration=2h \
--storage.tsdb.min-block-duration=2h
3. Kiểm tra block đã upload lên S3 chưa
# Dùng thanos tools để inspect bucket
thanos tools bucket inspect \
--objstore.config-file=bucket.yaml \
--output=table
4. Xử lý lỗi “duplicate samples”
Grafana hiển thị data bị nhân đôi? Thêm flag deduplication vào Thanos Query:
thanos query \
--query.replica-label=replica \
--query.auto-downsampling \
[các endpoint khác]
5. Alert khi Sidecar mất kết nối S3
# alert rule cho Thanos
groups:
- name: thanos
rules:
- alert: ThanosSidecarBucketOperationsFailed
expr: rate(thanos_objstore_bucket_operation_failures_total[5m]) > 0
for: 5m
labels:
severity: warning
annotations:
summary: "Thanos Sidecar không upload được lên Object Storage"
Thanos vs Cortex vs VictoriaMetrics — chọn cái nào?
Câu này mình gặp hoài. Câu trả lời phụ thuộc vào quy mô và mức độ sẵn sàng thay đổi kiến trúc.
Thanos phù hợp nhất nếu đang có Prometheus sẵn — chỉ cần thêm Sidecar, không cần đụng vào cấu hình scraping hiện tại. VictoriaMetrics xử lý throughput cao hơn 5-10x Prometheus trên cùng phần cứng và tốn ít RAM hơn, nhưng đòi hỏi migrate hoàn toàn. Cortex mạnh ở quy mô lớn (hàng trăm triệu samples/giây) nhưng cần thêm Cassandra hoặc DynamoDB cho metadata store — overhead vận hành không nhỏ.
Dưới 10 cluster, dưới 1 triệu active series? Thanos là lựa chọn thực dụng nhất. Không cần over-engineer.

