DEV Community

Tarık Anafarta for Açıklab

Posted on

Kubernetes + ELK ile AIOps Temeli: Audit, Events, Metrics, State ve RCA Dashboardları

Bu yazıda Kubernetes üzerinde çalışan bir ortamı ELK Stack ile gözlemlenebilir hale getirip, bunun üzerine senaryo bazlı anomali tespiti ve kök neden analizi yaklaşımı kuracağız.

Buradaki hedef sadece “logları Elasticsearch’e atalım” değil. Hedef şu:

  • Kubernetes audit loglarından kim, ne zaman, hangi objeye dokundu? sorusunu cevaplamak.
  • Kubernetes eventlerinden pod neden ayağa kalkmadı, neden evict oldu, neden image çekemedi? sorusunu cevaplamak.
  • Metricbeat metrikleriyle CPU, memory, volume, pod, node durumu nedir? sorusunu cevaplamak.
  • kube-state-metrics ile cluster’ın o anki deployment, pod, PVC, service, node state bilgisini Elasticsearch’e almak.
  • Kibana Discover, Alert Rule ve Dashboard kullanarak operasyonel bir detection/RCA zemini oluşturmak.
  • En sonda bu zemini AI ile yorumlanabilir hale getirip AIOps katmanına hazırlamak.

Ortam RKE2 üzerinde kuruldu. Elasticsearch, Kibana, Logstash, Filebeat, Metricbeat ve kube-state-metrics kullanıldı. Komutları kendi cluster isimlerinize ve namespace’lerinize göre uyarlamanız gerekebilir.


1. Genel mimari

Kurulum sonunda veri akışı şu hale geldi:

Kubernetes container logs  → Filebeat    → Logstash → Elasticsearch
Kubernetes events          → Metricbeat  → Logstash → Elasticsearch
Kubernetes metrics         → Metricbeat  → Logstash → Elasticsearch
Kubernetes audit logs      → Filebeat    → Logstash → Elasticsearch
Kubernetes object state    → kube-state-metrics → Metricbeat → Logstash → Elasticsearch
Enter fullscreen mode Exit fullscreen mode

Kibana tarafında ise şu Data View’lar kullanıldı:

Kubernetes Logs
Kubernetes Events
Kubernetes Metrics
Kubernetes Audit
Enter fullscreen mode Exit fullscreen mode

Sonra bu data view’lar üzerinden:

  • Discover session’lar oluşturuldu.
  • Alert rule’lar yazıldı.
  • State ve RCA dashboard’ları oluşturuldu.

2. Kubernetes audit loglarını açmak

Anomali tespiti için en kritik kaynak Kubernetes audit loglarıdır. Çünkü audit log bize şunu söyler:

  • İsteği kim attı?
  • Hangi resource’a erişildi?
  • Hangi namespace’teydi?
  • get, list, watch, create, patch, delete gibi hangi işlem yapıldı?
  • İstek başarılı mı oldu, forbidden mı döndü?
  • Hangi user agent ve source IP üzerinden geldi?

RKE2’de audit loglarını aktifleştirmek için /etc/rancher/rke2/config.yaml içerisine kube-apiserver argümanları eklenir.

Örnek:

kube-apiserver-arg:
  - audit-policy-file=/etc/rancher/rke2/audit-policy.yaml
  - audit-log-path=/var/lib/rancher/rke2/server/logs/audit.log
  - audit-log-format=json
  - audit-log-maxage=30
  - audit-log-maxbackup=10
  - audit-log-maxsize=100
Enter fullscreen mode Exit fullscreen mode

Sonrasında:

chmod 600 /etc/rancher/rke2/config.yaml
systemctl restart rke2-server
systemctl is-active rke2-server
kubectl get nodes
Enter fullscreen mode Exit fullscreen mode

Audit log dosyası:

ls -lh /var/lib/rancher/rke2/server/logs/audit.log*
tail -n 3 /var/lib/rancher/rke2/server/logs/audit.log
Enter fullscreen mode Exit fullscreen mode

