Thanos ile Prometheus Yüksek Erişilebilirlik Kurulumu

Prometheus kurulumunu bitirdiniz, metrikler akıyor, Grafana dashboard’larınız hazır. Ama bir gece sunucunuz restart oldu ve o anlık Prometheus instance’ınız da gitti. Ya da daha kötüsü, birden fazla Prometheus kurulumunuz var, her biri farklı bir veri seti tutuyor ve bunları birleştirmeniz gerekiyor. İşte tam bu noktada Thanos devreye giriyor.

Thanos, Prometheus’u gerçek anlamda production-ready hale getiren bir araç. Yüksek erişilebilirlik, uzun dönem depolama ve küresel sorgu yeteneği sunuyor. Bu yazıda sıfırdan bir Thanos kurulumu yapacağız, Prometheus ile entegre edeceğiz ve gerçek dünyada karşılaşacağınız senaryolara göre yapılandıracağız.

Thanos Nedir ve Neden Lazım?

Prometheus kendi başına harika bir araç ama bazı kısıtlamaları var. Verileri sadece yerel diskte tutuyor, tek bir instance birden fazla Prometheus’u birleştiremez ve yatay ölçekleme yapmıyor. Büyük altyapılarda bu sorunlar çok hızlı yüzünüze çarpıyor.

Thanos bu sorunları şu bileşenlerle çözüyor:

  • Thanos Sidecar: Prometheus’un yanına oturuyor, TSDB bloklarını object storage’a yüklüyor
  • Thanos Store Gateway: Object storage’daki verileri sorgulayabilir hale getiriyor
  • Thanos Querier: Birden fazla kaynaktan veri toplayıp birleştiriyor
  • Thanos Compactor: Object storage’daki eski blokları sıkıştırıyor ve downsampling yapıyor
  • Thanos Ruler: Alerting ve recording rule’ları Thanos üzerinden çalıştırıyor
  • Thanos Receiver: Remote write ile gelen metrikleri alıyor (push-based model için)

Gerçek dünya senaryosuna bakalım: 3 farklı veri merkeziniz var, her birinde Prometheus çalışıyor. Grafana’da hepsini tek ekranda görmek istiyorsunuz ve 2 yıllık metrik verisi tutmanız gerekiyor. Thanos olmadan bu iş gerçekten çok zahmetli.

Ortam Hazırlığı

Bu yazıda şu yapıyı kuracağız:

  • 2 adet Prometheus instance (HA çifti)
  • Thanos Sidecar (her Prometheus yanında)
  • MinIO (object storage olarak, S3 yerine lokal test için)
  • Thanos Store Gateway
  • Thanos Querier
  • Thanos Compactor

Önce gerekli dizinleri oluşturalım:

mkdir -p /opt/thanos/{bin,config,data}
mkdir -p /opt/prometheus/{prometheus1,prometheus2}/{data,config}
mkdir -p /opt/minio/data

# Thanos binary indirme (versiyonu kontrol edin)
cd /opt/thanos/bin
THANOS_VERSION="0.35.1"
wget https://github.com/thanos-io/thanos/releases/download/v${THANOS_VERSION}/thanos-${THANOS_VERSION}.linux-amd64.tar.gz
tar xzf thanos-${THANOS_VERSION}.linux-amd64.tar.gz
cp thanos-${THANOS_VERSION}.linux-amd64/thanos /usr/local/bin/
chmod +x /usr/local/bin/thanos
thanos --version

MinIO’yu da ayarlayalım, bu bizim object storage’ımız olacak:

# MinIO kurulumu
wget https://dl.min.io/server/minio/release/linux-amd64/minio -O /usr/local/bin/minio
chmod +x /usr/local/bin/minio

# MinIO için systemd servis
cat > /etc/systemd/system/minio.service << 'EOF'
[Unit]
Description=MinIO Object Storage
After=network.target

[Service]
Type=simple
User=minio
Group=minio
Environment=MINIO_ROOT_USER=thanosadmin
Environment=MINIO_ROOT_PASSWORD=thanossecret123
Environment=MINIO_VOLUMES=/opt/minio/data
ExecStart=/usr/local/bin/minio server /opt/minio/data --console-address ":9001"
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

useradd -r -s /bin/false minio
chown -R minio:minio /opt/minio
systemctl daemon-reload
systemctl enable --now minio

MinIO ayağa kalktıktan sonra http://sunucu-ip:9000 adresinden giriş yapıp thanos adında bir bucket oluşturun.

Prometheus Yapılandırması

Yüksek erişilebilirlik için iki Prometheus instance çalıştıracağız. Her ikisi de aynı hedefleri scrape edecek, Thanos bu iki kopyanın de-duplikasyonunu yapacak.

İlk Prometheus için yapılandırma:

# /opt/prometheus/prometheus1/config/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    cluster: "production"
    replica: "prometheus-1"  # Bu label Thanos de-duplikasyonu için kritik!

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]

  - job_name: "node_exporter"
    static_configs:
      - targets:
          - "web-server-01:9100"
          - "web-server-02:9100"
          - "db-server-01:9100"

  - job_name: "blackbox"
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
          - "https://orneksite.com"
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: "localhost:9115"

İkinci Prometheus için sadece replica label’ını değiştirin:

# /opt/prometheus/prometheus2/config/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    cluster: "production"
    replica: "prometheus-2"  # Burayı değiştirdik

# Geri kalan kısım aynı...

Neden replica label önemli? Thanos Querier, de-duplikasyon yaparken bu label’a bakıyor. cluster label’ı aynı, sadece replica farklı olan metrikleri tek bir kaynak gibi gösteriyor. Eğer bunu yapmazsanız aynı metriği iki kez görürsünüz.

Thanos Sidecar Kurulumu

Her Prometheus instance’ının yanına bir Sidecar koyuyoruz. Sidecar iki işi yapıyor: Prometheus’un TSDB bloklarını object storage’a yüklüyor ve Prometheus’u Thanos Querier’a expose ediyor.

Object storage yapılandırma dosyası:

# /opt/thanos/config/objstore.yml
type: S3
config:
  bucket: "thanos"
  endpoint: "localhost:9000"
  access_key: "thanosadmin"
  secret_key: "thanossecret123"
  insecure: true  # MinIO için HTTP kullanıyoruz, production'da false yapın

Sidecar servisleri oluşturalım:

# Prometheus 1 için Thanos Sidecar systemd servisi
cat > /etc/systemd/system/thanos-sidecar-1.service << 'EOF'
[Unit]
Description=Thanos Sidecar for Prometheus 1
After=network.target prometheus1.service

[Service]
Type=simple
User=prometheus
Group=prometheus
ExecStart=/usr/local/bin/thanos sidecar 
  --tsdb.path=/opt/prometheus/prometheus1/data 
  --prometheus.url=http://localhost:9090 
  --objstore.config-file=/opt/thanos/config/objstore.yml 
  --http-address=0.0.0.0:19191 
  --grpc-address=0.0.0.0:10901
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

# Prometheus 2 için Thanos Sidecar (farklı portlar!)
cat > /etc/systemd/system/thanos-sidecar-2.service << 'EOF'
[Unit]
Description=Thanos Sidecar for Prometheus 2
After=network.target prometheus2.service

[Service]
Type=simple
User=prometheus
Group=prometheus
ExecStart=/usr/local/bin/thanos sidecar 
  --tsdb.path=/opt/prometheus/prometheus2/data 
  --prometheus.url=http://localhost:9092 
  --objstore.config-file=/opt/thanos/config/objstore.yml 
  --http-address=0.0.0.0:19192 
  --grpc-address=0.0.0.0:10902
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now thanos-sidecar-1 thanos-sidecar-2

Thanos Store Gateway

Store Gateway, object storage’daki tarihsel verileri sorgulayabilir hale getiriyor. Sidecar yeni verileri (son 2 saat) sağlarken, Store eski verileri sunuyor.

cat > /etc/systemd/system/thanos-store.service << 'EOF'
[Unit]
Description=Thanos Store Gateway
After=network.target

