InfluxDB ile Kubernetes Cluster İzleme ve Metrik Yönetimi

Kubernetes cluster’ınızı izlemek, production ortamında hayatta kalmanın temel koşullarından biri. Pod’lar crash oluyor, node’lar dolup taşıyor, servisler cevap vermiyor ve siz bunları gerçek zamanlı göremiyorsanız, sabahın 3’ünde bir Slack bildirimi yerine müşteri şikayetiyle uyanan türden birisiniz demektir. InfluxDB, zaman serisi verilerini depolamak için tasarlanmış yapısıyla Kubernetes metriklerini toplamak ve analiz etmek için oldukça güçlü bir seçenek sunar. Bu yazıda, InfluxDB’yi Kubernetes cluster’ınıza entegre edecek, Telegraf ile metrikleri toplayacak ve anlamlı sorgular yazacaksınız.

Neden InfluxDB?

Prometheus + Grafana ikilisi Kubernetes monitoring için çok yaygın kullanılır ve harika bir çözümdür. Ancak InfluxDB’nin bazı avantajları vardır. InfluxQL ve Flux sorgu dilleri ile karmaşık zaman serisi analizleri yapmak daha sezgiseldir. Yüksek yazma hızlarında performans kaybı yaşanmaz. InfluxDB 2.x ile gelen built-in dashboard’lar, Grafana olmadan da temel görselleştirme yapmanıza izin verir. Öte yandan InfluxDB Cloud ile on-premise kurulumu arasında geçiş yapmak oldukça kolaydır.

Gerçek dünya senaryosu olarak şunu düşünün: 15 node’lu, 200’den fazla pod çalıştıran bir e-ticaret platformu yönetiyorsunuz. Black Friday yaklaşıyor ve her metriğin anlık olarak izlenmesi gerekiyor. Prometheus’un retention policy’si dolmuş, eski verileri sorgulamak için ayrı bir sistem kurmak istemiyorsunuz. InfluxDB bu noktada uzun dönem retention ve downsampling özellikleriyle devreye giriyor.

Ortam Gereksinimleri

Kuruluma geçmeden önce neye ihtiyacınız olduğunu netleştirelim.

  • Çalışan bir Kubernetes cluster (en az 1.20+)
  • kubectl erişimi ve admin yetkileri
  • Helm 3.x kurulu
  • En az 4GB RAM ve 2 CPU’ya sahip bir node (InfluxDB için)
  • Persistent Volume desteği (storageClass tanımlı olmalı)

InfluxDB’yi Kubernetes’e Kurma

Helm Repository Ekleme

InfluxDB’nin resmi Helm chart’ını kullanacağız. Bu hem kurulumu kolaylaştırır hem de güncellemeleri yönetmeyi basitleştirir.

helm repo add influxdata https://helm.influxdata.com/
helm repo update
helm search repo influxdata/influxdb2

Bu komutun çıktısında mevcut chart versiyonlarını göreceksiniz. Şu an için 2.x branch’ini kullanmanızı öneririm çünkü InfluxDB 2.x, built-in UI, token tabanlı kimlik doğrulama ve Flux sorgu dili gibi kritik özellikler sunuyor.

Namespace Oluşturma

Monitoring bileşenlerini ayrı bir namespace altında toplamak, RBAC yönetimi ve kaynak izolasyonu açısından büyük kolaylık sağlar.

kubectl create namespace monitoring
kubectl label namespace monitoring purpose=monitoring

InfluxDB Values Dosyası Hazırlama

Varsayılan değerlerle kurulum yapmak yerine, production’a uygun bir values dosyası oluşturalım.

# influxdb-values.yaml
image:
  repository: influxdb
  tag: 2.7.1-alpine
  pullPolicy: IfNotPresent

persistence:
  enabled: true
  storageClass: "standard"
  accessMode: ReadWriteOnce
  size: 50Gi

resources:
  requests:
    memory: "2Gi"
    cpu: "500m"
  limits:
    memory: "4Gi"
    cpu: "2000m"

