Zabbix’te Maintenance Periyodu Tanımlama

Gece yarısı telefon çalıyor, NOC ekibinden biri arıyor: “Abla, şu sunuculara güncelleme atacağız, Zabbix’ten alarm yağmasın diye ne yapacağız?” İşte tam bu noktada maintenance periyotları devreye giriyor. Zabbix’in en kullanışlı özelliklerinden biri olan bu mekanizma, planlı bakım pencerelerinde gereksiz alarm kirliliğini önler ve hem siz hem de ekibiniz sabaha kadar gereksiz stres yaşamaz.

Maintenance Periyodu Nedir ve Neden Önemlidir

Zabbix’teki maintenance periyodu, belirli bir zaman aralığında host veya host gruplarına yönelik bildirim mekanizmasını askıya almanızı sağlar. Ama burada ince bir nokta var: maintenance aktifken veri toplanmaya devam eder, sadece tetiklenen problemler için bildirim gitmez. Bu ayrımı çok iyi anlamak gerekiyor çünkü bazı ekipler “maintenance açtık, veri de toplanmıyor” yanılgısına düşüyor.

İki temel maintenance türü var:

  • With data collection: İzleme devam eder, trigger’lar ateşlenir ama bildirim gitmez. Problem log’u tutulmaya devam eder.
  • No data collection: Host’a hiçbir istek gönderilmez, veri toplanmaz. Gerçek anlamda “sessiz mod” budur.

Çoğu senaryo için birinci tip yeterli. Özellikle ağ cihazlarını yeniden başlatıyorsanız ya da kernel güncelleme sonrası reboot yapıyorsanız, No data collection daha temiz bir deneyim sunar.

Zabbix API ile Maintenance Oluşturma

Arayüzden tıklayarak da maintenance açabilirsiniz ama bu yaklaşım ölçeklenmiyor. Onlarca sunucuya aynı anda bakım penceresi açmanız gerektiğinde, Zabbix API’si hayat kurtarır. Önce bir authentication token alalım:

curl -s -X POST 
  -H "Content-Type: application/json" 
  -d '{
    "jsonrpc": "2.0",
    "method": "user.login",
    "params": {
      "username": "Admin",
      "password": "zabbix"
    },
    "id": 1
  }' 
  http://zabbix.sirket.local/zabbix/api_jsonrpc.php

Bu isteğin döndürdüğü result alanındaki string bizim auth token’ımız. Bunu bir değişkene atalım ve maintenance oluşturalım:

TOKEN="abc123def456"
SIMDI=$(date +%s)
BITIS=$((SIMDI + 7200))  # 2 saatlik pencere

curl -s -X POST 
  -H "Content-Type: application/json" 
  -d "{
    "jsonrpc": "2.0",
    "method": "maintenance.create",
    "params": {
      "name": "Patch Tuesday - Web Sunucular",
      "active_since": ${SIMDI},
      "active_till": ${BITIS},
      "hostids": ["10084", "10085", "10086"],
      "timeperiods": [
        {
          "timeperiod_type": 0,
          "start_date": ${SIMDI},
          "period": 7200
        }
      ],
      "maintenance_type": 0
    },
    "auth": "${TOKEN}",
    "id": 2
  }" 
  http://zabbix.sirket.local/zabbix/api_jsonrpc.php

Burada maintenance_type: 0 veri toplamaya devam eden türü, maintenance_type: 1 ise veri toplamayan türü temsil ediyor. timeperiod_type: 0 ise tek seferlik (one time only) periyot anlamına geliyor.

Shell Script ile Toplu Maintenance Yönetimi

Gerçek ortamda tek bir sunucu için değil, bir host grubunun tamamı için maintenance açmak daha mantıklı. Şu script’i production’da kullanıyoruz:

#!/bin/bash
# zabbix_maintenance.sh
# Kullanim: ./zabbix_maintenance.sh <group_adi> <sure_dakika> <aciklama>

ZABBIX_URL="http://zabbix.sirket.local/zabbix/api_jsonrpc.php"
ZABBIX_USER="automation_user"
ZABBIX_PASS="guclu_sifre_buraya"

GROUP_ADI="${1:-'Linux Servers'}"
SURE_DK="${2:-60}"
ACIKLAMA="${3:-'Otomatik bakım penceresi'}"

# Token al
TOKEN=$(curl -s -X POST 
  -H "Content-Type: application/json" 
  -d "{
    "jsonrpc": "2.0",
    "method": "user.login",
    "params": {
      "username": "${ZABBIX_USER}",
      "password": "${ZABBIX_PASS}"
    },
    "id": 1
  }" "${ZABBIX_URL}" | python3 -c "import sys,json; print(json.load(sys.stdin)['result'])")

echo "Token alindi: ${TOKEN:0:8}..."

# Host group ID bul
GROUP_ID=$(curl -s -X POST 
  -H "Content-Type: application/json" 
  -d "{
    "jsonrpc": "2.0",
    "method": "hostgroup.get",
    "params": {
      "filter": {"name": ["${GROUP_ADI}"]}
    },
    "auth": "${TOKEN}",
    "id": 2
  }" "${ZABBIX_URL}" | python3 -c "import sys,json; data=json.load(sys.stdin); print(data['result'][0]['groupid'])")

echo "Group ID: ${GROUP_ID}"

SIMDI=$(date +%s)
BITIS=$((SIMDI + SURE_DK * 60))
MAINTENANCE_ADI="${ACIKLAMA} - $(date '+%Y-%m-%d %H:%M')"

# Maintenance olustur
RESULT=$(curl -s -X POST 
  -H "Content-Type: application/json" 
  -d "{
    "jsonrpc": "2.0",
    "method": "maintenance.create",
    "params": {
      "name": "${MAINTENANCE_ADI}",
      "active_since": ${SIMDI},
      "active_till": ${BITIS},
      "groupids": ["${GROUP_ID}"],
      "timeperiods": [
        {
          "timeperiod_type": 0,
          "start_date": ${SIMDI},
          "period": $((SURE_DK * 60))
        }
      ],
      "maintenance_type": 0,
      "description": "${ACIKLAMA}"
    },
    "auth": "${TOKEN}",
    "id": 3
  }" "${ZABBIX_URL}")

echo "Sonuc: ${RESULT}"

Bu script’i çalıştırmadan önce automation için ayrı bir Zabbix kullanıcısı oluşturmanızı öneririm. Admin hesabıyla API çağrısı yapmak güvenlik açısından kötü pratik.

Tekrarlayan Maintenance Periyotları

Her Salı gece saat 02:00’de güncelleme yapıyorsanız, her seferinde elle maintenance açmak yerine tekrarlayan periyot tanımlayabilirsiniz. Zabbix arayüzünde bunu yapmak için Configuration > Maintenance yolunu izleyip yeni bir maintenance oluştururken timeperiod bölümünde “Every week” seçeneğini kullanabilirsiniz. API üzerinden ise şöyle görünüyor:

curl -s -X POST 
  -H "Content-Type: application/json" 
  -d "{
    "jsonrpc": "2.0",
    "method": "maintenance.create",
    "params": {
      "name": "Haftalik Patch Penceresi - Veritabani",
      "active_since": 1700000000,
      "active_till": 1800000000,
      "groupids": ["15"],
      "timeperiods": [
        {
          "timeperiod_type": 2,
          "dayofweek": 2,
          "start_time": 7200,
          "period": 3600
        }
      ],
      "maintenance_type": 0
    },
    "auth": "${TOKEN}",
    "id": 3
  }" 
  http://zabbix.sirket.local/zabbix/api_jsonrpc.php

Buradaki parametreleri açayım:

  • timeperiod_type: 2: Haftalık tekrar
  • dayofweek: 2: Salı günü (1=Pazartesi, 2=Salı, …, 7=Pazar)
  • start_time: 7200: Gece 02:00 (saniye cinsinden, 7200 saniye = 2 saat)
  • period: 3600: 1 saatlik pencere
  • active_since / active_till: Bu maintenance tanımının geçerli olduğu tarih aralığı

active_since ve active_till alanları, tekrarlayan maintenance’ın hangi tarihler arasında aktif olacağını belirler. Örneğin bir projenin beta dönemi boyunca her hafta maintenance açmak istiyorsanız bu alanlar çok işe yarıyor.

Maintenance Sırasında Problem Davranışı

Bir şey önemli: Maintenance başlamadan önce zaten açık olan bir problem, maintenance boyunca bildirim almaya devam eder mi? Hayır. Zabbix, maintenance aktifken mevcut problemleri de susturur. Maintenance bittiğinde ise hala aktif olan problemler için bildirim tetiklenip tetiklenmeyeceği trigger’ın kendisine bağlı. Generate multiple ALARMS seçeneği açıksa bildirim gelir, kapalıysa gelmez.

Bu davranışı test etmek için şu Python betiğini kullanabilirsiniz:

#!/usr/bin/env python3
"""
Zabbix aktif maintenance durumunu kontrol eder
"""
import requests
import json
from datetime import datetime

ZABBIX_URL = "http://zabbix.sirket.local/zabbix/api_jsonrpc.php"

def get_token(user, password):
    payload = {
        "jsonrpc": "2.0",
        "method": "user.login",
        "params": {"username": user, "password": password},
        "id": 1
    }
    r = requests.post(ZABBIX_URL, json=payload)
    return r.json()["result"]

def get_active_maintenances(token):
    simdi = int(datetime.now().timestamp())
    payload = {
        "jsonrpc": "2.0",
        "method": "maintenance.get",
        "params": {
            "output": "extend",
            "selectHosts": ["host", "name"],
            "selectGroups": ["name"],
            "filter": {}
        },
        "auth": token,
        "id": 2
    }
    r = requests.post(ZABBIX_URL, json=payload)
    maintenances = r.json()["result"]
    
    aktif = []
    for m in maintenances:
        bitis = int(m["active_till"])
        if bitis > simdi:
            aktif.append({
                "id": m["maintenanceid"],
                "name": m["name"],
                "bitis": datetime.fromtimestamp(bitis).strftime("%Y-%m-%d %H:%M"),
                "hosts": [h["name"] for h in m.get("hosts", [])],
                "gruplar": [g["name"] for g in m.get("groups", [])]
            })
    return aktif

token = get_token("Admin", "zabbix")
aktif_maintenanceler = get_active_maintenances(token)

for m in aktif_maintenanceler:
    print(f"[{m['id']}] {m['name']}")
    print(f"  Bitis: {m['bitis']}")
    print(f"  Hostlar: {', '.join(m['hosts']) if m['hosts'] else '-'}")
    print(f"  Gruplar: {', '.join(m['gruplar']) if m['gruplar'] else '-'}")
    print()

Ansible ile Zabbix Maintenance Entegrasyonu

DevOps ekipleri için daha ilginç bir senaryo: Ansible playbook çalışmadan önce otomatik maintenance aç, playbook bitince kapat. Ansible’ın community.zabbix koleksiyonu bunu çok kolaylaştırıyor:

---
- name: Web Sunucu Guncelleme Playbook
  hosts: web_sunuculari
  gather_facts: false

  pre_tasks:
    - name: Zabbix maintenance baslat
      community.zabbix.zabbix_maintenance:
        server_url: "http://zabbix.sirket.local/zabbix"
        login_user: "automation_user"
        login_password: "{{ vault_zabbix_pass }}"
        name: "Ansible - {{ inventory_hostname }} guncelleme"
        host_names:
          - "{{ inventory_hostname }}"
        state: present
        collect_data: true
        minutes: 30
        desc: "Otomatik Ansible guncelleme maintenance"
      delegate_to: localhost

  tasks:
    - name: Paketleri guncelle
      ansible.builtin.apt:
        upgrade: dist
        update_cache: true
      become: true

    - name: Gerekirse yeniden baslat
      ansible.builtin.reboot:
        reboot_timeout: 300
      become: true
      when: ansible_os_family == "Debian"

  post_tasks:
    - name: Zabbix maintenance kapat
      community.zabbix.zabbix_maintenance:
        server_url: "http://zabbix.sirket.local/zabbix"
        login_user: "automation_user"
        login_password: "{{ vault_zabbix_pass }}"
        name: "Ansible - {{ inventory_hostname }} guncelleme"
        state: absent
      delegate_to: localhost

Bu yapıda pre_tasks ve post_tasks bloklarını kullanmak kritik. Eğer playbook bir sebepten başarısız olursa, post_tasks hala çalışır ve maintenance’ı kapatır. Tabii bunun için --force-handlers bayrağını da playbook’a eklemek iyi bir pratik.

Eski Maintenance Kayıtlarını Temizleme

Zaman içinde Zabbix veritabanında onlarca, bazen yüzlerce eski maintenance kaydı birikir. Bunları temizlemek hem veritabanı performansı açısından hem de arayüz karmaşıklığını azaltmak açısından önemli. API ile süresi geçmiş maintenance’ları bulup silelim:

#!/bin/bash
# Suresi gecmis maintenance kayitlarini temizle

ZABBIX_URL="http://zabbix.sirket.local/zabbix/api_jsonrpc.php"
TOKEN=$(./get_token.sh)  # Token'i ayri bir scriptten al
SIMDI=$(date +%s)

# Suresi gecmis kayitlari bul
ESKI_IDS=$(curl -s -X POST 
  -H "Content-Type: application/json" 
  -d "{
    "jsonrpc": "2.0",
    "method": "maintenance.get",
    "params": {
      "output": ["maintenanceid", "name", "active_till"]
    },
    "auth": "${TOKEN}",
    "id": 1
  }" "${ZABBIX_URL}" | python3 -c "
import sys, json
data = json.load(sys.stdin)
simdi = ${SIMDI}
eski = [m['maintenanceid'] for m in data['result'] 
        if int(m['active_till']) < simdi - 86400]  # 1 gunden eski
print(json.dumps(eski))
")

echo "Silinecek maintenance sayisi: $(echo $ESKI_IDS | python3 -c 'import sys,json; print(len(json.load(sys.stdin)))')"

# Sil
if [ "$(echo $ESKI_IDS | python3 -c 'import sys,json; print(len(json.load(sys.stdin)))')" -gt "0" ]; then
  curl -s -X POST 
    -H "Content-Type: application/json" 
    -d "{
      "jsonrpc": "2.0",
      "method": "maintenance.delete",
      "params": ${ESKI_IDS},
      "auth": "${TOKEN}",
      "id": 2
    }" "${ZABBIX_URL}"
  echo "Temizlik tamamlandi."
else
  echo "Silinecek kayit yok."
fi

Bu script’i cron’a ekleyip her Pazar gece çalıştırabilirsiniz. 30 gün geçmiş tüm maintenance kayıtlarını temizlemek için eşiği 86400 * 30 olarak değiştirin.

Gözden Kaçan Detaylar ve Pratik Öneriler

Yıllarca Zabbix kullananların sıklıkla düştüğü birkaç tuzak var:

  • Saat dilimi sorunları: Zabbix sunucusu UTC’de çalışıyorken siz Türkiye saatiyle maintenance açmaya çalışırsanız 3 saatlik kayma yaşarsınız. API’ye gönderdiğiniz timestamp’lerin her zaman UTC tabanlı olduğunu unutmayın. date -u +%s kullanın, date +%s değil.
  • Host vs Host Group önceliği: Bir host hem bir grup maintenance’ında hem de bireysel host maintenance’ında yer alıyorsa, ikisi de aynı anda aktif olabilir. Bu çakışma sorun yaratmaz ama yönetimi zorlaştırır. Mümkünse ya group bazlı ya da host bazlı tutun, ikisini karıştırmayın.
  • Zabbix Proxy ortamları: Eğer proxy kullanıyorsanız, maintenance bilgisi proxy’e iletilmesi biraz zaman alabilir. Özellikle passive proxy’lerde bu gecikme fark edilebilir oluyor. Maintenance’ı bakım başlamadan 5-10 dakika önce açmak bu sorunu pratik olarak çözer.
  • Tags ile maintenance: Zabbix 6.0 ve sonrasında maintenance’ları host tag’leri ile ilişkilendirebilirsiniz. Örneğin env:production tagine sahip tüm hostlara maintenance açmak mümkün. Bu özelliği kullanmak, bakım süreçlerini çok daha granüler hale getirir.
  • Maintenance sırasında eskalasyon: Normal şartlarda Zabbix problemler için eskalasyon action’ları tetikler. Maintenance aktifken bu eskalasyonlar da durur. Maintenance bittiğinde hala açık olan problemler için eskalasyon sıfırdan başlar, kaldığı yerden devam etmez.

Sonuç

Zabbix maintenance periyotları, görünürde basit bir özellik gibi dursa da doğru kullanıldığında operasyonel olgunluğun önemli bir göstergesi haline gelir. Ham alarm sayısını düşürür, NOC ekibinin güvenini artırır ve “bu alarm önemli mi değil mi” yorgunluğunu azaltır.

Şu üç noktayı akılda tutmak yeterli: maintenance açmayı manuel bir işlem olmaktan çıkarın ve CI/CD ya da Ansible pipeline’ınıza entegre edin; timestamp’lerde UTC dikkatini asla elden bırakmayın; ve periyodik temizlik yapmazsanız birkaç ay içinde yüzlerce atıl kayıtla karşı karşıya kalırsınız. Bunların üçü de öğrenilmesi kolay ama öğrenilmediğinde ciddi operasyonel acılara yol açan detaylar. Ekibinize bu alışkanlıkları kazandırdığınızda, gece yarısı telefon çalmayı büyük ölçüde azaltmış olursunuz.

Bir yanıt yazın

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