Audit policy tasarımı

Başta çok geniş audit policy kullanırsanız, disk hızla büyür. Özellikle get/list/watch çok gürültülüdür. Kubernetes controller’ları, Rancher, Elastic operator, kubelet, dashboard gibi bileşenler sürekli API server’a istek atar.

Bu yüzden audit policy şu prensiple tasarlandı:

  • Health endpointleri loglama.
  • Leases/events gibi çok gürültülü kaynakları loglama.
  • Secret ve ConfigMap erişimini metadata seviyesinde logla.
  • RBAC değişikliklerini daha detaylı logla.
  • Pod, workload, NetworkPolicy, Ingress değişikliklerini logla.
  • Her şeyi loglamaya çalışma.

Özellikle şu hata yapıldı ve düzeltildi:

Geniş get/list/watch audit logging açılınca audit log hacmi çok hızlı büyüdü.
Özellikle watch kayıtları log büyümesinin ana sebebi oldu.
Bu nedenle kalıcı policy’den geniş watch loglama kaldırıldı.
Enter fullscreen mode Exit fullscreen mode

Bu çok önemli bir ders: güvenlik için her şeyi loglamak cazip görünür ama pratikte kullanılamaz hale gelebilir.


3. kube-state-metrics kurulumu

Kubernetes eventleri ve metrikleri yeterli değildir. Bazen “şu anda cluster objelerinin state’i nedir?” sorusuna cevap vermek gerekir.

Örneğin:

  • Deployment desired replica kaç, available kaç?
  • PVC Bound mı Pending mi?
  • Node Ready mi, DiskPressure var mı?
  • Pod Running mi, Pending mi?
  • Service tipi nedir?

Bunun için kube-state-metrics kuruldu.

Helm ile kuruldu:

helm repo add kube-state-metrics https://kubernetes.github.io/kube-state-metrics
helm repo update

helm install kube-state-metrics kube-state-metrics/kube-state-metrics \
  -n kube-system
Enter fullscreen mode Exit fullscreen mode

Kontrol:

kubectl get deploy,svc,pods -n kube-system | egrep -i 'kube-state-metrics'
kubectl get svc -n kube-system kube-state-metrics -o wide
kubectl get endpoints -n kube-system kube-state-metrics
Enter fullscreen mode Exit fullscreen mode

Beklenen:

deployment.apps/kube-state-metrics   1/1
service/kube-state-metrics           ClusterIP ... 8080/TCP
pod/kube-state-metrics-...           1/1 Running
Enter fullscreen mode Exit fullscreen mode

Endpoint örneği:

10.42.x.x:8080
Enter fullscreen mode Exit fullscreen mode

Kubernetes 1.33+ ortamlarında Endpoints is deprecated; use EndpointSlice uyarısı görülebilir. Bu uyarı hata değildir.


4. kube-state-metrics verisini Metricbeat ile Elasticsearch’e almak

Mevcut Metricbeat zaten kubelet/node/container/volume metriklerini topluyordu. Ancak state_* metricset’lerini aynı DaemonSet’e eklemek doğru değildir.

Neden?

Çünkü DaemonSet her node’da çalışır. Eğer her node aynı kube-state-metrics servisini scrape ederse duplicate state metric üretir.

Bu yüzden ayrı bir metricbeat-state Deployment oluşturuldu.

Örnek metricbeat-state.yaml:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: metricbeat-state
  namespace: elk
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: metricbeat-state-elk
rules:
  - apiGroups: [""]
    resources:
      - nodes
      - namespaces
      - pods
      - services
      - persistentvolumes
      - persistentvolumeclaims
      - resourcequotas
      - replicationcontrollers
    verbs:
      - get
      - list
      - watch
  - apiGroups: ["apps"]
    resources:
      - deployments
      - daemonsets
      - statefulsets
      - replicasets
    verbs:
      - get
      - list
      - watch
  - apiGroups: ["storage.k8s.io"]
    resources:
      - storageclasses
    verbs:
      - get
      - list
      - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: metricbeat-state-elk
subjects:
  - kind: ServiceAccount
    name: metricbeat-state
    namespace: elk
roleRef:
  kind: ClusterRole
  name: metricbeat-state-elk
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: beat.k8s.elastic.co/v1beta1
kind: Beat
metadata:
  name: metricbeat-state
  namespace: elk
spec:
  type: metricbeat
  version: 9.4.0
  config:
    fields_under_root: true
    fields:
      elk_dataset: k8s_metrics

    metricbeat.modules:
      - module: kubernetes
        metricsets:
          - state_node
          - state_namespace
          - state_pod
          - state_container
          - state_deployment
          - state_daemonset
          - state_statefulset
          - state_replicaset
          - state_service
          - state_persistentvolume
          - state_persistentvolumeclaim
          - state_storageclass
          - state_resourcequota
        period: 30s
        hosts:
          - http://kube-state-metrics.kube-system.svc.cluster.local:8080

    output.logstash:
      hosts:
        - elk-ls-ls-beats.elk.svc:5044

  deployment:
    podTemplate:
      spec:
        serviceAccountName: metricbeat-state
        automountServiceAccountToken: true
        containers:
          - name: metricbeat
            securityContext:
              runAsUser: 0
            resources:
              requests:
                cpu: 100m
                memory: 200Mi
              limits:
                cpu: 500m
                memory: 500Mi
Enter fullscreen mode Exit fullscreen mode

Uygulama:

kubectl apply -f metricbeat-state.yaml
kubectl get beat,pods -n elk
Enter fullscreen mode Exit fullscreen mode

İlk başta şu hata alındı:

failed to create temporary Beat meta file: permission denied
Enter fullscreen mode Exit fullscreen mode

Çözüm olarak container’a şu eklendi:

securityContext:
  runAsUser: 0
Enter fullscreen mode Exit fullscreen mode

Sonrasında RBAC hatası görüldü:

cannot list resource "nodes" at the cluster scope
Enter fullscreen mode Exit fullscreen mode

Bu da ClusterRole + ClusterRoleBinding eklenerek çözüldü.

Son durumda:

metricbeat-state   green   1   1
pod/...            1/1 Running
Enter fullscreen mode Exit fullscreen mode

Kibana’da şu sorgularla doğrulandı:

metricset.name: "state_pod"
metricset.name: "state_deployment"
metricset.name: "state_node"
metricset.name: "state_resourcequota"
metricset.name: "state_persistentvolumeclaim"
Enter fullscreen mode Exit fullscreen mode

5. Cluster state dashboard’ı

kube-state-metrics entegrasyonundan sonra bir cluster state dashboard’ı oluşturuldu.

Bu dashboard’da şu KPI ve grafikler yer aldı:

Ulaşılamayan Deployment Replica
Pending Pod Sayısı
Pending PVC Sayısı
Sorunlu Node Sayısı
Namespace Bazlı Pod Sayısı
Pod Durum (Phase) Dağılımı
PVC Durum Dağılımı
Servis Tipleri Dağılımı
Enter fullscreen mode Exit fullscreen mode

Alt tarafta detay tabloları:

Cluster State - Podlar
Cluster State - Deploymentlar
Cluster State - Node Durumları
Cluster State - PVC Durumları
Cluster State - ResourceQuota
Cluster State - Servisler
Enter fullscreen mode Exit fullscreen mode

Buradaki kritik nokta: Lens panellerinde Count of records kullanmak genelde yanlıştır. Çünkü Metricbeat aynı objeyi periyodik olarak tekrar yazar. Bu yüzden gerçek obje sayısı için unique_count kullanıldı.

Örnekler:

Pod sayısı        → unique_count(kubernetes.pod.name)
PVC sayısı        → unique_count(kubernetes.persistentvolumeclaim.name)
Service sayısı    → unique_count(kubernetes.service.name)
Deployment sayısı → unique_count(kubernetes.deployment.name)
Enter fullscreen mode Exit fullscreen mode

PVC phase değerleri için:

Bound   → PVC bir PV’ye başarıyla bağlanmış. İyi durum.
Pending → PVC henüz volume alamamış. İncelenmeli.
Lost    → Bağlı PV kaybolmuş veya ilişki bozulmuş. Kötü durum.
Enter fullscreen mode Exit fullscreen mode

6. Service account token kötüye kullanımı ve secret enumeration

İlk güvenlik senaryosu service account token kötüye kullanımıydı.

Bir saldırgan pod içinden service account token’ını çalarsa, bu token ile API server’a istek atabilir. Özellikle şu davranışlar şüphelidir:

  • Service account’un secret listelemesi.
  • Normalde erişmediği namespace’e erişmesi.
  • Çok sayıda resource tipini kısa sürede sorgulaması.
  • list veya watch ile keşif yapması.

Kibana Discover sorgusu:

Saved search:

ServiceAccount Hassas Resource Erişimi
Enter fullscreen mode Exit fullscreen mode

Alert:

user.name: system\:serviceaccount\:* and kubernetes.audit.object_ref.resource: "secrets" and event.action: ("list" or "watch") and responseStatus.code: 200
Enter fullscreen mode Exit fullscreen mode

Bu alert get işlemlerinden daha değerlidir; çünkü list/watch secrets genelde enumeration davranışına daha yakındır.

Not: Dashboard service account gibi bilinen normal hesaplar false positive üretiyorsa exclude edilebilir.


7. RBAC değişiklikleri ve privilege creep başlangıç tespiti

RBAC değişiklikleri privilege escalation veya privilege creep için kritiktir.

İzlenen resource’lar:

roles
rolebindings
clusterroles
clusterrolebindings
Enter fullscreen mode Exit fullscreen mode

KQL:

kubernetes.audit.object_ref.resource: ("roles" or "rolebindings" or "clusterroles" or "clusterrolebindings") and event.action: ("create" or "update" or "patch" or "delete")
Enter fullscreen mode Exit fullscreen mode

Ama burada dikkat edilmesi gereken şey şu:

Bu ilk sürüm sadece değişikliği yakalar.

Gerçek privilege creep analizi için ayrıca şunlar gerekir:

  • Periyodik RBAC snapshot.
  • Principal bazlı effective permission hesaplama.
  • Zaman içinde permission surface artıyor mu analizi.
  • Peer group karşılaştırması.

Bizim kurduğumuz sürüm operasyonel ilk katmandır.


8. Untrusted registry ve image envanteri

Supply chain risklerinin ilk görünür noktası container image kaynağıdır.

Önce çalışan image envanteri çıkarıldı:

metricset.name: "state_container" and container.image.name: *
Enter fullscreen mode Exit fullscreen mode

Kolonlar:

@timestamp
kubernetes.namespace
kubernetes.pod.name
kubernetes.container.name
container.image.name
metricset.name
Enter fullscreen mode Exit fullscreen mode

Saved search:

Container Image Envanteri
Enter fullscreen mode Exit fullscreen mode

Sonra allowlist dışı image sorgusu oluşturuldu. Örnek lab allowlist:

metricset.name:"state_container" and container.image.name:* and not container.image.name:(docker.io/rancher/* or docker.io/longhornio/* or docker.elastic.co/* or registry.k8s.io/* or k8s.gcr.io/kube-state-metrics/* or docker.io/kubernetesui/* or docker.io/aciklab/liman* or docker.io/library/redis* or docker.io/library/postgres* or curlimages/*)
Enter fullscreen mode Exit fullscreen mode

Alert:

Untrusted Registry Kullanımı
Enter fullscreen mode Exit fullscreen mode

Bu senaryonun ileri seviyesi için ileride şunlar eklenebilir:

  • Image hash baseline.
  • Tag mutation detection.
  • First-time-seen image.
  • Vulnerability scanner entegrasyonu.
  • Admission controller ile allowlist dışı image engelleme.

9. Secret ve ConfigMap erişimi

Secret ve ConfigMap erişimi audit log ile izlendi.

KQL örneği:

kubernetes.audit.object_ref.resource: ("secrets" or "configmaps") and event.action: ("get" or "list" or "watch")
Enter fullscreen mode Exit fullscreen mode

Bu senaryoda dikkat edilmesi gereken nokta:

  • Secret içeriği loglanmaz.
  • Kim, ne zaman, hangi secret/configmap objesine erişti bilgisi loglanır.
  • İnsan kullanıcı ve service account erişimleri ayrı değerlendirilmelidir.

Alert’lerde gereksiz gürültüyü azaltmak için bazı normal sistem kullanıcıları veya dashboard erişimleri exclude edilebilir.


10. Privileged container, host network ve host namespace kullanımı

Kubernetes’te güvenlik açısından en riskli ayarlardan bazıları:

privileged: true
hostNetwork: true
hostPID: true
hostIPC: true
Enter fullscreen mode Exit fullscreen mode

Bu ayarlar pod create audit kayıtları üzerinden izlendi.

Yaklaşım:

  • Pod create/update kayıtlarını audit logdan bul.
  • Security context alanlarını yakala.
  • Privileged veya host namespace kullanımı varsa alert üret.

Bu senaryo özellikle untrusted image veya RBAC değişikliği ile birlikte görülürse daha kritik hale gelir.

Örneğin:

Untrusted image + privileged container = supply chain / node compromise riski
RBAC değişikliği + privileged container = pivot hazırlığı riski
Secret enumeration + privileged container = credential harvesting riski
Enter fullscreen mode Exit fullscreen mode

11. Memory leak, OOM ve BackOff

Memory senaryosunda önemli bir ders öğrenildi:

Her memory problemi doğrudan OOMKilled event’i olarak görünmeyebilir.
Enter fullscreen mode Exit fullscreen mode

Testte pod Exit Code 137 ile öldü ama Kubernetes Reason: OOMKilled yerine Reason: Error gösterdi. Events tarafında ise genellikle BackOff görüldü.

Bu yüzden pratik yaklaşım şu oldu:

  • Events tarafında BackOff, OOMKilled, OOMKilling izle.
  • Metrics tarafında container memory usage / limit pct izle.
  • Pod describe çıktısında Exit Code 137 ve restart count ile doğrula.

Events KQL:

kubernetes.event.reason: ("BackOff" or "OOMKilled" or "OOMKilling")
Enter fullscreen mode Exit fullscreen mode

Memory metric alert:

metricset.name: "container" and kubernetes.container.memory.usage.limit.pct >= 0.95
Enter fullscreen mode Exit fullscreen mode

Başta eşik düşük olduğu için Logstash gibi sistem bileşenlerinde false positive geldi. Eşik %95 seviyesine çekildi ve pencere genişletildi.


12. API server reconnaissance

API reconnaissance tespiti için ilk refleks geniş get/list/watch loglamaktı. Bu pratikte yanlış oldu.

Neden?

  • watch kayıtları çok yoğun.
  • Controller’lar ve operator’lar sürekli API server izler.
  • Audit log büyümesi hızla arttı.

Bu nedenle kalıcı olarak geniş watch loglamaktan vazgeçildi.

Daha kontrollü yaklaşım:

  • kubectl kaynaklı get/list trafiğini izle.
  • Başarısız discovery denemelerini izle.
  • Secret enumeration davranışını ayrıca izle.

Örnek KQL:

event.action: ("get" or "list") and userAgent: *kubectl*
Enter fullscreen mode Exit fullscreen mode

Başarısız API discovery:

responseStatus.code >= 400 and event.action: ("get" or "list") and userAgent: *kubectl*
Enter fullscreen mode Exit fullscreen mode

Secret enumeration:

kubernetes.audit.object_ref.resource: "secrets" and event.action: ("get" or "list") and userAgent: *kubectl*
Enter fullscreen mode Exit fullscreen mode

13. Deployment değişikliği ve servis bozulması korelasyonu

Bir servis bozulduğunda ilk soru şudur:

Son ne değişti?
Enter fullscreen mode Exit fullscreen mode

Deployment değişiklikleri audit logdan izlendi:

kubernetes.audit.object_ref.resource: "deployments" and event.action: ("create" or "update" or "patch" or "delete")
Enter fullscreen mode Exit fullscreen mode

Saved search:

Deployment Değişiklikleri
Enter fullscreen mode Exit fullscreen mode

Alert:

Deployment Değişikliği
Enter fullscreen mode Exit fullscreen mode

Bu alert tek başına “problem var” demek değildir. RCA için kanıt üretir. Örneğin aynı zaman aralığında şunlara bakılır:

  • Deployment unavailable replica var mı?
  • Podlar ready mi?
  • ImagePullBackOff var mı?
  • FailedScheduling var mı?
  • ConfigMap/Secret değişikliği var mı?

Tam latency korelasyonu için APM gerekir. Burada APM olmadığı için deployment change detection katmanı kuruldu.


14. Pod eviction ve node pressure

Pod eviction senaryosunda eventler izlendi.

Evicted podlar:

kubernetes.event.reason: "Evicted"
Enter fullscreen mode Exit fullscreen mode

Node pressure eventleri:

kubernetes.event.reason: ("NodeHasDiskPressure" or "NodeHasMemoryPressure" or "NodeHasPIDPressure" or "NodeNotReady")
Enter fullscreen mode Exit fullscreen mode

State metricleriyle bu senaryo güçlendirildi. Node state panelinde şu alanlar izlendi:

kubernetes.node.status.ready
kubernetes.node.status.disk_pressure
kubernetes.node.status.memory_pressure
kubernetes.node.status.pid_pressure
kubernetes.node.status.network_unavailable
kubernetes.node.status.unschedulable
Enter fullscreen mode Exit fullscreen mode

15. NetworkPolicy değişikliği ve servis erişim kaybı

NetworkPolicy değişiklikleri audit logdan izlendi.

KQL:

kubernetes.audit.object_ref.resource: "networkpolicies" and event.action: ("create" or "update" or "patch" or "delete")
Enter fullscreen mode Exit fullscreen mode

Güvenli test için hiçbir gerçek podu etkilemeyen bir NetworkPolicy oluşturuldu:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: r3-deny-test
  namespace: r3-networkpolicy-test
spec:
  podSelector:
    matchLabels:
      app: r3-non-existing-app
  policyTypes:
    - Ingress
  ingress: []
Enter fullscreen mode Exit fullscreen mode

Bu audit log’da create/patch/delete olarak görüldü.

Önemli not:

Tam network RCA için network flow/verdict logları gerekir.
Biz burada NetworkPolicy değişiklik tespitini kurduk.
Enter fullscreen mode Exit fullscreen mode

16. DNS resolution failure ve CoreDNS

DNS senaryosunda önce CoreDNS podları kontrol edildi:

kubectl get pods -n kube-system -o wide | grep -i coredns
Enter fullscreen mode Exit fullscreen mode

CoreDNS podları Running görünüyordu.

Terminalden CoreDNS logları görüldü:

kubectl logs -n kube-system <coredns-pod> --tail=50
Enter fullscreen mode Exit fullscreen mode

Loglarda şunlar görüldü:

[ERROR] plugin/kubernetes: Failed to watch
Enter fullscreen mode Exit fullscreen mode

Timestamp ile bakıldığında bu hataların aktif bir kriz olmadığı, eski loglar olduğu anlaşıldı.

Kibana’da CoreDNS gerçek container logları bulunamadı. message:*coredns* sorgusu yanıltıcıydı çünkü kube-state-metrics satırlarını getiriyordu.

Bu yüzden mevcut veriyle DNS senaryosu şu şekilde kuruldu:

  • CoreDNS pod state görünümü.
  • CoreDNS pod hazır değil alert’i.
  • CoreDNS ConfigMap değişiklikleri audit görünümü.
  • CoreDNS ConfigMap değişiklik alert’i.

CoreDNS pod state KQL:

metricset.name: "state_pod" and kubernetes.namespace: "kube-system" and kubernetes.pod.name: *coredns* and not kubernetes.pod.name: helm-install*
Enter fullscreen mode Exit fullscreen mode

CoreDNS ConfigMap değişikliği:

kubernetes.audit.object_ref.resource: "configmaps" and kubernetes.audit.object_ref.namespace: "kube-system" and kubernetes.audit.object_ref.name: *coredns* and event.action: ("create" or "update" or "patch" or "delete")
Enter fullscreen mode Exit fullscreen mode

Not:

CoreDNS ConfigMap alert kuruldu ama test patch yapılmadı.
Enter fullscreen mode Exit fullscreen mode

17. PVC, volume kullanımı ve storage eventleri

Storage senaryosunda ilk olarak volume metric olup olmadığına bakıldı:

metricset.name: "volume"
Enter fullscreen mode Exit fullscreen mode

Geniş zaman aralığında milyonlarca document görüldü. Bu normaldi çünkü volume metricset sık veri üretir. Time range Last 15 minutes yapılınca sayı makul seviyeye düştü.

Asıl PVC backed volume’ları görmek için sorgu daraltıldı:

metricset.name: "volume" and kubernetes.persistentvolumeclaim.name: *
Enter fullscreen mode Exit fullscreen mode

Önemli field:

kubernetes.volume.fs.used.pct
Enter fullscreen mode Exit fullscreen mode

Yüksek PVC doluluk alert’i:

metricset.name: "volume" and kubernetes.persistentvolumeclaim.name: * and kubernetes.volume.fs.used.pct >= 0.85
Enter fullscreen mode Exit fullscreen mode

Storage eventleri:

kubernetes.event.reason: ("FailedMount" or "FailedAttachVolume" or "FailedDetachVolume" or "VolumeResizeFailed" or "FailedBinding" or "ProvisioningFailed")
Enter fullscreen mode Exit fullscreen mode

Bu eventlerde FailedMount kayıtları görüldü. Bu storage RCA için doğru event tipiydi.


18. Scheduling failure ve quota ilişkisi

Scheduling problemleri için Kubernetes Events data view kullanıldı.

Örnek KQL:

kubernetes.event.reason: "FailedScheduling"
Enter fullscreen mode Exit fullscreen mode

Bu senaryoda ayrıca pod create audit kayıtları ve state_pod/state_resourcequota/state_persistentvolumeclaim verileriyle korelasyon yapıldı.

Şu paneller bu senaryoya yardımcı oldu:

  • Pending Pod Sayısı
  • Pending PVC Sayısı
  • Cluster State - Podlar
  • Cluster State - ResourceQuota
  • Cluster State - PVC Durumları

19. ImagePullBackOff kök neden analizi

Image pull problemleri için Kubernetes Events kullanıldı.

KQL:

kubernetes.event.reason: ("Failed" or "BackOff" or "ErrImagePull" or "ImagePullBackOff")
Enter fullscreen mode Exit fullscreen mode

Kök neden ayrımı için event message çok önemlidir:

manifest unknown              → image/tag yok
authentication required       → registry credential sorunu
i/o timeout                   → network/registry erişim sorunu
no such host                  → DNS sorunu
too many requests             → rate limit
Enter fullscreen mode Exit fullscreen mode

Bu senaryo untrusted registry senaryosuyla da bağlantılıdır.


20. AIOps korelasyon dashboard’ı

Son olarak ayrı bir dashboard oluşturuldu:

AIOps - RCA Korelasyon Dashboard
Enter fullscreen mode Exit fullscreen mode

Bu dashboard’un amacı alarm geldiğinde ilgili kanıtları tek ekranda toplamaktır.

Eklenen paneller:

Deployment Değişiklikleri
NetworkPolicy Değişiklikleri
CoreDNS Pod Durumu
CoreDNS ConfigMap Değişiklikleri
PVC Volume Kullanımı
Storage PVC Eventleri
Untrusted Registry Kullanımı
Container Image Envanteri
ServiceAccount Hassas Resource Erişimi
Cluster State - Deploymentlar
Cluster State - Podlar
Cluster State - Node Durumları
Cluster State - PVC Durumları
Cluster State - Servisler
Enter fullscreen mode Exit fullscreen mode

Bu dashboard artık AI yorumlama katmanı için temel veri ekranı oldu.


21. Operasyonel dersler

Bu çalışma sırasında birkaç kritik ders çıktı.

1. Audit log’da watch çok tehlikeli büyür

Geniş get/list/watch loglamak diski hızla büyütür. Özellikle watch kalıcı olarak açılmamalıdır.

2. Count of records çoğu metric panelinde yanıltıcıdır

Metricbeat aynı objeyi sürekli tekrar yazdığı için Count of records gerçek obje sayısı değildir. Obje sayısı için unique_count kullanmak gerekir.

3. OOMKilled her zaman event reason olarak gelmeyebilir

Bazen sadece BackOff ve Exit Code 137 görülür. Bu yüzden memory senaryosunda events + metrics + describe birlikte değerlendirilmelidir.

4. CoreDNS loglarını Kibana’da gördüğünü sanmak kolaydır

message:*coredns* gerçek CoreDNS logu değil, içinde coredns geçen metric satırı olabilir. Doğru log kaynağı doğrulanmadan saved search oluşturulmamalıdır.

5. Allowlist KQL yazarken wildcard formatına dikkat edilmeli

Tırnaklı wildcard beklenen sonucu vermeyebilir. Örneğin bu format çalıştı:

not container.image.name:(docker.io/rancher/* or docker.elastic.co/*)
Enter fullscreen mode Exit fullscreen mode

22. Neler Yapıldı?

Toplamda 7 anomali tespiti ve 7 kök neden analizi senaryosunun tamamına pratik ilk sürüm olarak dokunuldu.

Tamamlanan operasyonel parçalar:

Kubernetes audit log toplama
Kubernetes events toplama
Kubernetes metrics toplama
kube-state-metrics kurulumu
metricbeat-state kurulumu
state_* metricset doğrulama
Discover session’lar
Alert rule’lar
Cluster State dashboard
RCA Korelasyon dashboard
Enter fullscreen mode Exit fullscreen mode

Sonuç

Bu rehberde Kubernetes üzerinde ELK tabanlı bir AIOps temelini kurduk.

Kurulan sistem şunları yapabiliyor:

  • Kubernetes API aktivitelerini audit log ile izliyor.
  • Secret, ConfigMap, RBAC, NetworkPolicy, Deployment değişikliklerini yakalıyor.
  • Pod, node, PVC, service ve deployment state bilgisini Elasticsearch’e taşıyor.
  • Memory, storage, image pull, scheduling ve DNS gibi operasyonel problemleri görünür hale getiriyor.
  • Kibana dashboard’larıyla cluster state ve RCA kanıtlarını tek ekranda topluyor.
  • AI yorumlama katmanı için gerekli veriyi hazırlıyor.

Bu haliyle sistem henüz tam otomatik bir AIOps ürünü değil; ama AIOps ürününün ihtiyaç duyduğu veri, detection ve korelasyon temelini sağlam şekilde oluşturuyor.

Top comments (0)