Prometheus ile cAdvisor Kullanarak Docker Konteyner İzleme
Docker konteynerlarınızı izlemek, modern altyapı yönetiminin en kritik parçalarından biri haline geldi. Onlarca, belki yüzlerce konteynerin koştuğu bir ortamda “hangisi ne kadar kaynak yiyor?” sorusunun cevabını anlık olarak görmek istiyorsunuz. İşte tam bu noktada Prometheus ve cAdvisor ikilisi devreye giriyor. Bu yazıda sıfırdan kurulum yapıp, gerçek dünya senaryolarına uygun alert kuralları ve izleme yapılandırmaları oluşturacağız.
cAdvisor Nedir ve Neden Gerekli?
Prometheus kendi başına harika bir metrik toplama ve sorgulama sistemi. Ancak Docker konteynerlarından metrik toplamak için bir exporter‘a ihtiyaç duyuyor. cAdvisor (Container Advisor), Google tarafından geliştirilen ve Docker konteynerlarının CPU, bellek, ağ ve disk I/O metriklerini toplayarak Prometheus’a sunan açık kaynaklı bir araç.
cAdvisor’ın temel özellikleri şöyle:
- Konteynerlerin gerçek zamanlı kaynak kullanımını izler
- Docker socket’ine doğrudan erişerek veri toplar
/metricsendpoint üzerinden Prometheus formatında metrik sunar- Web arayüzü üzerinden anlık konteyner durumlarını görüntüleyebilirsiniz
- Herhangi bir konfigürasyon gerektirmeden çalışmaya başlar
Normalde docker stats komutu benzer bilgiler verse de bu veriler geçmişe dönük değil, anlık. Prometheus + cAdvisor kombinasyonu ile hem anlık hem de tarihsel analiz yapabiliyorsunuz.
Ortam Hazırlığı
Bu kurulumda Ubuntu 22.04 üzerinde çalışacağız. Docker ve Docker Compose kurulu olduğunu varsayıyorum. Eğer kurulu değilse:
# Docker kurulumu
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Docker Compose kurulumu
sudo apt-get install docker-compose-plugin -y
# Kurulumu doğrula
docker --version
docker compose version
Proje dizin yapımızı oluşturalım:
mkdir -p ~/monitoring/{prometheus,grafana}
cd ~/monitoring
Bu yapı içinde prometheus dizini konfigürasyon dosyalarını, grafana dizini ise Grafana verilerini tutacak.
Docker Compose ile Stack Kurulumu
Tüm servisleri tek bir docker-compose.yml dosyasında tanımlayacağız. Bu yaklaşım hem kurulumu kolaylaştırıyor hem de servislerin birbirleriyle iletişimini yönetmeyi basitleştiriyor.
# ~/monitoring/docker-compose.yml
version: '3.8'
networks:
monitoring:
driver: bridge
volumes:
prometheus_data: {}
grafana_data: {}
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- ./prometheus/rules:/etc/prometheus/rules
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=15d'
- '--web.enable-lifecycle'
- '--web.enable-admin-api'
ports:
- "9090:9090"
networks:
- monitoring
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
privileged: true
devices:
- /dev/kmsg:/dev/kmsg
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
- /cgroup:/cgroup:ro
ports:
- "8080:8080"
networks:
- monitoring
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=gizli_sifre_buraya
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
networks:
- monitoring
depends_on:
- prometheus
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
ports:
- "9100:9100"
networks:
- monitoring
Node Exporter’ı da ekledim çünkü gerçek dünyada konteynerlerin yanında host makinenin metriklerini de izlemek istiyorsunuz. Konteyner %90 CPU kullanıyor görünüyor ama aslında host’un tüm CPU’su dolmuş olabilir.
Prometheus Konfigürasyonu
Şimdi Prometheus’un hangi hedeflerden metrik toplayacağını tanımlayalım:
# ~/monitoring/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
monitor: 'docker-monitoring'
environment: 'production'
rule_files:
- "rules/*.yml"
alerting:
alertmanagers:
- static_configs:
- targets: []
# Alertmanager kurduysanız: targets: ['alertmanager:9093']
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'cadvisor'
scrape_interval: 10s
static_configs:
- targets: ['cadvisor:8080']
metric_relabel_configs:
- source_labels: [container_label_com_docker_compose_service]
target_label: service_name
- source_labels: [name]
regex: '/(.*)'
target_label: container_name
replacement: '$1'
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
relabel_configs:
- source_labels: [__address__]
target_label: instance
replacement: 'production-server-01'
scrape_interval: 10s ile cAdvisor’dan 15 saniye yerine 10 saniyede bir veri çekiyoruz. Konteyner ortamları hızlı değişebildiğinden daha sık örnekleme mantıklı. Ancak bunu çok düşürmemeyin, 5 saniyenin altına inince Prometheus’un bellek kullanımı ciddi artıyor.
Alert Kuralları Oluşturma
Gerçek dünya senaryosu: Bir konteyner belleğin %90’ını kullanıyor, CPU sürekli yüksek, ya da konteyner yeniden başlıyor. Bunları tespit edecek kurallar yazalım:
mkdir -p ~/monitoring/prometheus/rules
# ~/monitoring/prometheus/rules/container_alerts.yml
groups:
- name: container_alerts
interval: 30s
rules:
# Konteyner yüksek CPU kullanımı
- alert: ContainerHighCPUUsage
expr: |
(sum(rate(container_cpu_usage_seconds_total{name!=""}[3m])) by (name)
/ sum(container_spec_cpu_quota{name!=""} / container_spec_cpu_period{name!=""}) by (name)) * 100 > 80
for: 2m
labels:
severity: warning
annotations:
summary: "Konteyner yüksek CPU kullanıyor: {{ $labels.name }}"
description: "{{ $labels.name }} konteyneri son 3 dakikadır %{{ $value | printf "%.1f" }} CPU kullanıyor."
# Konteyner yüksek bellek kullanımı
- alert: ContainerHighMemoryUsage
expr: |
(container_memory_usage_bytes{name!=""} / container_spec_memory_limit_bytes{name!=""}) * 100 > 85
for: 1m
labels:
severity: critical
annotations:
summary: "Bellek limiti aşımı riski: {{ $labels.name }}"
description: "{{ $labels.name }} konteyneri bellek limitinin %{{ $value | printf "%.1f" }}'ini kullanıyor."
# Konteyner yeniden başlatma döngüsü (restart loop)
- alert: ContainerRestartLoop
expr: |
increase(container_start_time_seconds{name!=""}[1h]) > 3
for: 0m
labels:
severity: critical
annotations:
summary: "Konteyner yeniden başlatma döngüsünde: {{ $labels.name }}"
description: "{{ $labels.name }} son 1 saatte {{ $value }} kez yeniden başladı."
# Konteyner durdurulmuş
- alert: ContainerDown
expr: |
absent(container_last_seen{name="web-app"})
for: 1m
labels:
severity: critical
annotations:
summary: "Kritik konteyner çalışmıyor"
description: "web-app konteyneri son 1 dakikadır görünmüyor."
for: 0m kullanımına dikkat edin. Restart loop için bekleme süresi istemiyoruz, hemen uyarı gitsin. Ancak CPU ve bellek alertleri için kısa bir bekleme süresi koyuyoruz, yoksa geçici spike’larda gereksiz alarm üretilir.
Stack’i Ayağa Kaldırmak
cd ~/monitoring
docker compose up -d
# Servislerin durumunu kontrol et
docker compose ps
# Logları takip et
docker compose logs -f prometheus
docker compose logs -f cadvisor
Her şey düzgün ayağa kalktıysa şu portlardan erişebilirsiniz:
- Prometheus: http://sunucu-ip:9090
- cAdvisor: http://sunucu-ip:8080
- Grafana: http://sunucu-ip:3000
- Node Exporter Metrics: http://sunucu-ip:9100/metrics
Prometheus arayüzünde Status > Targets menüsüne gidin. Tüm hedeflerin UP durumunda olduğunu görmelisiniz. Eğer DOWN görüyorsanız büyük ihtimalle network yapılandırmasında sorun var.
Prometheus ile Konteyner Metriklerini Sorgulamak
cAdvisor çalışmaya başladıktan sonra Prometheus’un Expression Browser’ından (http://sunucu-ip:9090/graph) sorgular çalıştırabilirsiniz.
Sık kullandığım PromQL sorguları:
# Tüm konteynerlerin CPU kullanımı (%)
sum(rate(container_cpu_usage_seconds_total{name!=""}[5m])) by (name) * 100
# Belirli bir konteynerin bellek kullanımı (MB)
container_memory_usage_bytes{name="web-app"} / 1024 / 1024
# Bellek kullanım yüzdesi (limit varsa)
(container_memory_usage_bytes{name!=""} / container_spec_memory_limit_bytes{name!=""}) * 100
# En fazla CPU kullanan ilk 5 konteyner
topk(5, sum(rate(container_cpu_usage_seconds_total{name!=""}[5m])) by (name))
# Konteyner ağ trafiği (bytes/s gelen)
sum(rate(container_network_receive_bytes_total{name!=""}[5m])) by (name)
# Konteyner disk write hızı
sum(rate(container_fs_writes_bytes_total{name!=""}[5m])) by (name)
Bu sorguları doğrudan Grafana panellerinde kullanacaksınız. Özellikle topk() fonksiyonu bir anda hangi konteynerin kaynak yediğini anında görmek için çok kullanışlı.
Grafana’da Dashboard Oluşturma
Grafana’ya ilk girişte (admin/gizli_sifre_buraya) önce Prometheus’u data source olarak ekleyin:
- Connections > Data Sources > Add data source
- Prometheus seçin
- URL:
http://prometheus:9090(Docker network içinden konuşuyorlar) - Save & Test butonuna basın
Grafana’nın harika topluluğu hazır dashboard’lar paylaşıyor. 193 veya 14282 ID’li dashboard’ları import edebilirsiniz, bunlar cAdvisor için özel olarak hazırlanmış ve oldukça kapsamlı.
- Dashboards > Import > Dashboard ID: 193 > Load
- Data source olarak az önce eklediğiniz Prometheus’u seçin
- Import butonuna basın
Ancak hazır dashboard’lar bazen ihtiyacınıza tam uymaz. Kendi panellerinizi oluşturmak için:
# Her konteyner için CPU kullanım paneli (time series)
sum(rate(container_cpu_usage_seconds_total{
container_label_com_docker_compose_project="monitoring",
name!=""
}[2m])) by (name) * 100
Gerçek Dünya Senaryosu: Bellek Sızıntısı Tespiti
Bir web uygulamanız var ve zaman içinde yavaşladığını fark ediyorsunuz. Ekip “restart atınca düzeliyor” diyor. Bu klasik bir bellek sızıntısı belirtisi.
Prometheus ile konteyner bellek kullanımının trendine bakabilirsiniz:
# Son 24 saatte bellek kullanım trendi
container_memory_usage_bytes{name="web-app"}
# Bellek kullanımının saatlik artış hızı
deriv(container_memory_usage_bytes{name="web-app"}[1h])
deriv() fonksiyonu sürekli artan bir değer görüyorsa bu gerçekten bellek sızıntısı. Grafana’da bu sorguyu bir panel olarak ekleyip trend çizgisi ekleyin. Eğer düz yukarı giden bir çizgi görüyorsanız geliştiricilere “bakın, işte proof” diye gösterebilirsiniz. Bu tip verileri göstermek, “ya restart yapsak” tartışmalarını bitiriyor.
Çoklu Host İzleme Senaryosu
Birden fazla sunucuda Docker konteynerleri çalışıyorsa merkezi Prometheus’un hepsini scrape etmesini ayarlayabilirsiniz. Her sunucuya sadece cAdvisor ve Node Exporter kurmanız yeterli:
# Remote sunuculara sadece bu servisleri kur
# docker-compose.remote.yml
version: '3.8'
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
privileged: true
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
ports:
- "8080:8080"
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
ports:
- "9100:9100"
Merkezi Prometheus konfigürasyonuna bu sunucuları ekleyin:
# prometheus.yml'e ekleme
scrape_configs:
- job_name: 'cadvisor-remote'
static_configs:
- targets:
- '192.168.1.10:8080'
- '192.168.1.11:8080'
- '192.168.1.12:8080'
labels:
datacenter: 'dc1'
- job_name: 'node-exporter-remote'
static_configs:
- targets:
- '192.168.1.10:9100'
- '192.168.1.11:9100'
- '192.168.1.12:9100'
labels:
datacenter: 'dc1'
Güvenlik açısından 8080 ve 9100 portlarını internete açmayın. Sunucular arasında private network varsa onu kullanın, yoksa Prometheus’u VPN üzerinden bağlayın veya exporter’ların önüne nginx + basic auth koyun.
Prometheus Konfigürasyonunu Yeniden Yükleme
--web.enable-lifecycle flag’ini aktif ettik. Bu sayede Prometheus’u durdurmadan konfigürasyonu yeniden yükleyebilirsiniz:
# Konfigürasyon dosyasının geçerliliğini kontrol et
docker exec prometheus promtool check config /etc/prometheus/prometheus.yml
# Hot reload yap (servisi durdurmadan)
curl -X POST http://localhost:9090/-/reload
# Konteyner içinden yapıyorsanız
docker exec prometheus kill -HUP 1
Yeni bir alert kuralı ekledikten sonra reload yapmayı unutmayın. Bunu atlayınca “neden alert gelmiyor” diye 20 dakika debug yapabilirsiniz.
Disk Kullanımını Kontrol Altında Tutmak
Prometheus verilerini uzun süre tutmak disk alanını hızla tüketebilir. Özellikle çok sayıda konteyner izleniyorsa günde birkaç GB veri üretilebilir.
# Prometheus veri dizininin boyutunu kontrol et
docker exec prometheus du -sh /prometheus
# Mevcut TSDB durumunu görüntüle
curl http://localhost:9090/api/v1/status/tsdb | python3 -m json.tool
# Disk alanı kritik olduğunda eski verileri silmek için
curl -X POST -g 'http://localhost:9090/api/v1/admin/tsdb/delete_series?match[]={job="cadvisor"}&start=2024-01-01T00:00:00Z&end=2024-01-15T00:00:00Z'
docker-compose.yml‘deki --storage.tsdb.retention.time=15d ayarı ile Prometheus otomatik olarak 15 günden eski verileri siliyor. Uzun vadeli depolama gerekiyorsa Thanos veya Cortex gibi çözümlere bakmanız gerekiyor, ancak bu ayrı bir yazı konusu.
Yaygın Sorunlar ve Çözümleri
cAdvisor metrikleri gelmiyor:
# cAdvisor loglarını kontrol et
docker logs cadvisor --tail 50
# Privileged mod aktif mi kontrol et
docker inspect cadvisor | grep -i privileged
# /dev/kmsg erişimi sorun yaratıyorsa bu satırı kaldır
# devices:
# - /dev/kmsg:/dev/kmsg
Prometheus hedefler DOWN görünüyor:
# Network bağlantısını test et
docker exec prometheus wget -qO- http://cadvisor:8080/metrics | head -20
# DNS çözümlemesini kontrol et
docker exec prometheus nslookup cadvisor
Grafana Prometheus’a bağlanamıyor:
Grafana konfigürasyonunda URL olarak http://localhost:9090 yazarsanız çalışmaz. Grafana konteyneri kendi localhost’unu görür. Doğru URL: http://prometheus:9090 (servis adı üzerinden Docker network içi iletişim).
Sonuç
Prometheus ve cAdvisor kombinasyonu, Docker konteyner izleme için production ortamında da güvenle kullanabileceğiniz sağlam bir çözüm. Kurulumu bir kez yapıp doğru alert kurallarını tanımladıktan sonra “bir şeyler çöktüğünde öğrenmek” yerine “çökmeden önce haberdar olmak” konumuna geçiyorsunuz.
Bu stack’in güzelliği genişleyebilir olması. Bugün Docker konteynerlarını izliyorsunuz, yarın bir PostgreSQL exporter, bir Redis exporter ya da kendi uygulamanızın metriklerini ekleyebilirsiniz. Prometheus ekosistemi inanılmaz zengin, neredeyse her teknoloji için hazır bir exporter bulabiliyorsunuz.
Bir sonraki adım olarak Alertmanager kurarak Slack veya e-posta entegrasyonu yapmayı öneririm. Alert kuralları yazdınız ama onları nereye göndereceğinizi tanımlamak da en az kural yazmak kadar önemli. Ayrıca Grafana’nın provisioning özelliğiyle dashboard’larınızı ve data source konfigürasyonlarınızı kod olarak yönetmek, bu altyapıyı başka sunuculara taşımayı çok kolaylaştırıyor.