adminUser:
  organization: "k8s-monitoring"
  bucket: "kubernetes"
  user: "admin"
  password: "guclu-bir-sifre-koyun"
  token: "uzun-ve-rastgele-bir-token-buraya"

service:
  type: ClusterIP
  port: 8086

ingress:
  enabled: true
  className: nginx
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
  hostname: influxdb.your-domain.com
  tls: true

livenessProbe:
  path: "/health"
  scheme: "HTTP"
  initialDelaySeconds: 30

readinessProbe:
  path: "/ready"
  scheme: "HTTP"
  initialDelaySeconds: 5

Şimdi bu dosyayla kurulumu gerçekleştirelim.

helm upgrade --install influxdb influxdata/influxdb2 
  --namespace monitoring 
  --values influxdb-values.yaml 
  --wait 
  --timeout 10m

Kurulum tamamlandıktan sonra pod’un ayağa kalktığını doğrulayın.

kubectl get pods -n monitoring -l app.kubernetes.io/name=influxdb2
kubectl logs -n monitoring -l app.kubernetes.io/name=influxdb2 --tail=50

Telegraf ile Kubernetes Metriklerini Toplama

InfluxDB yalnızca veri depolar. Metrikleri toplamak için Telegraf kullanacağız. Telegraf, InfluxData ekosisteminin bir parçası ve yüzlerce input plugin’e sahip bir metrik toplayıcı.

Kubernetes ortamında Telegraf’ı DaemonSet olarak deploy edeceğiz. Bu şekilde her node üzerinde bir Telegraf pod’u çalışır ve o node’a ait metrikleri toplar.

RBAC Yetkilendirmesi

Telegraf’ın Kubernetes API’sine erişebilmesi için gerekli yetkileri tanımlamamız gerekiyor.

# telegraf-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: telegraf
  namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: telegraf
rules:
  - apiGroups: [""]
    resources:
      - nodes
      - nodes/proxy
      - nodes/metrics
      - services
      - endpoints
      - pods
      - namespaces
    verbs: ["get", "list", "watch"]
  - apiGroups: ["extensions", "apps"]
    resources:
      - deployments
      - replicasets
      - daemonsets
      - statefulsets
    verbs: ["get", "list", "watch"]
  - nonResourceURLs: ["/metrics", "/metrics/cadvisor"]
    verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: telegraf
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: telegraf
subjects:
  - kind: ServiceAccount
    name: telegraf
    namespace: monitoring
kubectl apply -f telegraf-rbac.yaml

Telegraf ConfigMap

Telegraf konfigürasyonu bir ConfigMap olarak saklanacak. Bu yapı, konfigürasyon değişikliklerini pod’ları yeniden oluşturmadan uygulamanıza imkan tanır (elbette pod restart gerekir ama image yeniden çekilmez).

# telegraf-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: telegraf-config
  namespace: monitoring
data:
  telegraf.conf: |
    [agent]
      interval = "30s"
      round_interval = true
      metric_batch_size = 1000
      metric_buffer_limit = 10000
      collection_jitter = "5s"
      flush_interval = "30s"
      flush_jitter = "5s"
      precision = ""
      hostname = "$HOSTNAME"
      omit_hostname = false

    [[outputs.influxdb_v2]]
      urls = ["http://influxdb-influxdb2.monitoring.svc.cluster.local:8086"]
      token = "$INFLUXDB_TOKEN"
      organization = "k8s-monitoring"
      bucket = "kubernetes"

    [[inputs.kubernetes]]
      url = "https://$HOSTIP:10250"
      bearer_token = "/var/run/secrets/kubernetes.io/serviceaccount/token"
      insecure_skip_verify = true

    [[inputs.kube_inventory]]
      url = "https://kubernetes.default.svc"
      bearer_token = "/var/run/secrets/kubernetes.io/serviceaccount/token"
      insecure_skip_verify = true
      namespace = ""
      resource_include = ["deployments", "endpoints", "ingress",
                          "nodes", "pods", "services", "statefulsets"]

    [[inputs.cpu]]
      percpu = true
      totalcpu = true
      collect_cpu_time = false
      report_active = false

    [[inputs.disk]]
      ignore_fs = ["tmpfs", "devtmpfs", "devfs", "iso9660", "overlay", "aufs", "squashfs"]

    [[inputs.diskio]]

    [[inputs.mem]]

    [[inputs.net]]

    [[inputs.processes]]

    [[inputs.system]]