[Service]
Type=simple
User=thanos
Group=thanos
ExecStart=/usr/local/bin/thanos store 
  --data-dir=/opt/thanos/data/store 
  --objstore.config-file=/opt/thanos/config/objstore.yml 
  --http-address=0.0.0.0:19191 
  --grpc-address=0.0.0.0:10905 
  --index-cache-size=500MB 
  --chunk-pool-size=2GB
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

useradd -r -s /bin/false thanos
mkdir -p /opt/thanos/data/store
chown -R thanos:thanos /opt/thanos/data
systemctl daemon-reload
systemctl enable --now thanos-store

--index-cache-size ve --chunk-pool-size parametrelerine dikkat edin. Bunlar performans için kritik. İndex cache, hangi blokların hangi time range’i kapsadığını memory’de tutuyor. Yeterince büyük tutarsanız disk I/O’su ciddi ölçüde azalıyor.

Thanos Querier Kurulumu

Querier, tüm Thanos bileşenlerini birleştiren merkezi nokta. Grafana bu adrese bağlanıyor.

cat > /etc/systemd/system/thanos-querier.service << 'EOF'
[Unit]
Description=Thanos Querier
After=network.target

[Service]
Type=simple
User=thanos
Group=thanos
ExecStart=/usr/local/bin/thanos query 
  --http-address=0.0.0.0:9091 
  --grpc-address=0.0.0.0:10906 
  --endpoint=localhost:10901 
  --endpoint=localhost:10902 
  --endpoint=localhost:10905 
  --query.replica-label=replica 
  --query.auto-downsampling
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now thanos-querier

--query.replica-label=replica parametresi kritik. Thanos Querier bu label değerine göre hangi metriklerin duplicate olduğunu anlıyor ve birini eliyor. --query.auto-downsampling ise uzun time range sorgularında otomatik olarak downsampled veri kullanıyor, bu sayede 1 yıllık grafik çizerken her sample’ı çekmek yerine 5 dakikalık örneklenmiş veri kullanılıyor.

Thanos Compactor Kurulumu

Compactor arka planda çalışıyor ve iki işi yapıyor: Eski blokları sıkıştırıyor (2 saatlik blokları 2 günlük bloklara birleştiriyor) ve downsampling yapıyor (5 dakikalık ve 1 saatlik örnekler oluşturuyor).

cat > /etc/systemd/system/thanos-compactor.service << 'EOF'
[Unit]
Description=Thanos Compactor
After=network.target

[Service]
Type=simple
User=thanos
Group=thanos
ExecStart=/usr/local/bin/thanos compact 
  --data-dir=/opt/thanos/data/compact 
  --objstore.config-file=/opt/thanos/config/objstore.yml 
  --http-address=0.0.0.0:19195 
  --retention.resolution-raw=30d 
  --retention.resolution-5m=90d 
  --retention.resolution-1h=365d 
  --wait 
  --wait-interval=30m
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

mkdir -p /opt/thanos/data/compact
chown -R thanos:thanos /opt/thanos/data
systemctl daemon-reload
systemctl enable --now thanos-compactor

Retention politikasını açıklayayım:

  • –retention.resolution-raw=30d: Ham veri (her 15 saniyede bir sample) 30 gün tutuluyor
  • –retention.resolution-5m=90d: 5 dakikalık downsampled veri 90 gün tutuluyor
  • –retention.resolution-1h=365d: 1 saatlik downsampled veri 1 yıl tutuluyor

Bu sayede 1 yıllık grafik için storage maliyetiniz çok düşüyor.

Önemli not: Compactor singleton olmalı. Aynı bucket’a birden fazla Compactor bağlamayın, veri bozulmasına yol açar.

Grafana Entegrasyonu

Grafana’ya Thanos Querier’ı datasource olarak ekleyin:

# Grafana datasource provisioning ile otomatik ekleyebilirsiniz
cat > /etc/grafana/provisioning/datasources/thanos.yml << 'EOF'
apiVersion: 1

