Prometheus Remote Storage: Store Metrics ใน Long-term Storage (S3, ClickHouse)

ข้อจำกัดใหญ่ของ Prometheus คือ TSDB ฝั่ง local เก็บข้อมูลได้แค่ระยะสั้น — ค่า default retention อยู่ที่ 15 วัน และถ้าดันขึ้นถึง 6 เดือนหรือ 1 ปี ดิสก์ของ server จะเต็มอย่างรวดเร็ว นอกจากนี้การ query ข้อมูลข้าม Prometheus หลายตัวก็ทำไม่ได้โดยตรง เมื่อองค์กรต้องการเก็บ metrics ไว้ย้อนหลังหลายปีเพื่อ compliance, capacity planning หรือ trend analysis ระยะยาว ทางออกคือใช้ Remote Storage — ตัวเก็บข้อมูลภายนอกที่ออกแบบมาสำหรับ long-term retention ผ่าน remote_write / remote_read protocol ที่ Prometheus รองรับเป็น built-in

ทำไม Local TSDB ไม่พอ

TSDB บน disk ของ Prometheus ถูกออกแบบให้ทำงานกับ workload ระยะสั้น — เน้นเขียนเร็ว อ่านเร็วในช่วง 1-2 สัปดาห์ล่าสุด เก็บนานกว่านั้นจะติดข้อจำกัดเรื่อง disk size, block compaction, และ memory สำหรับ index หาก retention ยาวขึ้น (เช่น 90 วัน) prediction disk usage มักพุ่งเกินจริง 2-3 เท่าเพราะ label cardinality ที่ไม่ได้ควบคุม และเวลา restart server ต้องโหลด index ขึ้น memory ทำให้ startup time ช้าลงตามปริมาณข้อมูล

อีกปัญหาคือ single-instance storage ไม่มี replication — ถ้า disk เสียหรือไฟล์เสียจาก crash ข้อมูลสูญทันที ไม่มี snapshot ต้นทางให้กู้กลับ นอกจากนี้การรวม metric จาก server หลายตัวใน Dashboard เดียวต้องใช้ Federation ที่ bandwidth-heavy หรือ Thanos/Mimir เข้ามาช่วย ซึ่งล้วนอาศัย Remote Storage เป็นฐาน

Remote Write และ Remote Read

Remote Write คือ protocol ที่ Prometheus ส่ง sample ทุกตัวที่ scrape ได้ไปยัง endpoint ภายนอกแบบ batch พร้อม snappy compression รูปแบบคือ protobuf ผ่าน HTTP POST — ระบบปลายทางที่รองรับ protocol นี้จะรับแล้วเก็บลง backend ของตัวเอง (S3, Cassandra, ClickHouse, ฯลฯ) ส่วน Remote Read เป็น query-side: Prometheus ส่ง query ไปให้ remote endpoint ช่วยตอบ แล้วรวมผลกับ local TSDB ก่อน return ให้ผู้ใช้

# prometheus.yml
remote_write:
  - url: "https://storage.example.com/api/v1/write"
    queue_config:
      capacity: 10000
      max_shards: 30
      max_samples_per_send: 2000
      batch_send_deadline: 5s
    write_relabel_configs:
      - source_labels: [__name__]
        regex: "go_.*"
        action: drop        # ตัด metric ที่ไม่ต้องการเก็บนาน

remote_read:
  - url: "https://storage.example.com/api/v1/read"
    read_recent: false      # ข้อมูลช่วงล่าสุดยังดูจาก local TSDB

พารามิเตอร์ queue_config มีผลโดยตรงกับ memory ของ server: max_shards คือจำนวน goroutine ที่ flush batch ขนานกัน ถ้า remote endpoint ช้าแต่ตั้งค่าสูงเกินไปจะกิน RAM มหาศาล การ monitor metric prometheus_remote_storage_shards และ prometheus_remote_storage_samples_pending จึงจำเป็นเพื่อปรับ tuning ให้ match กับ throughput จริง

Thanos

Thanos เชื่อมต่อกับ Prometheus ผ่าน sidecar ที่อ่าน block จาก local TSDB แล้วอัพโหลดเข้า object storage (S3, GCS, Azure Blob) หน่วย Store Gateway ใช้ block เหล่านั้นตอบ query ระยะยาว ส่วน Compactor ทำ downsample เพื่อลดขนาดข้อมูลเก่า (5m / 1h resolution) ข้อเด่นคือ cost ต่ำ — ใช้ object storage ราคาถูก และ dedup ข้อมูลจาก HA pair ได้โดย Querier

Mimir / Cortex

Grafana Mimir (fork มาจาก Cortex) รับ remote_write โดยตรงไม่ต้องอาศัย sidecar — ทำ horizontal scaling ได้เต็มรูปแบบ รองรับ multi-tenancy ผ่าน HTTP header X-Scope-OrgID เก็บข้อมูลบน object storage เช่นกัน และมี query engine แบบ distributed ที่แบ่งงานข้าม replicas เหมาะกับองค์กรที่ต้อง serve metric ให้หลายทีมหรือหลายลูกค้าในคลัสเตอร์เดียว

VictoriaMetrics

VictoriaMetrics เป็น TSDB ทางเลือกที่ compact และเร็วกว่า default TSDB ของ Prometheus หลายเท่า รองรับ protocol remote_write ของ Prometheus, Graphite, InfluxDB ในตัวเดียว deploy แบบ single-binary หรือ cluster ก็ได้ ใช้ disk-based storage ของตัวเอง (ไม่ใช่ object storage) — เหมาะเมื่อต้องการ latency ต่ำและ operation simple กว่า Thanos/Mimir

ClickHouse (ผ่าน Adapter)

ClickHouse ไม่ได้รองรับ remote_write โดยตรง แต่มี adapter อย่าง PromHouse หรือ ClickHouse-native ingest ที่แปลง protobuf เป็น table schema ได้ จุดเด่นคือ SQL query ที่ flexible กว่า PromQL และเก็บ log + metric ใน backend เดียวกันได้ ข้อเสียคือ dashboard ใน Grafana ต้องใช้ SQL plugin แทน Prometheus datasource ปกติ

ตารางเปรียบเทียบ

SolutionBackendจุดเด่นเหมาะกับ
ThanosObject Storage (S3/GCS)Cost ต่ำ, dedup HAMulti-site federation
MimirObject StorageMulti-tenant, scale ดีEnterprise SaaS
VictoriaMetricsLocal DiskCompact, fast ingestPerformance-critical
ClickHouseSQL DBSQL + flexible schemaData lake

ข้อควรระวังเมื่อเปิด Remote Write

  • ตรวจ network egress cost — sample หลาย million/นาที ถ้าส่งข้าม region จะคิดค่า bandwidth ทุกวัน
  • ใช้ write_relabel_configs เพื่อ drop metric ที่ไม่จำเป็น (โดยเฉพาะ metric ภายในของแอป เช่น go_*, process_*)
  • ตั้ง retention local 2-4 ชั่วโมงให้ครอบคลุมช่วงที่ remote ดาวน์ได้ เพื่อ buffer การ retry
  • Monitor prometheus_remote_storage_failed_samples_total และ prometheus_remote_storage_dropped_samples_total เพื่อรู้ว่าข้อมูลหายก่อนเก็บถึงหรือไม่
  • ระวัง label cardinality สูงจะทำให้ remote endpoint ประมวลผลช้า หรือ reject 429 — control ที่ต้นทางเสมอ

สถาปัตยกรรม Reference

Pattern ทั่วไปคือ Prometheus local (retention 2-6 ชั่วโมง) → remote_write → long-term store (Thanos/Mimir/VictoriaMetrics) → Grafana query ผ่าน unified datasource — query ช่วง real-time ยังไปที่ local server เพื่อ latency ต่ำ แต่ query ย้อนหลังจะ route ไปยัง remote โดยอัตโนมัติผ่าน query frontend หรือ Thanos Querier

[ Exporters ] --scrape--> [ Prometheus (local 4h) ]
                                |
                                | remote_write
                                v
                         [ Mimir / Thanos ]
                                |
                                v
                        [ Object Storage (S3) ]
                                ^
                                |
[ Grafana ] --> [ Query Frontend ] ----+
                                |
                                +--> [ Prometheus (local) ]

สรุป

Remote Storage ช่วยแก้ข้อจำกัดของ local TSDB เรื่อง retention, replication และ global query — โดยไม่ต้องเปลี่ยน workflow การ scrape เดิม เลือก backend ให้ match กับ workload: Thanos เหมาะกับระบบที่มี Prometheus หลายตัวกระจายเป็น data center-level, Mimir เหมาะกับ multi-tenant SaaS, VictoriaMetrics เหมาะกับ team ที่ต้องการ performance สูงและ operation ง่าย ส่วน ClickHouse เหมาะเป็น analytics store ที่รวม log + metric ใน platform เดียว

ไม่ว่าจะเลือก solution ใด สิ่งที่ต้องวางก่อนคือ relabel rule (ตัด metric ที่ไม่จำเป็น), queue tuning, และ cardinality budget — เพราะ remote_write ไม่ได้แก้ปัญหา cardinality ที่ต้นทาง ถ้าส่งทุก label ไปทั้งหมดจะทำให้ backend พังเหมือนกัน