Telegraf DaemonSet

# telegraf-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: telegraf
  namespace: monitoring
  labels:
    app: telegraf
spec:
  selector:
    matchLabels:
      app: telegraf
  template:
    metadata:
      labels:
        app: telegraf
    spec:
      serviceAccountName: telegraf
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          operator: Exists
          effect: NoSchedule
        - key: node-role.kubernetes.io/master
          operator: Exists
          effect: NoSchedule
      containers:
        - name: telegraf
          image: telegraf:1.28-alpine
          resources:
            requests:
              memory: "256Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "500m"
          env:
            - name: HOSTNAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: HOSTIP
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: INFLUXDB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: influxdb-token
                  key: token
          volumeMounts:
            - name: telegraf-config
              mountPath: /etc/telegraf
            - name: proc
              mountPath: /rootfs/proc
              readOnly: true
            - name: sys
              mountPath: /rootfs/sys
              readOnly: true
            - name: docker-socket
              mountPath: /var/run/docker.sock
              readOnly: true
          securityContext:
            privileged: true
      volumes:
        - name: telegraf-config
          configMap:
            name: telegraf-config
        - name: proc
          hostPath:
            path: /proc
        - name: sys
          hostPath:
            path: /sys
        - name: docker-socket
          hostPath:
            path: /var/run/docker.sock
      hostNetwork: false
      hostPID: true

InfluxDB token’ını Secret olarak oluşturun.

kubectl create secret generic influxdb-token 
  --from-literal=token="uzun-ve-rastgele-bir-token-buraya" 
  --namespace monitoring

Tüm kaynakları uygulayın.

kubectl apply -f telegraf-configmap.yaml
kubectl apply -f telegraf-daemonset.yaml
kubectl get pods -n monitoring -l app=telegraf

InfluxDB’de Bucket ve Retention Policy Yönetimi

Kubernetes metriklerinin boyutu hızla büyür. Ham verileri sonsuza kadar saklamak hem maliyetli hem de pratik değil. InfluxDB’nin retention policy ve task özellikleri burada devreye giriyor.

# InfluxDB CLI ile bağlanma
kubectl exec -it -n monitoring 
  $(kubectl get pod -n monitoring -l app.kubernetes.io/name=influxdb2 -o jsonpath='{.items[0].metadata.name}') 
  -- influx bucket list --org k8s-monitoring

Downsampled metrikler için ayrı bir bucket oluşturalım. Ham veriler 7 gün, örneklenmiş veriler 90 gün saklanacak.

kubectl exec -it -n monitoring 
  $(kubectl get pod -n monitoring -l app.kubernetes.io/name=influxdb2 -o jsonpath='{.items[0].metadata.name}') 
  -- influx bucket create 
    --name kubernetes-downsampled 
    --org k8s-monitoring 
    --retention 2160h

Flux ile Kullanışlı Sorgular Yazma

InfluxDB 2.x’in Flux sorgu dili, SQL’e kıyasla zaman serisi verileri için çok daha güçlü. Birkaç gerçek dünya senaryosu için sorgu örnekleri hazırlayalım.

Pod CPU Kullanımı Sorgulama

InfluxDB UI’da veya Grafana üzerinden kullanabileceğiniz sorgular.

// Son 1 saatin pod CPU kullanımı - namespace bazında gruplanmış
from(bucket: "kubernetes")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "kubernetes_pod_container")
  |> filter(fn: (r) => r._field == "cpu_usage_nanocores")
  |> map(fn: (r) => ({r with _value: float(v: r._value) / 1000000.0}))
  |> group(columns: ["namespace", "pod_name"])
  |> aggregateWindow(every: 5m, fn: mean, createEmpty: false)
  |> yield(name: "pod_cpu_usage")

Node Memory Kullanımı ve Alert Eşiği

// Node memory kullanımı yüzde olarak
from(bucket: "kubernetes")
  |> range(start: -30m)
  |> filter(fn: (r) => r._measurement == "kubernetes_node")
  |> filter(fn: (r) => r._field == "memory_working_set_bytes")
  |> group(columns: ["node_name"])
  |> aggregateWindow(every: 1m, fn: last, createEmpty: false)
  |> map(fn: (r) => ({
      r with
      _value: float(v: r._value) / (1024.0 * 1024.0 * 1024.0)
  }))
  |> yield(name: "node_memory_gb")

Downsampling Task Oluşturma

Ham verileri her saat örnekleyerek başka bir bucket’a yazacak bir task tanımlayalım.

// InfluxDB UI > Tasks > Create Task bölümünde kullanın
option task = {
  name: "kubernetes-downsampling",
  every: 1h,
  offset: 5m
}

from(bucket: "kubernetes")
  |> range(start: -task.every)
  |> filter(fn: (r) =>
    r._measurement == "kubernetes_pod_container" or
    r._measurement == "kubernetes_node"
  )
  |> aggregateWindow(every: 5m, fn: mean, createEmpty: false)
  |> to(bucket: "kubernetes-downsampled", org: "k8s-monitoring")

Alert Yapılandırması

InfluxDB 2.x’in built-in alerting sistemi, harici bir araç olmadan bildirim göndermenize olanak tanır. Slack entegrasyonu için örnek bir alert tanımı.

# InfluxDB CLI ile check oluşturma
kubectl exec -it -n monitoring 
  $(kubectl get pod -n monitoring -l app.kubernetes.io/name=influxdb2 -o jsonpath='{.items[0].metadata.name}') 
  -- influx check create threshold 
    --name "High Node Memory Usage" 
    --query 'from(bucket:"kubernetes") |> range(start: -5m) |> filter(fn:(r) => r._measurement == "mem") |> filter(fn:(r) => r._field == "used_percent") |> last()' 
    --field "_value" 
    --crit-min 90 
    --warn-min 80 
    --every 1m 
    --org k8s-monitoring

Slack notification endpoint oluşturmak için ise InfluxDB UI’ı kullanmak daha pratik. Alerts > Notification Endpoints > Create yolunu izleyip Slack webhook URL’nizi girin.

Performans Tuning ve Sorun Giderme

InfluxDB Konfigürasyon Optimizasyonu

Yüksek yazma yoğunluğunda karşılaşılan sorunların büyük kısmı cache boyutu ve shard yapılandırmasından kaynaklanır. InfluxDB’nin config.toml dosyasını ConfigMap olarak yönetebilirsiniz.

# Mevcut konfigürasyonu kontrol etme
kubectl exec -it -n monitoring 
  $(kubectl get pod -n monitoring -l app.kubernetes.io/name=influxdb2 -o jsonpath='{.items[0].metadata.name}') 
  -- influx server-config

Yaygın Sorunlar ve Çözümleri

Telegraf pod’ları InfluxDB’ye bağlanamıyor:

DNS çözümlemesi sorunları sıkça görülür. Service adının doğru olduğundan emin olun.

kubectl exec -it -n monitoring 
  $(kubectl get pod -n monitoring -l app=telegraf -o jsonpath='{.items[0].metadata.name}') 
  -- nslookup influxdb-influxdb2.monitoring.svc.cluster.local

Yüksek cardinality sorunu:

Kubernetes label’larının hepsi tag olarak alınırsa cardinality patlar. Telegraf konfigürasyonuna aşağıdaki filtreleri ekleyin.

[[inputs.kube_inventory]]
  url = "https://kubernetes.default.svc"
  bearer_token = "/var/run/secrets/kubernetes.io/serviceaccount/token"
  insecure_skip_verify = true
  [inputs.kube_inventory.tagdrop]
    pod_labels = ["*"]
  [inputs.kube_inventory.taginclude]
    pod_labels = ["app", "version", "environment"]

