
![]()
Monitoring; sistemlerin sağlıklı çalışıp çalışmadığını anlamak, hataları tespit etmek ve performansı ölçmek için hayati öneme sahiptir. Bu yazıda, popüler açık kaynak kodlu izleme (monitoring) araçları olan Prometheus ve Grafana’nın nasıl kullanılacağından bahsedecek ve Kafka’nın izlenmesiyle ilgili docker ortamında bir örnek yapacağız.
Prometheus
Prometheus, açık kaynak kodlu bir izleme ve uyarı sistemi olup, ölçüm verilerini birleştirmek ve işlemek için çok boyutlu veri modeli ve esnek sorgu diline sahiptir. Hedeflerini, servis keşif mekanizması veya statik yapılandırma ile belirleyebilir ve bu hedeflerden zaman serisi verilerini toplar. Bu veriler, Grafana gibi görselleştirme araçlarıyla incelenebilir.

Grafana
Grafana, çok çeşitli veri kaynaklarından veri görselleştirme ve analiz için kullanılan açık kaynaklı bir platformdur. Grafana, grafikler, histogramlar ve ölçekler oluşturarak veri analizi yapabilir. Ayrıca, kullanıcıların belirli metrikleri ve verileri izlemelerine olanak tanıyan bir uyarı özelliği de vardır.

