Kasım 22 2024

Kubernetes Kaynak Yönetimi: Request, Limit ve VPA Ayarları

Hepimiz o sancılı anı en az bir kez yaşamışızdır: Hafta sonu tam kahvenizden ilk yudumu almışken, Slack veya PagerDuty üzerinden bir “Pod crashed” uyarısı düşer. Hemen terminale koşup cluster’a sızarsınız, kubectl describe pod komutunu yapıştırırsınız ve karşınızda o meşhur ibareyi görürsünüz: OOMKilled (Exit Code 137). Ya da daha sinsisi; CPU kullanımı %10 seviyelerindeyken uygulamanın response time’ları bir anda saniyelere fırlar, çünkü arkada amansız bir CPU throttling savaşı dönmektedir.

Kubernetes dünyasında kaynak yönetimi (resources), teoride çok basit görünse de pratikte prod ortamlarının en büyük baş belasıdır. Bu makalede, deneyimli bir devops mühendisinin gözünden, kubernetes üzerinde CPU/Memory dengesini nasıl kuracağımızı, vpa (Vertical Pod Autoscaler) ile kaynak yönetimini nasıl otomatize edeceğimizi ve throttling/OOMKill canavarlarıyla nasıl savaşacağımızı derinlemesine ele alacağız.

Request ve Limit: scheduler’ın Terazi Hassasiyeti

Kubernetes dünyasında kaynakları tanımlarken iki temel kavram kullanırız: requests ve limits. Bunların arasındaki farkı netleştirmek, sistemin kararlılığı için atılacak ilk adımdır.

  • Request: Bir pod’un schedule edilebilmesi için garanti edilen minimum kaynak miktarıdır. Kubernetes scheduler, bir node üzerinde pod’u konumlandırırken sadece bu değere bakar. Eğer node üzerinde boşta yeterli “request” kapasitesi yoksa, pod o node’a yerleşemez (Pending durumunda kalır).
  • Limit: Bir pod’un fiziksel olarak tüketebileceği maksimum kaynaktır. Pod bu sınırı aşmaya çalıştığında kernel seviyesinde kısıtlamalar devreye girer.

QoS (Quality of Service) Sınıfları Neden Önemli?

Request ve limit değerlerini nasıl tanımladığınız, Kubernetes’in podunuza atayacağı QoS sınıfını belirler. Node üzerinde kaynak darboğazı yaşandığında, kubelet ilk olarak hangi pod’u feda edeceğine (eviction) bu sınıfa göre karar verir:

  1. Guaranteed (Garantili): Pod içerisindeki tüm container’ların request ve limit değerleri birbirine eşittir (hem CPU hem Memory için). Kubernetes bu pod’ları en son gözden çıkarır. Veritabanları ve stateful servisler için idealdir.
  2. Burstable (Esneyebilir): Request değeri limit değerinden küçüktür veya sadece request tanımlanmıştır. Web uygulamalarımızın %90’ı bu sınıfa girer. Node sıkıştığında, limitlerine yaklaşan burstable pod’lar ilk hedef tahtasındadır.
  3. BestEffort (Gönlünden Ne Koparsa): Ne request ne de limit tanımlanmıştır. Node üzerinde kaynak bittiği an, kubelet bu pod’ları acımadan öldürür. Prod ortamında asla ama asla kullanılmamalıdır!
# Burstable QoS sınıfına örnek bir pod tanımı
apiVersion: v1
kind: Pod
metadata:
  name: billing-service
  namespace: production
spec:
  containers:
  - name: app
    image: internal/billing:v2.1.0
    resources:
      requests:
        memory: "256Mi"
        cpu: "200m"
      limits:
        memory: "512Mi"
        cpu: "1000m"

CPU Throttling ve OOMKill: Sessiz Katiller

Memory ve CPU, işletim sistemi kernel’ı tarafından farklı şekillerde yönetilir. Bu fark, pod’larımızın hayatta kalma mücadelesini doğrudan etkiler.

OOMKill (Out of Memory)

Memory, sıkıştırılamaz (non-compressible) bir kaynaktır. Bir pod, kendisine tanımlanan memory limit değerini aşarsa, kernel’ın oom-killer mekanizması devreye girer ve pod’u anında öldürür. Pod’unuz durduk yere 137 exit kodu ile çöküyorsa, memory limitiniz uygulamanın anlık yük altında ihtiyaç duyduğu heap size’a yetmiyor demektir.

Bunu debug etmek için şu komutla son çöken pod’ların nedenlerine bakabilirsiniz:

kubectl get pods -n production -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.containerStatuses[*].lastState.terminated.reason}{"\n"}{end}' | grep OOMKilled

CPU Throttling

CPU ise sıkıştırılabilir (compressible) bir kaynaktır. Pod’unuz CPU limitine ulaştığında işletim sistemi onu öldürmez; bunun yerine pod’a tahsis edilen CPU zaman dilimlerini (CFS shares) kısar. Buna throttling denir.

Uygulamanız çökmez ama bir anda istekleri işlememeye başlar, thread’ler kuyruğa girer ve latency tavan yapar. Birçok junior mühendis bu durumu fark edemez çünkü pod “Running” durumundadır ve CPU kullanımı %100 görünmez (çünkü limit bazlı kırpılmıştır).

Prometheus üzerinde CPU throttling olayını yakalamak için şu PromQL sorgusunu kullanabilirsiniz:

sum(rate(container_cpu_cfs_throttled_seconds_total[5m])) by (pod, container) / sum(rate(container_cpu_usage_seconds_total[5m])) by (pod, container) * 100

Eğer bu oran %5’in üzerindeyse, uygulamanız ciddi şekilde yavaşlatılıyor demektir. Limit değerinizi artırmanın vakti gelmiştir.

VPA (Vertical Pod Autoscaler) ile Otomatik Kaynak Yönetimi

Yazılımcılara “Uygulamanız ne kadar kaynak tüketiyor?” diye sormak, bir çocuğa “Ne kadar dondurma istersin?” diye sormaya benzer. Cevap hep “Çok!” olur. İşte bu noktada vpa devreye giriyor. VPA, pod’ların geçmiş kaynak tüketimlerini izleyerek en ideal request ve limit değerlerini otomatik olarak hesaplar.

VPA üç ana bileşenden oluşur:

  • Recommender: Tarihsel metrikleri (Prometheus veya Metrics Server üzerinden) inceleyerek ideal kaynak önerilerini hesaplar.
  • Updater: Eğer bir pod önerilen değerlerin çok dışındaysa, pod’u silerek yeni değerlerle yeniden ayağa kalkmasını tetikler (eğer mode: Auto ise).
  • Admission Controller: Pod yeniden oluşturulurken mutasyon aşamasında araya girer ve yeni request/limit değerlerini pod spec’ine enjekte eder.

Aşağıda prod ortamında güvenle kullanabileceğiniz bir VPA konfigürasyon örneği yer alıyor:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: auth-service-vpa
  namespace: production
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: auth-service
  updatePolicy:
    updateMode: "Auto" # "Off", "Initial" veya "Auto" yapabilirsiniz.
  resourcePolicy:
    containerPolicies:
      - containerName: '*'
        minAllowed:
          cpu: "100m"
          memory: "128Mi"
        maxAllowed:
          cpu: "2000m"
          memory: "4Gi"
        controlledResources: ["cpu", "memory"]

Pro-Tip: Eğer pod’larınızın durduk yere restart olmasını istemiyorsanız, updateMode: "Off" olarak ayarlayın. VPA sadece öneri (recommendation) üretecektir. Siz de bu önerileri inceleyerek (kubectl describe vpa auth-service-vpa) manuel olarak güncelleme yapabilirsiniz.

VPA ve HPA Çelişkisi: İki Kaptan Bir Gemiyi Batırır

Eğer cluster mimarinizde hem hpa (Horizontal Pod Autoscaler) hem de VPA kullanıyorsanız dikkat etmeniz gereken çok kritik bir kural var: İkisini de aynı kaynak metriğine (örn: CPU kullanımına) göre ölçeklenecek şekilde ayarlayamazsınız!

Eğer HPA CPU kullanımına göre pod sayısını artırmaya çalışırken, VPA de aynı CPU metriğine bakıp pod’un dikey boyutunu büyütmeye çalışırsa, sistem kararsız bir döngüye girer. HPA pod ekler, VPA pod’u yeniden başlatıp büyütür, tam bir kaos yaşanır.

Bu Çıkmazdan Nasıl Kurtuluruz?

  1. HPA’yı Custom/External Metriklere Geçirin: HPA’yı CPU/Memory yerine Prometheus üzerinden gelen saniye başına istek sayısı (RPS), kuyruk uzunluğu (RabbitMQ queue size) veya aktif veritabanı bağlantı sayısı gibi işlevsel metriklere göre ölçeklendirin. VPA ise arkada sessizce pod’ların fiziksel limitlerini optimize etsin.
  2. VPA’yı Sadece Öneri Modunda Çalıştırın: VPA’yı updateMode: "Off" modunda bırakıp, Goldilocks gibi open-source araçlar kullanarak sadece doğru kaynak değerlerini bulmak için bir pusula olarak kullanın.

Altın Kurallar ve Best Practices

  • CPU Limitlerini Çok Sıkı Tutmayın (Veya Hiç Koymayın): Modern Kubernetes topluluklarında (özellikle büyük ölçekli altyapılarda) CPU limitlerinin kaldırılması tartışılıyor. Çünkü CPU limitleri CFS throttling nedeniyle gereksiz latency oluşturabiliyor. Bunun yerine yüksek CPU request’i tanımlayıp limit koymamak (veya çok yüksek tutmak) node üzerindeki işlemci gücünü daha efektif kullanabilir. Ancak Memory limitleri kesinlikle zorunludur!
  • Overcommit Oranını İyi Yönetin: Node’larınızdaki toplam Memory limitlerinin, fiziksel node kapasitesini aşırı derecede geçmesine (overcommit) izin vermeyin. Aksi takdirde bir yük anında tüm node kilitlenebilir ve kubelet pod’ları kontrolsüzce öldürmeye başlar.
  • Liveness ve Readiness Probe’lara Dikkat Edin: Probe’ların kullandığı endpoint’lerin yüksek CPU/Memory tüketmediğinden emin olun. Throttling anında probe’lar timeout’a düşerse, Kubernetes sağlam podunuzu “unhealthy” sayıp restart döngüsüne sokabilir.

Kubernetes üzerinde kaynak yönetimi, sürekli izlenmesi ve dinamik olarak ayarlanması gereken canlı bir süreçtir. VPA gibi otomasyon araçlarını sisteminize entegre ederek hem cloud maliyetlerinizi düşürebilir hem de o meşhur cumartesi gecesi uykularınızı garanti altına alabilirsiniz.

Category: Genel | LEAVE A COMMENT
Ekim 18 2024

GitOps ile Infrastructure as Code: ArgoCD ve Flux Karşılaştırması

Modern yazılım geliştirme süreçlerinde “lokalde çalışıyordu, production’da neden patladı?” sendromunu aşmanın en asil yolu altyapımızı da uygulama kodlarımız gibi sürüm kontrol sistemlerinde tutmaktan geçiyor. İşte bu noktada, Infrastructure as Code (IaC) felsefesinin uygulama dağıtım süreçleriyle evlenmesinden doğan GitOps yaklaşımı devreye giriyor. Günümüzde Kubernetes cluster’larını yönetmenin fiili standardı haline gelen GitOps modelinde, Git repomuz sistemimizin “Single Source of Truth” (Tek Doğruluk Kaynağı) haline geliyor. Peki, bu ekosistemin iki dev oyuncusu olan ArgoCD ve Flux arasından hangisini seçmeliyiz? Bu makalede, iki aracı derinlemesine karşılaştıracak, Helm chart deployment pratiklerine bakacak ve işler ters gittiğinde can simidimiz olacak rollback stratejilerini inceleyeceğiz.

Push-Based vs. Pull-Based: Neden GitOps?

Geleneksel CI/CD pipeline süreçlerinde genellikle “Push-Based” (İtme Odaklı) bir yaklaşım benimseriz. Jenkins, GitLab CI veya GitHub Actions gibi bir araç, uygulamanın imajını build eder ve ardından kubectl apply veya helm upgrade komutlarıyla hedef Kubernetes cluster’ına bağlanıp değişikliği push eder. Kulağa kolay geliyor değil mi? Ancak bu yaklaşımın iki büyük karanlık noktası vardır:

  1. Güvenlik Açığı: CI/CD aracınıza cluster üzerinde yüksek yetkili (admin) erişim anahtarları (kubeconfig) vermeniz gerekir. Eğer CI sunucunuz hacklenirse, tüm cluster anahtarlarını teslim etmiş olursunuz.
  2. State Drift (Durum Sapması): Cluster üzerinde birisi manuel olarak (örneğin gece yarısı hotfix’i ile) bir deployment’ı değiştirirse, Git repomuzdaki kod ile canlıdaki durum birbirinden sapar. CI aracının bir sonraki tetiklenmesine kadar bu durumdan haberimiz olmaz.

Pull-Based GitOps ise bu problemi tersine çevirir. Cluster içerisine kurduğumuz bir operator (ArgoCD veya Flux), Git repomuzu sürekli izler (polling veya webhook ile). Repoda yeni bir commit gördüğünde, aradaki farkı algılar ve cluster’ı Git’teki durumla eşitlemek için “pull” eder. Dışarıya hiçbir credential sızmaz, cluster kendi kendini yönetir.

ArgoCD vs. Flux: Mimari ve Felsefe Farkları

İki araç da CNCF (Cloud Native Computing Foundation) bünyesinde mezun (graduated) projelerdir ve production ortamlarında rüştünü fazlasıyla ispatlamıştır. Ancak felsefeleri oldukça farklıdır.

1. ArgoCD: Görsel Güç ve Merkezi Yönetim

ArgoCD, kullanıcı dostu web arayüzü (UI) ve merkezi yönetim kabiliyetleriyle öne çıkar. Eğer organizasyonunuzda çok sayıda developer varsa ve onların Kubernetes kaynaklarını görsel olarak izlemesini, loglara erişmesini, senkronizasyon durumunu canlı grafiklerle görmesini istiyorsanız ArgoCD tam size göredir.

  • CRD Yapısı: Temel olarak Application ve AppProject Custom Resource Definition (CRD) yapılarını kullanır.
  • SSO Entegrasyonu: Dex aracılığıyla Keycloak, Okta, GitHub gibi kimlik sağlayıcılarla harika entegre olur. Multi-tenancy desteği mükemmeldir.
  • Yönetim Tarzı: Web UI üzerinden manuel tetikleme (Sync) yapılmasına izin verir (Opsiyonel olarak kapatılabilir).

2. Flux (Flux v2): Kubernetes Native ve Minimalist

Flux, Kubernetes felsefesine sıkı sıkıya bağlıdır. Bir web arayüzü barındırmaz (üçüncü parti CLI veya UI araçları hariç). Tamamen “Git-first” ve “declarative” bir yaklaşımla çalışır. Mikrofonu Kubernetes’in kendi controller mimarisine bırakır.

  • Modüler Mimari: Flux, GitOps Toolkit adı verilen bağımsız controller’lardan oluşur (Source Controller, Kustomize Controller, Helm Controller, Notification Controller).
  • Çoklu Cluster (Multi-cluster) Kolaylığı: Git repolarını hiyerarşik olarak tarayıp düzinelerce cluster’ı tek bir Flux instance’ı ile yönetmek oldukça esnektir.
  • CLI Gücü: fluxctl (artık sadece flux) CLI’ı, terminal bağımlısı mühendislerin rüyalarını süsleyecek seviyededir.

Hızlı Karşılaştırma Tablosu

  • Multi-Tenancy
  • Özellik ArgoCD Flux v2
    Kullanıcı Arayüzü (UI) Var (Çok güçlü ve detaylı) Yok (CLI odaklı / Üçüncü parti eklentiler var)
    Mimari Monolitik Operator / API Server Mikroservis / Modüler Controller’lar
    Helm Desteği Var (Client-side render eder) Var (Dedicated Helm Controller kullanır)
    Yerleşik (AppProject nesneleri ile) Kubernetes RBAC ve Namespace izolasyonu ile

    GitOps Dünyasında Helm Yönetimi

    GitOps yaparken Kubernetes manifestlerini doğrudan çiğ YAML olarak tutmak yerine genellikle Helm chart paketlerini kullanırız. Hem ArgoCD hem de Flux, Helm entegrasyonuna sahiptir ancak işleyişleri farklıdır.

    ArgoCD ile Helm Dağıtımı

    ArgoCD, Helm chart’ı Git’ten veya harici bir Helm repo’sundan okur. Arka planda helm template komutunu çalıştırarak saf manifestleri üretir ve bunları cluster’a uygular. Yani cluster’da gerçek bir helm list komutu çalıştırdığınızda bu release’i göremezsiniz; her şey standart Kubernetes kaynakları olarak görünür.

    İşte ArgoCD için örnek bir declarative Application manifesti:

    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: kertenkerem-api
      namespace: argocd
    spec:
      project: default
      source:
        repoURL: 'https://charts.bitnami.com/bitnami'
        chart: nginx
        targetRevision: 15.0.0
        helm:
          valueFiles:
            - values.yaml
          parameters:
            - name: service.type
              value: ClusterIP
      destination:
        server: 'https://kubernetes.default.svc'
        namespace: production
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
    

    Buradaki selfHeal: true parametresi kritik önem taşır. Eğer birisi cluster’da gidip kubectl edit ile Nginx deployment’ının replika sayısını değiştirirse, ArgoCD bunu anında yakalar ve saniyeler içinde Git’teki duruma (örneğin 3 replikaya) geri döndürür.

    Flux ile Helm Dağıtımı

    Flux ise işi Kubernetes native controller’lar aracılığıyla çözer. İlk olarak kaynağı (HelmRepository) tanımlarız, ardından bu kaynaktan beslenen bir HelmRelease kaynağı oluştururuz. Flux, Kubernetes içerisinde gerçek Helm release’leri oluşturur.

    İlk adım: Helm Repository Tanımlama

    apiVersion: source.toolkit.fluxcd.io/v1beta2
    kind: HelmRepository
    metadata:
      name: bitnami
      namespace: flux-system
    spec:
      interval: 1h
      url: https://charts.bitnami.com/bitnami
    

    İkinci adım: HelmRelease Kaynağı

    apiVersion: helm.toolkit.fluxcd.io/v2beta1
    kind: HelmRelease
    metadata:
      name: kertenkerem-api
      namespace: production
    spec:
      interval: 15m
      chart:
        spec:
          chart: nginx
          version: '15.x'
          sourceRef:
            kind: HelmRepository
            name: bitnami
            namespace: flux-system
          interval: 1h
      install:
        remediation:
          retries: 3
      upgrade:
        remediation:
          retries: 3
      values:
        service:
          type: ClusterIP
    

    Rollback Stratejileri: İşler Sarpasarınca Ne Yapıyoruz?

    Canlıya yeni bir sürüm çıktık ve loglar bir anda kırmızıya boyandı. Geleneksel dünyada panikle helm rollback yazarız. Ancak GitOps dünyasında bu bir antipattern’dir! Neden mi? Çünkü cluster üzerinde manuel yapacağınız her rollback, Git reposundaki durumla çelişecektir. GitOps operator’ınız canlı durumu tekrar Git’tekine eşitlemek için (eğer self-heal açıksa) uygulamanızı tekrar hatalı sürüme yükseltecektir. Kısır döngüye hoş geldiniz!

    Peki doğru rollback stratejileri nelerdir?

    1. “Git Revert” Stratejisi (The Pure GitOps Way)

    En temiz, en denetlenebilir rollback yöntemi Git geçmişini geriye almaktır.
    Hatalı deployment’a sebep olan commit belirlenir ve lokalde şu komut koşturulur:

    git revert <commit-hash>
    git push origin main
    

    GitOps operator’ı değişikliği algılar, yeni “eski” versiyonu cluster’a uygular. Bu sayede audit log’larımızda kimin, ne zaman, neden rollback yaptığının kaydı kalır.

    2. Otomatik Helm Rollback (Automated Remediation)

    Bazen uygulamanın ayağa kalkamaması (CrashLoopBackOff) durumunda Git commit’ini bekleyecek vaktimiz olmayabilir. Flux ve ArgoCD bu durumlar için “Auto-Rollback” mekanizmaları sunar.

    Flux’ta Rollback Yapılandırması:
    Yukarıda paylaştığımız Flux HelmRelease manifestindeki remediation bloğu tam olarak bu işe yarar. Eğer Helm upgrade işlemi başarısız olursa (örneğin readiness probe’lar geçemezse), Flux otomatik olarak bir önceki çalışan Helm release sürümüne geri döner (rollback).

    ArgoCD’de Rollback Yapılandırması:
    ArgoCD’de eğer senkronizasyon başarısız olursa, otomatik rollback doğrudan ArgoCD Application seviyesinde yönetilebilir. Ancak dikkat edin; eğer Git’teki kod hala hatalı sürümü işaret ediyorsa ve ArgoCD “Auto-Sync” modundaysa, sürekli bir loop oluşabilir. Bu yüzden ArgoCD’de genellikle Progressive Delivery araçları (Argo Rollouts) ile birlikte Canary veya Blue/Green deployment stratejileri tercih edilir.

    Hangisini Seçmelisiniz?

    Yol ayrımındaysanız şu basit kuralları göz önünde bulundurabilirsiniz:

    • Şu durumlarda ArgoCD seçin: Yazılım geliştirme ekipleriniz cluster durumunu izlemek için terminale mahkum kalmak istemiyorsa, SSO entegreli şık bir dashboard şartsa ve uygulama gruplarını mantıksal projeler halinde (multi-tenancy) izole etmek istiyorsanız.
    • Şu durumlarda Flux seçin: Kubernetes felsefesine sıkı sıkıya bağlı kalmak istiyorsanız, kaynak tüketimi (resource footprint) sizin için kritikse, cluster içinde ekstra bir web server/UI çalıştırmak istemiyor ve tamamen Git entegrasyonuna güveniyorsanız.

    Her iki araç da günün sonunda sizi manuel müdahalelerin getirdiği güvensiz hislerden kurtaracak ve altyapınızı gerçek anlamda kod olarak yönetmenizi sağlayacaktır. Cluster’ınız kararlı, pipeline’larınız yeşil kalsın!

    Category: Genel | LEAVE A COMMENT
    Temmuz 19 2024

    Zabbix 7.x ile Kubernetes Cluster Monitoring

    Kubernetes ekosisteminde monitoring denildiğinde akla ilk gelen Prometheus-Grafana ikilisi olsa da, modern devops dünyasında zabbix 7.x sürümüyle kartları yeniden dağıtıyor. Bu yazımızda, legacy sistemlerden aşina olduğumuz bu devasa canavarın, kubernetes cluster’larındaki container metriklerini auto-discovery (LLD) yetenekleriyle nasıl saniyeler içinde yakaladığını, verileri nasıl işlediğini ve Grafana ile nasıl görselleştirdiğini ele alacağız. “Prometheus kurduk ama RAM tüketimi ocağımıza incir ağacı dikti” diyenlerdenseniz, kemerlerinizi bağlayın; Zabbix 7.x’in hafif ve güçlü Kubernetes entegrasyonuna dalıyoruz.

    Neden Zabbix 7.x? (Eski Dostun Yeni Numaraları)

    Yıllarca Zabbix’i sadece VM’lerin CPU ve disk doluluk oranlarını izlemek için kullandıysanız, kendinizi güncellemenin vakti geldi demektir. Zabbix 7.x, Kubernetes dünyasını yabancı bir gezegen gibi görmüyor. HTTP agent, out-of-the-box gelen gelişmiş Kubernetes template’leri ve JSONPath preprocessing yetenekleri sayesinde API Server üzerinden doğrudan cluster’ın kalbine inebiliyor.

    Peki neden Prometheus yerine Zabbix? Cevap basit: Unified Monitoring ve Uzun Vadeli Veri Saklama (Long-term Retention). Eğer cluster dışında fiziksel switch’leriniz, legacy veritabanlarınız ve sanal makineleriniz varsa, hepsini tek bir panele toplamak ve bunu yaparken TSDB (Time Series Database) kaynaklı çılgın RAM maliyetlerinden kaçınmak istiyorsanız, Zabbix 7.x tam size göre.

    Adım 1: Kubernetes Cluster Üzerinde Zabbix Helm Deployment

    Zabbix’in cluster içindeki gözü kulağı olacak Zabbix Agent 2 ve Zabbix Proxy yapılandırmasını kurarak işe başlıyoruz. Kubernetes API’si ile güvenli bir şekilde konuşabilmek için service account ve rol tanımlamalarına ihtiyacımız var. Neyse ki resmi Helm chart bu işi bizim yerimize hallediyor.

    İlk olarak Zabbix topluluk reposunu sistemimize ekleyelim:

    helm repo add zabbix-community https://zabbix-community.github.io/helm-charts
    helm repo update

    Şimdi, cluster metriklerini toplamak için optimize edilmiş bir values.yaml dosyası hazırlayalım. Bu dosyada Zabbix Server adresimizi ve cluster adımızı belirtiyoruz. Aşağıdaki konfigürasyonu zabbix-values.yaml olarak kaydedebilirsiniz:

    zabbixProxy:
      enabled: true
      resources:
        limits:
          cpu: 500m
          memory: 512Mi
        requests:
          cpu: 100m
          memory: 128Mi
      env:
        - name: ZBX_HOSTNAME
          value: "k8s-production-proxy"
        - name: ZBX_SERVER_HOST
          value: "zabbix-server.kertenkerem.local" # Zabbix Server IP veya FQDN'iniz
    
    zabbixAgent:
      enabled: true
      resources:
        limits:
          cpu: 200m
          memory: 256Mi
        requests:
          cpu: 50m
          memory: 64Mi
      env:
        - name: ZBX_HOSTNAMEITEM
          value: "system.hostname"

    Bu konfigürasyon ile cluster içinde bir DaemonSet olarak Zabbix Agent 2 ve cluster dışındaki ana sunucumuza verileri güvenli ve sıkıştırılmış şekilde iletecek bir Zabbix Proxy ayağa kaldırıyoruz. Kurulumu şu komutla tetikleyelim:

    kubectl create namespace monitoring
    helm install zabbix zabbix-community/zabbix-helm-ch --namespace monitoring -f zabbix-values.yaml

    Adım 2: Auto-Discovery (LLD) ile Metrik Avcılığı

    Kubernetes dinamik bir yapıya sahiptir; pod’lar saniyeler içinde ölür, yenileri doğar. Statik IP’ler veya host tanımlamaları burada sökmez. Zabbix 7.x, bu kaosu çözmek için Low-Level Discovery (LLD) mekanizmasını kullanır. Kubernetes API Server üzerinden pods, nodes, namespaces ve services discovery kurallarını çalıştırır.

    Zabbix Web UI arayüzüne giriş yaptıktan sonra şu adımları izleyin:

    1. API Token Oluşturma

    Zabbix Server’ın cluster API’si ile konuşabilmesi için Helm kurulumu sırasında otomatik oluşturulan service account token’ını almamız gerekiyor:

    kubectl get secret $(kubectl get serviceaccount zabbix-service-account -n monitoring -o jsonpath="{.secrets[0].name}") -n monitoring -o jsonpath="{.data.token}" | base64 --decode

    Not: Kubernetes 1.24 ve üzeri kullanıyorsanız, secret manuel oluşturulmuş olabilir. Helm chart bunu sizin için halletmediyse, service account için bir `kubernetes.io/service-account-token` tipinde Secret oluşturup token’ı oradan okumalısınız.

    2. Zabbix Üzerinde Host Tanımlama

    • Configuration -> Hosts -> Create Host yolunu izleyin.
    • Host Name alanına Kubernetes Cluster Production yazın.
    • Templates kısmına “Kubernetes by HTTP” template’ini ekleyin. Bu template, Zabbix 7.0 ile gelen out-of-the-box harika bir canavardır.
    • Macros sekmesine geçiş yapın ve aşağıdaki kritik değişkenleri tanımlayın:
    {$KUBE.API.URL} -> https://<kubernetes-api-endpoint>:6443
    {$KUBE.API.TOKEN} -> <Bir önceki adımda elde ettiğiniz token>

    Bu tanımlamadan sonra Zabbix, HTTP agent yardımıyla cluster API’nize sorgu atmaya başlayacak. Birkaç dakika içinde “Discovery rules” altındaki kuralların tetiklendiğini ve cluster’ınızdaki tüm node’ların, pod’ların ve container’ların otomatik olarak sisteme “Graph” ve “Item” olarak eklendiğini göreceksiniz. İşte auto-discovery’nin gücü!

    Adım 3: Grafana Entegrasyonu (Görsel Şölen)

    Zabbix’in kendi arayüzündeki grafikler son yıllarda iyileşmiş olsa da, hiçbirimiz yöneticilerimize veya development ekiplerine o 90’lardan kalma görünümlü panelleri göstermek istemeyiz. Bize Grafana lazım.

    Grafana üzerinde Zabbix veri kaynağını (datasource) aktifleştirmek için şu adımları izliyoruz:

    grafana-cli plugins install alexanderzobnin-zabbix-app
    systemctl restart grafana-server

    Grafana arayüzüne gidip Connections -> Data Sources -> Add New Data Source dedikten sonra listeden Zabbix’i seçiyoruz. Konfigürasyon ayarlarında dikkat etmeniz gereken kritik noktalar şunlar:

    • URL: http://zabbix-server-ip/zabbix/api_jsonrpc.php
    • Access: Server (Default)
    • Zabbix API Connection: Zabbix admin kullanıcı adı ve şifreniz.

    Bağlantıyı test edip kaydettikten sonra, Kubernetes cluster metriklerimizi içeren dashboard’ları tasarlayabiliriz. Örneğin, her pod’un CPU tüketimini dinamik olarak çeken bir panel yazmak istersek, Grafana query alanına şu regex’i girebiliriz:

    Group: Kubernetes
    Host: /.*/
    Application: CPU
    Item: /Calculated CPU usage percent/

    Bu sorgu sayesinde, cluster’a yeni bir mikroservis deploy edildiğinde hiçbir manuel müdahale yapmadan o servisin CPU grafiği saniyeler içinde Grafana panelinizde belirecektir.

    Adım 4: Akıllı Alerting Kuralları

    Gecenin saat 3’ünde “Pod restart attı” diye uyanmak istemiyorsanız, Zabbix’in esnek trigger yapısını doğru kurgulamanız gerekir. Klasik CPU doldu alert’leri yerine Kubernetes dünyasına uygun akıllı trigger’lar yazmalıyız.

    Örnek 1: CrashLoopBackOff Durumu tespiti

    Bir pod sürekli hata alıp kapanıyorsa ve restart sayısı artıyorsa, bu kritik bir durumdur. Zabbix template’i içinde gelen varsayılan kuralı özelleştirebiliriz:

    last(/Kubernetes by HTTP/kube.pod.restart_rate[{#POD.NAME}]) > 3 and last(/Kubernetes by HTTP/kube.pod.status[{#POD.NAME}]) = 0

    Bu trigger, pod’un son 5 dakika içindeki restart hızı 3’ten fazla ise ve pod “Ready” durumunda değilse alarm üretir. Geçici network kesintilerinde boşuna Slack kanallarınızı spam’lemez.

    Örnek 2: Node Disk Basıncı (Disk Pressure)

    Kubelet’in node üzerindeki pod’ları evict etmeye başlamadan (yani sistem dışına atmadan) önce diskin dolduğunu anlamamız gerekir:

    last(/Kubernetes by HTTP/kube.node.status.disk_pressure[{#NODE.NAME}]) = 1

    Bu alarm tetiklendiğinde, Zabbix’in Webhook entegrasyonu sayesinde Slack veya PagerDuty üzerinden anlık bildirim alabilir, hatta otomatik aksiyon (Remote Command) tanımlayarak ilgili node üzerindeki gereksiz docker imajlarını temizleyen bir script çalıştırabilirsiniz.

    Zabbix 7.x Kubernetes Monitoring’in Avantaj ve Dezavantajları

    Her sistemde olduğu gibi bu mimarinin de güçlü ve zayıf yanları var. Kararınızı vermeden önce bunları masaya yatıralım:

    Avantajları Dezavantajları
    Düşük kaynak tüketimi (RAM/CPU dostu) Kubernetes native olmaması (Prometheus operator kadar cluster içine entegre değil)
    Merkezi yönetim ve güçlü LLD yetenekleri Custom Metric API ile HPA (Horizontal Pod Autoscaler) entegrasyonu görece zor
    Uzun vadeli verileri saklamada veritabanı esnekliği (PostgreSQL/TimescaleDB) Grafana template kütüphanesinin Prometheus kadar zengin olmaması

    Sonuç

    Zabbix 7.x, Kubernetes cluster’larını izlemek için hantal ve “outdated” bir çözüm olmaktan çok uzak. Aksine, kaynak tüketimini minimize etmek isteyen ve tüm IT altyapısını (fiziksel, sanal, container) tek bir merkezi noktadan yönetmeyi hedefleyen kıdemli sistem ve devops mühendisleri için biçilmiş kaftan. Auto-discovery mekanizmasının gücü ve Grafana’nın görsel yetenekleri birleştiğinde, production ortamınızda uçtan uca izlenebilirlik (observability) sağlamak işten bile değil.

    Siz de cluster’larınızda Zabbix kullanmayı denediniz mi? Yaşadığınız tecrübeleri veya takıldığınız yerleri yorumlarda bizimle paylaşın, debugging seansına beraber devam edelim!

    Category: Genel | LEAVE A COMMENT