datasources:
  - name: Thanos
    type: prometheus
    access: proxy
    url: http://localhost:9091
    isDefault: true
    jsonData:
      timeInterval: "15s"
      queryTimeout: "60s"
      httpMethod: POST
    editable: true
EOF

systemctl restart grafana-server

Grafana’da artık Prometheus yerine Thanos datasource’unu kullanacaksınız. Sorgular tamamen aynı PromQL, hiçbir şeyi değiştirmenize gerek yok.

Sağlık Kontrolü ve Troubleshooting

Tüm bileşenler ayağa kalktı mı kontrol edelim:

# Tüm Thanos servislerinin durumunu kontrol et
for service in thanos-sidecar-1 thanos-sidecar-2 thanos-store thanos-querier thanos-compactor; do
  echo "=== $service ==="
  systemctl status $service --no-pager -l | tail -5
done

# HTTP health endpoint kontrolleri
curl -s http://localhost:19191/-/healthy  # Sidecar 1
curl -s http://localhost:19192/-/healthy  # Sidecar 2
curl -s http://localhost:19191/-/healthy  # Store Gateway
curl -s http://localhost:9091/-/healthy   # Querier

# Querier'in kaç endpoint gördüğünü kontrol et
curl -s http://localhost:9091/api/v1/stores | python3 -m json.tool

# Object storage'a veri gidiyor mu?
# MinIO'dan bucket içeriğini listele
mc alias set local http://localhost:9000 thanosadmin thanossecret123
mc ls local/thanos/

Sidecar’ın Prometheus’un TSDB bloklarını yükleyip yüklemediğini görmek için:

# Sidecar loglarını izle
journalctl -u thanos-sidecar-1 -f

# Başarılı upload şöyle görünür:
# level=info msg="upload completed" block=01H... duration=2.3s

# Querier'dan metrics kontrol
curl -s "http://localhost:9091/api/v1/query?query=up" | 
  python3 -c "import sys,json; data=json.load(sys.stdin); 
  [print(r['metric']['job'], r['metric'].get('replica','?'), r['value'][1]) 
  for r in data['data']['result']]"

Gerçek Dünya Senaryosu: Multi-Cluster Kurulum

Diyelim ki 3 farklı Kubernetes cluster’ınız var. Her birinde Prometheus çalışıyor ve merkezi bir Thanos Querier’dan hepsini görmek istiyorsunuz.

Her cluster’daki Sidecar için external_labels şöyle olmalı:

# Cluster A
external_labels:
  cluster: "k8s-prod-eu-west"
  replica: "prometheus-0"

# Cluster B
external_labels:
  cluster: "k8s-prod-us-east"
  replica: "prometheus-0"

# Cluster C
external_labels:
  cluster: "k8s-staging"
  replica: "prometheus-0"

Merkezi Querier tüm cluster’ları biliyor olmalı:

thanos query 
  --http-address=0.0.0.0:9091 
  --endpoint=k8s-prod-eu-west-thanos-sidecar:10901 
  --endpoint=k8s-prod-us-east-thanos-sidecar:10901 
  --endpoint=k8s-staging-thanos-sidecar:10901 
  --endpoint=thanos-store:10905 
  --query.replica-label=replica

Bu yapıda cluster label’ına göre PromQL yazabilirsiniz:

# Sadece prod EU'daki CPU kullanımı
avg(rate(node_cpu_seconds_total{cluster="k8s-prod-eu-west",mode="idle"}[5m]))

# Tüm cluster'larda HTTP 5xx oranı
sum by (cluster) (rate(http_requests_total{status=~"5.."}[5m]))

Alert ve Record Rules Thanos ile

Eğer alerting rule’larınız var ve bunları Thanos üzerinden çalıştırmak istiyorsanız Thanos Ruler devreye giriyor. Özellikle multi-cluster sorgularına dayanan alert’lar için gerekli.