Araçları tanıdığımıza göre uygulama kısmına geçebiliriz.
Demo
Uygulamayı Docker ortamında gerçekleştireceğiz. Kullandığımız docker-compose dosyasını aşağıda paylaşıyorum. Proje dosyalarına GitHub üzerinden de erişebilirsiniz.
version: "3.8"
services:
grafana:
image: "grafana/grafana:9.5.12"
ports:
- "3000:3000"
environment:
GF_PATHS_DATA: /var/lib/grafana
GF_SECURITY_ADMIN_PASSWORD: admin
container_name: grafana
depends_on:
- prometheus
networks:
- monitoring
prometheus:
image: "prom/prometheus:v2.47.1"
ports:
- "9090:9090"
volumes:
- ./etc/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
command: "--config.file=/etc/prometheus/prometheus.yml"
container_name: prometheus
networks:
- monitoring
jmx-kafka101:
image: "kayademirseda/jmx_exporter:1.0"
ports:
- "5556:5556"
environment:
CONFIG_YML: "/etc/jmx_exporter/config.yml"
JVM_OPTS: ${PROMETHEUS_JMX_AGENT_JVM_OPTS}
volumes:
- ./etc/jmx_exporter/config_kafka101.yml:/etc/jmx_exporter/config.yml
container_name: jmx-kafka101
depends_on:
- kafka101
networks:
- monitoring
jmx-kafka102:
image: "kayademirseda/jmx_exporter:1.0"
ports:
- "5557:5556"
environment:
CONFIG_YML: "/etc/jmx_exporter/config.yml"
JVM_OPTS: ${PROMETHEUS_JMX_AGENT_JVM_OPTS}
volumes:
- ./etc/jmx_exporter/config_kafka102.yml:/etc/jmx_exporter/config.yml
container_name: jmx-kafka102
depends_on:
- kafka102
networks:
- monitoring
jmx-kafka103:
image: "kayademirseda/jmx_exporter:1.0"
ports:
- "5558:5556"
environment:
CONFIG_YML: "/etc/jmx_exporter/config.yml"
JVM_OPTS: ${PROMETHEUS_JMX_AGENT_JVM_OPTS}
volumes:
- ./etc/jmx_exporter/config_kafka103.yml:/etc/jmx_exporter/config.yml
container_name: jmx-kafka103
depends_on:
- kafka103
networks:
- monitoring
kafka101:
image: "kayademirseda/kafka:1.0"
ports:
- "19092:9092"
- "9991:9991"
container_name: kafka101
volumes:
- ./etc/kafka/config/kafka1/server.properties:/kafka/config/server.properties
- ./etc/kafka/data/kafka1/:/data/kafka/
environment:
JMX_PORT: 9991
deploy:
resources:
limits:
memory: ${KAFKA_BROKER_MEM_LIMIT}
networks:
- monitoring
kafka102:
image: "kayademirseda/kafka:1.0"
ports:
- "29092:9092"
- "9992:9992"
container_name: kafka102
volumes:
- ./etc/kafka/config/kafka2/server.properties:/kafka/config/server.properties
- ./etc/kafka/data/kafka2/:/data/kafka/
environment:
JMX_PORT: 9992
deploy:
resources:
limits:
memory: ${KAFKA_BROKER_MEM_LIMIT}
networks:
- monitoring
kafka103:
image: "kayademirseda/kafka:1.0"
ports:
- "39092:9092"
- "9993:9993"
container_name: kafka103
volumes:
- ./etc/kafka/config/kafka3/server.properties:/kafka/config/server.properties
- ./etc/kafka/data/kafka3/:/data/kafka/
environment:
JMX_PORT: 9993
deploy:
resources:
limits:
memory: ${KAFKA_BROKER_MEM_LIMIT}
networks:
- monitoring
networks:
monitoring:
name: monitoring
driver: bridgeKısaca servislerin yapılandırmasına göz atalım.
- Grafana: Çeşitli veri kaynaklarından verileri görselleştirmek ve analiz etmek için kullanılan bir platformdur. Bu servis 3000 numaralı porttan hizmet verir. Ayrıca, Prometheus servisine bağımlıdır.
- Prometheus: Hedeflerden zaman serisi verilerini toplayan bir izleme ve uyarı sistemidir. Bu servis 9090 numaralı porttan hizmet verir.
- JMX-Kafka101, JMX-Kafka102, JMX-Kafka103: Bu servisler, Prometheus’un Kafka’dan JMX sorgulamalarını gerçekleştirmesini sağlar. Her bir JMX servisi, bir Kafka servisine bağımlıdır ve her biri farklı bir porttan hizmet verir.
- Kafka101, Kafka102, Kafka103: Bu servisler, Kafka brokerleridir.
Docker-compose dosyasını hızlıca inceledik. Şimdi de yapılandırma dosyalarını gözden geçirip görselleştirmeye başlayalım.
JMX ile Prometheus – Kafka Bağlantısını Kurma
Prometheus ile Kafka arasında bağlantı kurmak için jmx-exporter‘ı kullanıyoruz. Parametrelerin Prometheus tarafından kullanılabilmesi için konfigürasyon dosyasını jmx konteynerına eklememiz gerekmektedir.
- hostPort: Metriklerin alınacağı hedefin adresi ve portu belirlenir. Bu örnekte, metrikler
kafka101hostunun9991portundan alınır. Diğer konteynerlara erişim sağlamak için bu bölümü güncellememiz gerekmektedir. - lowercaseOutputName ve lowercaseOutputLabelNames: Bu ayarlar, metrik ve etiket isimlerinin küçük harfle çıktı olarak verilmesini sağlar. Bu, tutarlılık sağlamak ve karmaşayı azaltmak amacıyla yapılmaktadır.
- whitelistObjectNames ve blacklistObjectNames: Bu bölümler, hangi JMX nesnelerinin (ObjectName) metriklere dahil edileceğini veya hariç bırakılacağını belirtir.
whitelistObjectNamesbelirli nesneleri dahil ederken,blacklistObjectNamesbelirli nesneleri hariç tutar. Özellikle, belirli bir ön ek veya deseni içeren nesneleri filtrelemek için kullanılır. - rules: Bu bölüm, toplanan metrikler üzerinde işlem yapmak için Prometheus kurallarını tanımlar. Örneğin, metrik isimlerini yeniden adlandırmak, etiketler eklemek veya kaldırmak, metrik değerlerini dönüştürmek veya toplamak gibi işlemler gerçekleştirilebilir. Her kuralın altında, bir
pattern(desen) belirtilir ve bu desen, eşleşen metrikler üzerinde işlem yapmak için kullanılır. Daha sonra, işlem yapılan metriğin adı (name) ve etiketleri (labels) belirtilir. Bu örnekte,Broker MetricsveJVM Metricsolmak üzere iki kural tanımlanmıştır. Her bir kuralın altında, desen, metrik adı ve etiketler belirtilmiştir. Örneğin, CPU kullanımı için bir kural tanımlanmış ve bu kuralınpattern‘ıjava.lang<type=OperatingSystem><ProcessCpuLoad>olarak belirlenmiştir. Bu desen, CPU kullanım metriklerini temsil eder. Daha sonra, bu metriğin Prometheus’ta nasıl adlandırılacağı (name) ve hangi etiketlerle (labels) işaretleneceği belirlenmiştir.
hostPort: kafka101:9991
lowercaseOutputName: true
lowercaseOutputLabelNames: true
# Whitelist is used to reduce scrapping time
whitelistObjectNames:
- java.lang:*
- kafka.cluster:*
- kafka.controller:*
- kafka.log:*
- kafka.server:type=KafkaServer,name=BrokerState
- kafka.server:type=KafkaRequestHandlerPool,*
- kafka.server:type=BrokerTopicMetrics,*
- kafka.server:type=FetcherLagMetrics,*
- kafka.server:type=FetcherStats,*
- kafka.server:type=Request,*
- kafka.server:type=Fetch,*
- kafka.server:type=Produce,*
- kafka.server:type=ReplicaManager,*
- kafka.server:type=ReplicaFetcherManager,*
- kafka.server:type=SessionExpireListener,*
- kafka.server:type=controller-channel-metrics,*
- kafka.server:type=socket-server-metrics,*
- kafka.network:type=RequestChannel,*
- kafka.network:type=Processor,*
- kafka.network:type=SocketServer,*
- kafka.network:type=RequestMetrics,*
- kafka.coordinator.group:*
blacklistObjectNames:
- java.lang:type=ClassLoading,*
- java.lang:type=Compilation,*
- java.lang:type=MemoryManager,*
- kafka.utils:*
- kafka.controller:type=ControllerChannelManager,name=QueueSize,*
# Following metrics are exposed per topics
- kafka.log:type=Log,name=LogEndOffset,*
- kafka.log:type=Log,name=LogStartOffset,*
- kafka.cluster:type=Partition,name=InSyncReplicasCount,*
- kafka.cluster:type=Partition,name=LastStableOffsetLag,*
- kafka.cluster:type=Partition,name=ReplicasCounts,*
- kafka.cluster:type=Partition,name=UnderReplicated,*
- kafka.server:type=BrokerTopicMetrics,name=TotalFetchRequestsPerSec,*
- kafka.server:type=BrokerTopicMetrics,name=TotalProduceRequestsPerSec,*
- kafka.server:type=BrokerTopicMetrics,name=FailedProduceRequestsPerSec,*
- kafka.server:type=BrokerTopicMetrics,name=FailedFetchRequestsPerSec,*
- kafka.server:type=BrokerTopicMetrics,name=BytesRejectedPerSec,*
rules:
#-------------------------------------------------------------------------------------------------------
# Broker Metrics :
#-------------------------------------------------------------------------------------------------------
# Total Topic Count
- pattern: kafka.server<type=BrokerTopicMetrics, name=Topics><>Value
name: kafka_server_broker_topic_count
labels:
service: kafka-broker
env: cluster-demo
# Total Message Count
- pattern: kafka.server<type=BrokerTopicMetrics, name=MessagesInPerSec><>OneMinuteRate
name: kafka_server_broker_total_messages_per_sec
labels:
aggregate: one_minute_rate
service: kafka-broker
env: cluster-demo
# Total Partition Count
- pattern: kafka.cluster<type=Partition, name=([^,]+), topic=([^,]+), partition=([^,]+)><>Value
name: kafka_cluster_partition_$1
labels:
topic: $2
partition: $3
service: kafka-broker
env: cluster-demo
#-------------------------------------------------------------------------------------------------------
# JVM Metrics :
#-------------------------------------------------------------------------------------------------------
# CPU Usage
- pattern: java.lang<type=OperatingSystem><ProcessCpuLoad>
name: kafka_jvm_os_process_cpu_load
labels:
service: kafka-broker
env: cluster-demo
# RAM Usage
- pattern: java.lang<type=OperatingSystem><TotalPhysicalMemorySize>
name: kafka_jvm_os_total_physical_memory_size
labels:
service: kafka-broker
env: cluster-demo
# Heap Memory Usage
- pattern: java.lang<type=Memory><HeapMemoryUsage>(\w*)
name: kafka_jvm_heap_usage
labels:
type: $1
service: kafka-broker
env: cluster-demo
attrNameSnakeCase: true
# Non-Heap Memory Usage
- pattern: java.lang<type=Memory><NonHeapMemoryUsage>(\w*)
name: kafka_jvm_non_heap_usage
labels:
type: $1
service: kafka-broker
env: cluster-demo
attrNameSnakeCase: trueArdından, prometheus.yml dosyasını oluşturuyoruz. Bu dosya, Prometheus’un yapılandırma dosyasıdır ve Prometheus’un hangi metrikleri, ne sıklıkta ve nereden toplayacağını tanımlar.
- Global Ayarlar: Bu bölüm, tüm scrape işlemleri ve kural değerlendirmeleri için genel ayarları tanımlar. Örneğin, scrape aralığı (
scrape_interval) ve kural değerlendirme aralığı (evaluation_interval) burada belirtilir. Örneğin, her 15 saniyede bir metrik alınması ve kuralların her 15 saniyede bir değerlendirilmesi belirtilir. - Alertmanager Yapılandırması: Bu bölüm, Alertmanager yapılandırmasını belirtir. Alertmanager, Prometheus’tan gelen uyarıları yönetmek ve bunlara yanıt vermek için kullanılır. Ancak,
targetsbölümü boş olduğu için herhangi bir Alertmanager hedefi belirtilmemiştir. - Kuralların Yüklenmesi: Bu bölüm, Prometheus’un yükleyeceği kural dosyalarını belirtir. Ancak, kural dosyaları yorumlanmış (
#işaretiyle başlıyor) olduğu için herhangi bir kural dosyası yüklenmeyecektir. - Scrape Yapılandırmaları: Bu bölüm, Prometheus’un metrikleri toplayacağı hedefleri belirtir. Her scrape yapılandırması, bir “job” adı altında gruplandırılmış hedefler listesi içerir. Bu örnekte, “kafka” adında bir job tanımlanmış ve bu job’un metrikleri toplayacağı hedefler (
targets) belirtilmiştir. Bu hedefler,jmx-kafka101:5556,jmx-kafka102:5556vejmx-kafka103:5556adreslerindeki Kafka sunucularıdır.
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'kafka'
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ['jmx-kafka101:5556','jmx-kafka102:5556', 'jmx-kafka103:5556']Grafana Prometheus bağlantısı
Görselleştirmeleri yapabilmek için veri kaynağı olarak Prometheus eklememiz gerekiyor. Home> Administration > Data sources > Add data source adımlarını izleyerek Prometheus’u veri kaynağı olarak ekleyebilirsiniz.

Bu bağlantıyı, arayüzden olduğu gibi, yapılandırma dosyası ile de gerçekleştirebiliriz. Aşağıda bir örnek yapılandırma dosyasını bulabilirsiniz. Oluşturduğumuz datasource.yaml dosyasını /etc/grafana/provisioning/datasources dizinine kopyalayarak bağlantıyı sağlayabiliriz.
- apiVersion: Bu, yapılandırma dosyasının format sürümünü belirtir.
- deleteDatasources: Bu bölüm, silinecek veri kaynaklarını belirtir.
- datasources: Bu bölüm, eklenecek veya güncellenecek veri kaynaklarını belirtir. Her bir veri kaynağı için aşağıdaki bilgiler gerekir:
- name: Veri kaynağının adı.
- type: Veri kaynağının türü.
- access: Erişim modu.
- orgId: Veri kaynağının ait olduğu organizasyonun ID’si.
- url: Sunucu adresi.
- password: Kullanılacak şifre, eğer varsa.
- user: Kullanıcı adı, eğer varsa.
- database: Veritabanı adı, eğer varsa.
- basicAuth, basicAuthUser, basicAuthPassword: Temel kimlik doğrulama bilgileri, eğer kullanılacaksa.
- withCredentials: Başlıklarda kimlik bilgilerini etkinleştir veya devre dışı bırak.
- isDefault: Bu veri kaynağının varsayılan olup olmadığını belirtir, eğer varsa.
- jsonData: JSON formatında saklanacak alanlar.
- secureJsonData: Şifreli JSON verisi, örneğin TLS sertifikaları gibi.
- version: Yapılandırma sürümü.
- editable: Kullanıcıların UI’den veri kaynağını düzenleyip düzenleyemeyeceğini belirtir.
# config file version
apiVersion: 1
# list of datasources that should be deleted from the database
deleteDatasources:
- name: Prometheus
orgId: 1
# list of datasources to insert/update depending on
# what's available in the database
datasources:
# <string, required> name of the datasource. Required
- name: Prometheus
# <string, required> datasource type. Required
type: prometheus
# <string, required> access mode. proxy or direct (Server or Browser in the UI). Required
access: proxy
# <int> org id. will default to orgId 1 if not specified
orgId: 1
# <string> url
url: http://prometheus:9090
# <string> database password, if used
password:
# <string> database user, if used
user:
# <string> database name, if used
database:
# <bool> enable/disable basic auth
basicAuth:
# <string> basic auth username
basicAuthUser:
# <string> basic auth password
basicAuthPassword:
# <bool> enable/disable with credentials headers
withCredentials:
# <bool> mark as default datasource. Max one per org
isDefault: true
# <map> fields that will be converted to json and stored in json_data
jsonData:
httpMethod: POST
manageAlerts: true
prometheusType: Prometheus
prometheusVersion: 2.47.0
cacheLevel: 'High'
tlsAuth: false
tlsAuthWithCACert: false
# <string> json object of data that will be encrypted.
secureJsonData:
tlsCACert: "..."
tlsClientCert: "..."
tlsClientKey: "..."
version: 1
# <bool> allow users to edit datasources from the UI.
editable: true
Grafana ile Grafik Oluşturma
Grafana ile çeşitli görselleştirmeler oluşturabiliriz. Veri analizi ve izleme için ideal bir araç olan Grafana, çeşitli grafikler, histogramlar, ısı haritaları ve daha fazlasını oluşturmamıza olanak sağlar. Veriye dayalı uyarıları oluşturabilir ve bu uyarıları e-posta, Slack gibi platformlara yönlendirebiliriz. Ayrıca, karmaşık sorguları kaydederek daha sonraki kullanımlar için saklayabiliriz.
Şimdi bir grafik oluşturmayı birlikte deneyelim. İlk olarak, yeni bir dashboard oluşturmalıyız. Bu adımları takip edebiliriz: Home > Dashboards > New Dashboard. Sonra, ‘Add new panel’ seçeneğini tıklayarak yeni bir grafik başlatabiliriz. Grafik oluştururken, veri kaynağını seçmeli ve bir sorgu yazmalıyız. Sorgu, grafikte neyin gösterileceğini belirler. Örneğin, belirli bir zaman aralığındaki bir metriğin değerlerini gösterebiliriz. Daha sonra, grafik türünü seçip, grafik ayarlarını özelleştirebiliriz. Tüm bu adımlar tamamlandığında, ‘Apply’ düğmesine tıklayarak grafik panelini dashboard’a ekleyebiliriz.

Örneğin, ortalama bellek kullanımını gözlemlemek için bir grafik oluşturalım. İlk olarak, grafikte göstermek istediğimiz verinin kaynağını belirleriz. Kaynağı belirledikten sonra, verinin nasıl gösterileceğini belirleyen sorguyu yazmamız gerekiyor. Sonra, oluşturduğumuz grafiğe bir isim verelim ve bu ismi sol paneldeki ilgili alana giriyoruz. Aynı panelde, hangi tür verinin nasıl bir formatla gösterileceğini belirleyen grafik türünün özelliklerini de ayarlayabilirz. Ayarlar tamamlandıktan sonra, ‘kaydet’ butonuna basıyourz burada bize hangi panoya eklemek istediğimiz soracak. Son olarak, grafiği hangi panoya eklemek istediğimizi belirleyip grafiği kayıt ediyoruz.

Bu yazıda Prometheus ve Grafana’nın karmaşık izleme görevlerini nasıl basitleştirdiğini gördük ve Kafka kümesinin izlenme sürecini anlattık ve bu araçların birlikte nasıl çalıştığını açıkladık. Herkese keyifli okumalar dilerim, bir sonraki yazıda görüşmek üzere.
Kaynaklar: