Küme gözlemlenebilirliği: Prometheus, Grafana ve OpenTelemetry
“Ölçemezseniz yönetemezsiniz.” Üretim Kubernetes kümesi için bu üç boyutta görünürlüğe sahip olmak anlamına gelir: ölçümler (her birini ne kadar tüketiyor bileşen), kayıt (sistemde neler oluyor), e iz (isteklerin mikro hizmetlerde nasıl ilerlediği). Prometheus + Grafana + yığını Loki + OpenTelemetry bu ihtiyaca açık kaynaklı cevaptır.
Bu makalede Kubernetes için eksiksiz bir gözlemlenebilirlik yığını oluşturacağız: kube-prometheus-yığın altyapı metrikleri için yapılandıracağız Loki toplu günlükler için entegre edeceğiz OpenTelemetry Toplayıcı uygulamalar tarafından dağıtılan izleri toplamak ve bunları Tempo'ya (arka uç) iletmek için Grafana takibi). Sonuç, birleşik bir gözlemlenebilirlik platformudur Grafana'da görüntülenir.
Ne Öğreneceksiniz
- kube-prometheus-stack'ı yükleyin: Prometheus Operatörü, kube-state-metrics, Node Exporter
- Otomatik uygulama kazıma için ServiceMonitor ve PodMonitor oluşturun
- Kritik küme uyarıları için PrometheusRule (OOMKill, CrashLoopBackOff, vb.)
- Kubernetes etiketleriyle birleştirilmiş günlükler için Loki + Promtail
- OpenTelemetry Collector - Yapılandırılabilir telemetri hattı
- Dağıtılmış izleme için Grafana Tempo
- Kubernetes için önceden oluşturulmuş Grafana kontrol panelleri
- Grafana'da metrik-log-iz korelasyonu (Örnekler)
Gözlemlenebilirlik Yığınının Mimarisi
Kurulumdan önce bileşenlerin birbirleriyle nasıl ilişkili olduğunu anlayalım:
- Prometheus: HTTP kazımayla ölçümleri toplayın. Verileri 15-30 gün boyunca saklayın
- kube-durum-metrikleri: K8s nesnelerinin (Dağıtım, Pod vb.) durumuna ilişkin ölçümleri ortaya çıkarır.
- Düğüm Aktarıcısı: Düğüm donanım ölçümlerini (CPU, disk, ağ) ortaya çıkarır
- Loki: Pod günlüklerini toplayın. İçeriği indekslemez, sadece etiketleri indeksler
- Promtail: Konteyner günlüklerini Loki'ye gönderen DaemonSet
- OpenTelemetry Toplayıcı: Uygulamalardan izleri/ölçümleri/günlükleri alır ve bunları arka uçlara yönlendirir
- Grafana Saati: Dağıtılmış izleme için arka uç (izler)
- Grafana: Metrikleri (Prometheus), günlüğü (Loki), izlemeyi (Tempo) görüntülemek için birleştirilmiş kullanıcı arayüzü
kube-prometheus-stack'ın kurulması
# Installa kube-prometheus-stack (include Prometheus, Alertmanager, Grafana, kube-state-metrics, Node Exporter)
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# values.yaml per produzione
cat > kube-prometheus-values.yaml << 'EOF'
# Prometheus
prometheus:
prometheusSpec:
retention: 30d
retentionSize: "50GB"
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: ssd
resources:
requests:
storage: 100Gi
# Scrape tutte le ServiceMonitor/PodMonitor nel cluster
serviceMonitorSelectorNilUsesHelmValues: false
podMonitorSelectorNilUsesHelmValues: false
ruleSelectorNilUsesHelmValues: false
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
cpu: 2000m
memory: 8Gi
# Alertmanager
alertmanager:
alertmanagerSpec:
storage:
volumeClaimTemplate:
spec:
storageClassName: ssd
resources:
requests:
storage: 10Gi
config:
global:
slack_api_url: "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
route:
receiver: 'slack-critical'
group_wait: 30s
group_interval: 5m
repeat_interval: 12h
routes:
- receiver: 'slack-critical'
matchers:
- alertname =~ ".*Critical.*"
- receiver: 'slack-warning'
matchers:
- severity = warning
receivers:
- name: 'slack-critical'
slack_configs:
- channel: '#alerts-critical'
send_resolved: true
title: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}'
text: '{{ range .Alerts }}{{ .Annotations.summary }}{{ end }}'
- name: 'slack-warning'
slack_configs:
- channel: '#alerts-warning'
send_resolved: true
# Grafana
grafana:
enabled: true
ingress:
enabled: true
hosts:
- grafana.company.com
persistence:
enabled: true
size: 10Gi
# Datasource Loki pre-configurato
additionalDataSources:
- name: Loki
type: loki
url: http://loki.monitoring.svc:3100
jsonData:
derivedFields:
- datasourceUid: tempo
matcherRegex: '"traceID":"(\w+)"'
name: TraceID
url: '${__value.raw}'
- name: Tempo
type: tempo
url: http://tempo.monitoring.svc:3100
# kube-state-metrics
kube-state-metrics:
metricLabelsAllowlist:
- pods=[team,environment,app]
- deployments=[team,environment,app]
EOF
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--version 65.0.0 \
-f kube-prometheus-values.yaml
# Verifica
kubectl get pods -n monitoring
kubectl get servicemonitors -A
Uygulama Kazıma için ServiceMonitor
Prometheus Operatörünün kullandığı Servis Monitörü e PodMonitör Uygulama metriklerinin kazınmasını dinamik olarak yapılandırmak için. Hiçbir faydası yok Prometheus yapılandırmasını değiştirin:
# servicemonitor-api-service.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: api-service-monitor
namespace: team-alpha-production
labels:
team: team-alpha # label per selezionare questo monitor
spec:
selector:
matchLabels:
app: api-service # seleziona il Service con questo label
endpoints:
- port: metrics # nome della porta nel Service
interval: 30s
path: /metrics
# Basic auth se le metriche sono protette
# basicAuth:
# username: { name: metrics-auth, key: username }
# password: { name: metrics-auth, key: password }
namespaceSelector:
matchNames:
- team-alpha-production
---
# Aggiungi la porta metrics al Service dell'applicazione
apiVersion: v1
kind: Service
metadata:
name: api-service
namespace: team-alpha-production
labels:
app: api-service
spec:
selector:
app: api-service
ports:
- name: http
port: 8080
- name: metrics # porta dedicata alle metriche
port: 9090
targetPort: 9090
Küme Kritik Uyarısı
# prometheusrule-kubernetes-alerts.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: kubernetes-critical-alerts
namespace: monitoring
labels:
prometheus: kube-prometheus
spec:
groups:
- name: kubernetes.critical
rules:
# Pod in CrashLoopBackOff
- alert: PodCrashLoopBackOff
expr: |
rate(kube_pod_container_status_restarts_total[15m]) > 0
AND
kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff"} == 1
for: 5m
labels:
severity: critical
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} in CrashLoopBackOff"
# Pod OOMKilled
- alert: PodOOMKilled
expr: |
kube_pod_container_status_last_terminated_reason{reason="OOMKilled"} == 1
for: 0m
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} terminato per OOM"
description: "Aumenta i memory limits del container {{ $labels.container }}"
# Nodo sotto pressione di memoria
- alert: NodeMemoryPressure
expr: kube_node_status_condition{condition="MemoryPressure",status="true"} == 1
for: 2m
labels:
severity: critical
annotations:
summary: "Nodo {{ $labels.node }} sotto MemoryPressure"
# PVC quasi pieno
- alert: PersistentVolumeFillingUp
expr: |
kubelet_volume_stats_available_bytes /
kubelet_volume_stats_capacity_bytes < 0.15
for: 5m
labels:
severity: warning
annotations:
summary: "PVC {{ $labels.namespace }}/{{ $labels.persistentvolumeclaim }} al 85% della capacita"
# Deployment con zero repliche disponibili
- alert: DeploymentUnavailable
expr: kube_deployment_status_replicas_available == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Deployment {{ $labels.namespace }}/{{ $labels.deployment }} ha 0 repliche disponibili"
Toplu Günlükler için Loki + Promtail
# Installa Loki (modalita monolitica per cluster medio)
helm repo add grafana https://grafana.github.io/helm-charts
helm install loki grafana/loki \
--namespace monitoring \
--set loki.commonConfig.replication_factor=1 \
--set loki.storage.type=filesystem \
--set singleBinary.replicas=1 \
--set monitoring.selfMonitoring.enabled=false
# Installa Promtail (DaemonSet che invia log a Loki)
helm install promtail grafana/promtail \
--namespace monitoring \
--set config.clients[0].url=http://loki.monitoring.svc:3100/loki/api/v1/push \
--set config.snippets.extraScrapeConfigs='
- job_name: kubernetes-pods
kubernetes_sd_configs:
- role: pod
pipeline_stages:
- cri: {}
- labeldrop:
- filename
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_team]
target_label: team
- source_labels: [__meta_kubernetes_pod_label_app]
target_label: app
- source_labels: [__meta_kubernetes_namespace]
target_label: namespace'
# Query Loki in Grafana (LogQL):
# Tutti i log error del team-alpha:
# {namespace="team-alpha-production"} |= "ERROR"
# Error rate per app negli ultimi 5 minuti:
# sum(rate({namespace="team-alpha-production"} |= "ERROR" [5m])) by (app)
# Log strutturati JSON - estrai campo:
# {app="api-service"} | json | level="error" | line_format "{{.message}}"
Dağıtılmış İzler için OpenTelemetry Toplayıcı
# Installa OpenTelemetry Operator
kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/latest/download/opentelemetry-operator.yaml
---
# otel-collector.yaml - pipeline di telemetria
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: otel-collector
namespace: monitoring
spec:
mode: DaemonSet # un collector per nodo
config:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 1s
send_batch_size: 1024
# Aggiunge metadati Kubernetes ai trace (namespace, pod name, etc.)
k8sattributes:
auth_type: "serviceAccount"
passthrough: false
extract:
metadata:
- k8s.pod.name
- k8s.namespace.name
- k8s.deployment.name
- k8s.node.name
labels:
- tag_name: team
key: team
from: pod
# Campionamento: mantieni solo 10% dei trace in produzione (volume alto)
probabilistic_sampler:
sampling_percentage: 10
exporters:
otlp/tempo:
endpoint: http://tempo.monitoring.svc:4317
tls:
insecure: true
prometheus:
endpoint: "0.0.0.0:8889"
const_labels:
cluster: production
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch, k8sattributes, probabilistic_sampler]
exporters: [otlp/tempo]
metrics:
receivers: [otlp]
processors: [batch, k8sattributes]
exporters: [prometheus]
Grafana Tempo'nun kurulumu
# Installa Grafana Tempo
helm install tempo grafana/tempo-distributed \
--namespace monitoring \
--set storage.trace.backend=local
# Alternativa: Tempo monolitico per cluster piccoli/medi
helm install tempo grafana/tempo \
--namespace monitoring \
--set tempo.storage.trace.backend=filesystem \
--set tempo.storage.trace.local.path=/var/tempo
Kubernetes için Grafana kontrol paneli
Grafana'nın önceden oluşturulmuş gösterge tablolarından oluşan bir kataloğu vardır. Bu kimlikleri kullanıcı arayüzünden içe aktarın (Kontrol Panelleri > İçe Aktar):
| Gösterge tabloları | Kimlik Grafana | Yardımcı Program |
|---|---|---|
| Kubernetes Kümesine Genel Bakış | 7249 | Düğüme göre CPU/Bellek/Pod Genel Bakış |
| Kubernetes Dağıtımları | 8588 | Dağıtım durumu, yeniden başlatma oranı, replikalar |
| Düğüm Aktarıcı Dolu | 1860 | Düğüm donanım ölçümleri (CPU, disk, ağ) |
| Kubernetes PVC | 13646 | PVC depolama kullanımı |
| Loki Kontrol Paneli | 15141 | Günlükleri toplama, hata oranı, günlük gezgini |
| NGINX Giriş Denetleyicisi | 9614 | İstek oranı, gecikme, giriş durum kodu |
Metrik-Log-İzleme Korelasyonu (Örnekler)
Bu yığının gerçek gücü korelasyon: bir ölçümden yüksek gecikme süresiyle doğrudan ilgili izlemeye ve izlemeden günlüklere gidebilirsiniz o zaman Pod'un. Buna denir Örnek niteliğinde:
# Abilita gli exemplar in Prometheus (già abilitati in kube-prometheus-stack)
# Nell'applicazione, includi il traceID nell'histogram metric:
# Go/Python con OpenTelemetry:
# Quando crei un histogram, aggiungi l'exemplar con il trace ID corrente
# Il Prometheus scraper lo raccoglie e lo conserva
# In Grafana:
# 1. Vai alla dashboard API latency
# 2. Vedi un picco di latenza
# 3. Clicca il diamante (exemplar) sul grafico
# 4. Grafana ti apre automaticamente il trace in Tempo
# 5. Dal trace, clicca sul servizio con errore
# 6. Grafana mostra i log di quel Pod in Loki per quel timestamp
# Questo flusso metriche → trace → log e il "holy grail" dell'osservabilita
Kubernetes Gözlemlenebilirliği için En İyi Uygulamalar
Üretim Gözlemlenebilirliği Kontrol Listesi
- Kaynaklar için KULLANIM Yöntemi: Her kaynak için (CPU, bellek, disk, ağ): Kullanım, Doygunluk, Hatalar. Bunlar her düğüm için 3 temel uyarıdır
- Hizmetler için KIRMIZI Yöntem: Her hizmet için: Hız (talep/s), Hatalar (hata oranı), Süre (gecikme). Üçüne de uyarı
- SLO tabanlı uyarı: Her anormallik konusunda uyarı vermeyin; yalnızca SLO hata bütçenizi kullandığınızda uyarı verin. Daha az gürültü, daha fazla sinyal
- Farklılaştırılmış tutma: Ham ölçümler 15 gün, aylık toplamlar 1 yıldır. Ham günlük 7 gün, denetim günlüğü 1 yıl
- Parçalar için örnekleme: İzlerin %100'ünü üretimde tutmayın; bunun maliyeti çok yüksektir. Hata ayıklama için %1-10 yeterlidir
- Tutarlı etiketler: Filtreleme için her ölçüm, günlük ve izlemenin ekibi, ortamı, uygulaması ve sürümü bulunmalıdır
Sonuçlar ve Sonraki Adımlar
Eksiksiz bir gözlemlenebilirlik yığını — Metrikler için Prometheus, günlükler için Loki, OpenTelemetry + Trace Time — Kubernetes'i kara kutudan bir sisteme dönüştürür anlaşılabilir. Grafana'daki üç sinyal arasındaki korelasyon, zamanı büyük ölçüde azaltır Saatlerden dakikalara kadar ortalama hata ayıklama.
Bu serideki bir sonraki ve son makale — Federasyon e ile Kubernetes Çoklu Bulut Submariner — sanki farklı bulut sağlayıcıları arasında birden fazla kümeyi yönetme zorluğunu ele alıyor bu serinin tüm konseptlerini çoklu kümeye genişleten tek bir ürün vardı.
Serinin bir sonraki makalesi
İlgili Seriler
- Gözlemlenebilirlik ve Açık Telemetri — uygulama enstrümantasyonunun derinlemesine analizi
- ArgoCD ile GitOps — Argo Rollouts, otomatik kanarya analizi için Prometheus'u kullanıyor