Disk dolma problemi:

InfluxDB’nin disk kullanımını düzenli kontrol edin.

kubectl exec -it -n monitoring 
  $(kubectl get pod -n monitoring -l app.kubernetes.io/name=influxdb2 -o jsonpath='{.items[0].metadata.name}') 
  -- df -h /var/lib/influxdb2

Retention policy’niz çalışmıyorsa bucket ayarlarını doğrulayın.

kubectl exec -it -n monitoring 
  $(kubectl get pod -n monitoring -l app.kubernetes.io/name=influxdb2 -o jsonpath='{.items[0].metadata.name}') 
  -- influx bucket list --org k8s-monitoring

Yedekleme Stratejisi

Production’da veri kaybı yaşamamak için düzenli yedekleme şart.

# CronJob ile otomatik yedekleme
cat <<EOF | kubectl apply -f -
apiVersion: batch/v1
kind: CronJob
metadata:
  name: influxdb-backup
  namespace: monitoring
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: influxdb-backup
            image: influxdb:2.7.1-alpine
            command:
            - /bin/sh
            - -c
            - |
              influx backup /backup/$(date +%Y%m%d) 
                --host http://influxdb-influxdb2.monitoring.svc.cluster.local:8086 
                --token $INFLUXDB_TOKEN 
                --org k8s-monitoring
            env:
            - name: INFLUXDB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: influxdb-token
                  key: token
            volumeMounts:
            - name: backup-storage
              mountPath: /backup
          restartPolicy: OnFailure
          volumes:
          - name: backup-storage
            persistentVolumeClaim:
              claimName: influxdb-backup-pvc
EOF

Grafana Entegrasyonu

InfluxDB’nin built-in UI’ı temel ihtiyaçlar için yeterli, ancak Grafana ile çok daha zengin dashboard’lar oluşturabilirsiniz. Grafana data source eklemek için.

  • Type: InfluxDB seçin
  • Query Language: Flux seçin
  • URL: http://influxdb-influxdb2.monitoring.svc.cluster.local:8086
  • Organization: k8s-monitoring
  • Token: InfluxDB token’ınız
  • Default Bucket: kubernetes

Grafana Dashboard ID 13502 (InfluxDB 2.x Kubernetes monitoring), doğrudan import edebileceğiniz hazır bir dashboard sunuyor. Import ettikten sonra data source’u kendi InfluxDB kurulumunuzla eşleştirin.

Sonuç

InfluxDB ile Kubernetes cluster monitoring kurulumu ilk bakışta karmaşık görünebilir, ancak parçalara ayırdığınızda oldukça mantıklı bir yapı ortaya çıkıyor. InfluxDB veri depolar, Telegraf metrik toplar, Flux sorgular yazar ve built-in alerting bildirim gönderir. Bu dört bileşen bir arada çalıştığında, cluster’ınızda ne olup bittiğini gerçek zamanlı ve tarihsel olarak takip edebiliyorsunuz.

Özellikle vurgulamak istediğim birkaç nokta var. Cardinality yönetimi production’da en sık sorun yaratan konuların başında gelir, tag seçimlerine dikkat edin. Retention policy ve downsampling’i baştan doğru kurmak, ileride disk krizleriyle uğraşmaktan sizi kurtarır. DaemonSet yapısı sayesinde cluster büyüdükçe monitoring altyapısı da otomatik olarak ölçeklenir ve bu gerçekten büyük bir avantaj.

Son olarak, bu altyapıyı kurmak yetmez; düzenli olarak alert kurallarını gözden geçirin, yedeklemelerin çalıştığını doğrulayın ve Telegraf ile InfluxDB versiyonlarını güncel tutun. Monitoring sisteminizin kendisini de izlemeniz gerektiğini unutmayın, aksi halde izleme aracınız çöktüğünde bunu en son siz öğrenirsiniz.

Bir yanıt yazın

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