cat > /opt/thanos/config/rules/alerts.yml << 'EOF'
groups:
  - name: thanos-rules
    interval: 1m
    rules:
      - alert: NodeHighCPU
        expr: |
          avg by (instance, cluster) (
            rate(node_cpu_seconds_total{mode!="idle"}[5m])
          ) > 0.85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Yüksek CPU kullanımı: {{ $labels.instance }}"
          description: "{{ $labels.cluster }} cluster'ında {{ $labels.instance }} üzerinde CPU kullanımı %{{ $value | humanizePercentage }}"
EOF

Thanos Ruler servisi:

cat > /etc/systemd/system/thanos-ruler.service << 'EOF'
[Unit]
Description=Thanos Ruler
After=network.target

[Service]
Type=simple
User=thanos
Group=thanos
ExecStart=/usr/local/bin/thanos rule 
  --data-dir=/opt/thanos/data/ruler 
  --eval-interval=1m 
  --rule-file=/opt/thanos/config/rules/*.yml 
  --alertmanagers.url=http://localhost:9093 
  --query=http://localhost:9091 
  --objstore.config-file=/opt/thanos/config/objstore.yml 
  --http-address=0.0.0.0:19196 
  --grpc-address=0.0.0.0:10907 
  --label=ruler_cluster="production" 
  --label=ruler_replica="ruler-1"
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

mkdir -p /opt/thanos/data/ruler
chown -R thanos:thanos /opt/thanos/data
systemctl daemon-reload
systemctl enable --now thanos-ruler

Performans İpuçları

Production’da karşılaştığım birkaç önemli nokta:

  • Store Gateway bellek kullanımı: Index cache için yeterli bellek ayırın. 1 yıllık veri için en az 4GB RAM Store Gateway’e ayırmanızı öneririm. --index-cache-size=2GB ile başlayın ve gözlemleyin.
  • Compactor tek instance zorunluluğu: Bunu tekrar vurguluyorum çünkü bu hatayı yapanları gördüm. İki Compactor aynı bucket’a bağlanırsa bloklar karışıyor ve veri kaybı yaşanıyor.
  • Sidecar ve Prometheus TSDB: Sidecar’ın Prometheus TSDB dizinine doğrudan erişimi olmalı. Prometheus’un --storage.tsdb.min-block-duration=2h ve --storage.tsdb.max-block-duration=2h ayarlarını Sidecar ile uyumlu tutun. Varsayılan değerler genellikle iyi çalışır.
  • Object storage maliyeti: MinIO üzerinde çalışırken fark etmezsiniz ama S3’e geçtiğinizde GET request maliyetleri önemli oluyor. Store Gateway’in chunk pool’unu büyük tutarak aynı veriyi defalarca S3’ten çekmesini önleyin.
  • Querier timeout: Uzun time range sorguları için --query.timeout=5m değerini artırmayı düşünün. Grafana’da 1 yıllık grafik çizerken zaman aşımı yaşarsanız bu parametreye bakın.

Sonuç

Thanos kurulumu ilk bakışta karmaşık görünüyor ama her bileşenin belirli bir görevi var ve birbirini güzel tamamlıyorlar. Özetlersek:

  • Sidecar: Prometheus yanında oturuyor, veriyi object storage’a taşıyor
  • Store Gateway: Eski veriyi sorgulanabilir yapıyor
  • Querier: Her şeyi birleştiriyor, Grafana buraya bakıyor
  • Compactor: Depolama maliyetini düşürüyor, arka planda çalışıyor
  • Ruler: Thanos veriyle alert yazmanızı sağlıyor

Bu yapıyı kurduğunuzda hem yüksek erişilebilirlik hem uzun dönem depolama hem de multi-cluster görünürlük elde ediyorsunuz. Prometheus’un tek instance kısıtından kurtuluyorsunuz ve altyapınızı büyüttükçe bu yapı da sorunsuz ölçekleniyor.

Başlangıç için MinIO ile test edin, her şey stabil çalıştıktan sonra AWS S3 veya Google Cloud Storage’a geçin. Object storage sağlayıcısı değiştiğinde sadece objstore.yml dosyasını güncellemeniz yeterli, geri kalan hiçbir şeyi değiştirmenize gerek yok.

Benzer Konular

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir