Hızlı Özet: Zabbix 7.0 LTS ve PostgreSQL/TimescaleDB yığınının Docker Compose ile VDS üzerinde kararlı çalışması için asgari 2 vCPU (%0 steal time), 4 GB RAM (chunk buffer tahsisli), 40 GB NVMe (yüksek 4K QD1 IOPS) ve 1 Gbps uplink gereklidir. Metrik toplama hattı Docker bridge ağında izole edilerek sunucu-ajan trafiğinde 10050/10051 TCP üzerinden TLS-PSK şifrelemesi ve ağ donanımlarında SHA-256/AES-256 destekli SNMPv3 protokolüyle güvenceye alınmalıdır. Linux çekirdeğinde vm.overcommit_memory=1 ve net.core.somaxconn=1024 parametreleri optimize edildiğinde, tek bir KVM VDS üzerinde I/O darboğazı yaşamadan saniyede 1.000+ yeni değer (NVPS) işleme kapasitesine ulaşılır.
İçindekiler
- Zabbix İçin KVM VDS Donanım Gereksinimleri ve Boyutlandırma
- Linux Çekirdek Optimizasyonu ve PostgreSQL 16 Parametreleri
- Docker Compose ile Zabbix Server, Web ve DB Dağıtımı
- Nginx SSL Ters Proxy ve Güvenlik Sıkılaştırma
- Zabbix Agent 2 Kurulumu ve Telegram Bildirim Entegrasyonu
- Veritabanı Bakımı ve Adım Adım Felaket Kurtarma (Disaster Recovery)
- Sıkça Sorulan Sorular (SSS)
Zabbix İçin KVM VDS Donanım Gereksinimleri ve Boyutlandırma
Zabbix mimarisinde sunucu boyutlandırması, geleneksel sunucu metriklerinden (CPU çekirdek sayısı veya toplam RAM miktarı) önce doğrudan NVPS (New Values Per Second — Saniye Başına Yeni Değer) metrik hacmi ve veritabanı arka ucunun (PostgreSQL) ürettiği disk G/Ç (I/O) paternleri üzerinden hesaplanır. Docker üzerinde Zabbix VDS kurulumu gerçekleştirirken konteyner izolasyon katmanının getirdiği I/O ek yükü (overlay2 storage driver ve Docker bridge ağı), alttaki sanallaştırma mimarisinin donanıma doğrudan erişim hızını kritik bir parametreye dönüştürür.
1. NVPS (Saniye Başına Yeni Değer) Matematiksel Modellemesi
NVPS, Zabbix Server süreçlerinin (poller, trapper, snmp poller, icmp pinger) saniyede topladığı ve PostgreSQL history_syncer süreçlerine aktardığı veri noktası sayısını ifade eder. Sistem üzerindeki host ve item envanteri bilindiğinde teorik NVPS şu formülle hesaplanır:
$$\text{NVPS} = \sum_{i=1}^{N} \frac{\text{İzlenen Öğe Sayısı}_i}{\text{Yenileme Aralığı (sn)}_i}$$
Örneğin, 250 adet Linux sunucusunun her birinden 80 adet işletim sistemi metriği (CPU, RAM, disk, network) 30 saniyelik periyotlarla; 50 adet ağ anahtarından ise (SNMPv2/v3) port başına 10 metrik 60 saniyelik periyotlarla toplanıyorsa:
$$\text{NVPS}_{\text{Agent}} = \frac{250 \times 80}{30} = 666.6 \text{ değer/sn}$$
$$\text{NVPS}_{\text{SNMP}} = \frac{50 \times 48 \text{ port} \times 10}{60} = 4.000 \text{ değer/sn}$$
$$\text{Toplam NVPS} \approx 4.667 \text{ değer/sn}$$
Bu değer, Zabbix Server'ın her saniye bellekteki veri kuyruğuna 4.667 yeni satır eklemesi ve PostgreSQL'e toplu (batch) yazma işlemi gerçekleştirmesi gerektiği anlamına gelir.
2. PostgreSQL Disk Boyutu ve Veri Akışı Hesaplaması
PostgreSQL üzerinde standart Zabbix şemasında history (float değerler), history_uint (tamsayılar), history_str (metinler) ve trends tabloları bulunur. Standart bir PostgreSQL veri tabanında (TimescaleDB sıkıştırması devre dışıyken) tek bir geçmiş kaydının disk maliyeti yaklaşık 90 ila 120 bayttır:
- Tuple başlığı (Heap header): 23–24 bayt
- Kolon verisi (
itemid,clock,value,ns): 24 bayt - B-Tree İndeks ek yükü (
itemid_clockindeksi): ~40–50 bayt - Sayfa hizalama ve boşluk dolgusu (Padding): ~8 bayt
TimescaleDB eklentisi (chunk-based compression) devreye alındığında, LZ4/ZSTD tabanlı kolonel sıkıştırma sayesinde satır başı maliyet 15–25 bayt bandına geriler.
Günlük saf disk artışı formülü:
$$\text{Günlük Disk (GB)} = \frac{\text{NVPS} \times \text{Kayıt Boyutu (Bayt)} \times 86.400}{1024^3}$$
Örnek Senaryo: 2.000 NVPS Altında Günlük Depolama
- Ham PostgreSQL (110 Bayt/kayıt):
$$\frac{2.000 \times 110 \times 86.400}{1.073.741.824} \approx 17.69 \text{ GB/gün} \implies 30 \text{ günde } \approx 530 \text{ GB}$$ - TimescaleDB ile Sıkıştırılmış (20 Bayt/kayıt):
$$\frac{2.000 \times 20 \times 86.400}{1.073.741.824} \approx 3.22 \text{ GB/gün} \implies 30 \text{ günde } \approx 96.6 \text{ GB}$$
Docker konteynerleri içinde Zabbix çalıştırılırken history verisi Docker container katmanına değil, doğrudan ana makineden bind-mount veya named volume ile bağlanan kalıcı NVMe depolama alanına yazılmalıdır.
3. Disk IOPS ve Gecikme (Latency) Dinamikleri
Zabbix veritabanı I/O profili asimetriktir: %85–90 Yazma (Write), %10–15 Okuma (Read). Ancak bu yazma işlemi saf sıralı (sequential) değil, B-tree indeks güncellemeleri ve WAL (Write-Ahead Logging) fsync çağrıları nedeniyle yoğun rastgele (random) 4K/8K blok operasyonlarından oluşur.
PostgreSQL history_syncer süreçleri veriyi shared_buffers üzerinden diske aktarırken iki darboğaz oluşur: 1. WAL Flush Gecikmesi: Zabbix trapper/poller süreçleri veriyi teslim aldığında transaction commit anında WAL kaydı diske fdatasync() ile yazılmalıdır. Disk p99 fsync gecikmesi 2 milisaniyenin üzerine çıktığı anda history_syncer süreçleri kilitlenir (%100 busy) ve Zabbix kuyruğu (queue) dakikalar içinde şişer. 2. Checkpoint Fırtınası: PostgreSQL max_wal_size sınırına ulaştığında tüm kirli sayfalar (dirty pages) diske flush edilir. Yetersiz IOPS sunan ortamlarda disk I/O util% değeri %100'e oturur ve web arayüzü 504 Gateway Timeout üretir.
Bu operasyonel gereksinimler doğrultusunda saniye başına ihtiyaç duyulan taban IOPS formülü:
$$\text{Gerekli IOPS} \approx (\text{NVPS} \times 1.5) + \text{Checkpoint Buffer IOPS} + \text{Read/Housekeeper IOPS}$$
| NVPS Yükü | Minimum Sürekli Yazma IOPS (4K) | Zirve (Burst/Checkpoint) IOPS | Hedef p99 fsync Gecikmesi |
|---|---|---|---|
| 500 NVPS | 800 IOPS | 2.500 IOPS | $< 2.0\text{ ms}$ |
| 2.000 NVPS | 3.500 IOPS | 10.000 IOPS | $< 1.0\text{ ms}$ |
| 5.000 NVPS | 9.000 IOPS | 25.000 IOPS | $< 0.8\text{ ms}$ |
| 10.000+ NVPS | 20.000+ IOPS | 50.000+ IOPS | $< 0.5\text{ ms}$ |
4. Sanallaştırma Katmanı: KVM ve CPU Steal Time (%st) Kriteri
KVM tabanlı bir VDS üzerinde Docker ile Zabbix mimarisi kurgulanırken hipervizör düzeyindeki kaynak dağıtımı doğrudan metrik toplama doğruluğunu belirler. OpenVZ veya LXC gibi paylaşımlı çekirdek mimarilerinde diğer kiracıların I/O patlamaları ana çekirdek üzerinde kilitlenmelere yol açar. KVM üzerinde ise ayrılmış vCPU'lar doğrudan donanım sanallaştırma komut setlerine (Intel VT-x / AMD-V) erişir.
Buradaki en kritik sistem metriği CPU Steal Time (%st) değeridir:
# CPU Steal Time ve I/O Wait oranını anlık denetleme
sar -u 1 5
Çıktıda %st alanının 0.00 olması zorunludur:
Linux 6.8.0-45-generic (zabbix-prod) 04.10.2026 _x86_64_ (8 CPU)
13:40:01 CPU %user %nice %system %iowait %steal %idle
13:40:02 all 18.25 0.00 4.80 0.15 0.00 76.80
13:40:03 all 19.10 0.00 5.10 0.12 0.00 75.68
Hipervizörde aşırı kaynak tahsisi (oversubscription) olduğunda %st değeri %1–2 seviyesine bile çıksa, Zabbix poller süreçleri zamanında uyandırılamaz; bu durum geçersiz "Host unreachable" alarmlarına ve yanlış pozitif bildirimlere sebep olur. Altyapı sağlayıcısının fiziksel işlemci çekirdeklerini birebir izole edebilmesi şarttır. Bu doğrultuda tropic.host bulut altyapısında sunulan KVM VDS çözümleri, sıfır aşırı abonelik (%st = 0.0%) garantisi ve kurumsal sınıf PCIe 4.0 NVMe SSD sürücüleri (4K QD1 rastgele okumada 50.000+ IOPS) ile Zabbix ve PostgreSQL arka ucunun ihtiyaç duyduğu kesintisiz I/O hattını donanımsal olarak temin eder.
5. KVM VDS Donanım ve Boyutlandırma Matrisi
Aşağıdaki tablo, Docker Compose üzerinde konuşlandırılan Zabbix 7.0+ LTS, PostgreSQL 16 ve TimescaleDB bileşenleri için test edilmiş ve doğrulanmış donanım profillerini göstermektedir:
| Metrik Profili | NVPS Aralığı | İzlenen Host / Öğe | vCPU & Çekirdek Tipi | Sistem Belleği (RAM) | PostgreSQL shared_buffers |
Disk Mimarisi (IOPS Kapasitesi) | tropic.host Önerilen VDS Profili |
|---|---|---|---|---|---|---|---|
| Starter | $100 - 500$ | 50 host / 5.000 öğe | 2 vCPU (Yüksek Frekans $\ge 3.5\text{ GHz}$) | 4 GB | 1 GB | 50 GB PCIe NVMe ($> 3.000\text{ IOPS}$) | KVM-NVMe-Starter (2 vCPU / 4 GB RAM) |
| Production Mid | $1.000 - 3.000$ | 300 host / 30.000 öğe | 4–8 vCPU (AMD EPYC / Ryzen 9) | 16 GB | 4 GB | 200 GB Enterprise NVMe ($> 15.000\text{ IOPS}$) | KVM-NVMe-Pro (6 vCPU / 16 GB RAM) |
| Enterprise High | $5.000 - 10.000$ | 1.200 host / 120.000 öğe | 12–16 vCPU (AMD EPYC $\ge 3.7\text{ GHz}$) | 32–64 GB | 12–16 GB | 500 GB PCIe 4.0 NVMe ($> 40.000\text{ IOPS}$) | KVM-NVMe-Ultra (16 vCPU / 64 GB RAM) |
| Hyperscale | $> 15.000$ | 3.000+ host / 300.000+ öğe | 24+ vCPU (Ayrılmış Çekirdek) | 128 GB | 32 GB | $2 \times 1\text{ TB}$ NVMe (RAID1 / Direct-I/O) | KVM-Dedicated-Node (32 vCPU / 128 GB RAM) |
6. Üretim Öncesi Disk Doğrulama ve Linux Çekirdek Optimizasyonu
Docker stack kurulumuna geçilmeden önce VDS disk altyapısının Zabbix WAL yazma yükünü taşıyıp taşımayacağı fio ile sentetik olarak test edilmelidir:
# PostgreSQL fdatasync gecikmesini doğrudan test eden benchmark komutu
fio --name=pg-wal-benchmark \
--filename=/var/lib/docker/wal_test.dat \
--size=2G \
--ioengine=sync \
--fdatasync=1 \
--rw=write \
--bs=8k \
--numjobs=1 \
--direct=1 \
--group_reporting \
--runtime=60 \
--time_based
Bu test sonucunda raporlanan clat (completion latency) yüzdelik dilimlerinde 99.00th persentil değeri 1.50 ms altında kalmalıdır.
Çekirdek ve Sanal Bellek Ayarları
Zabbix konteynerlerinin konuşlanacağı ana makinede bellek taşmalarını ve agresif swap kullanımını engellemek için /etc/sysctl.d/99-zabbix-performance.conf dosyası oluşturulmalıdır:
# Disk yazma gecikmesini düşürmek için dirty memory buffer optimizasyonu
vm.dirty_background_ratio = 5
vm.dirty_ratio = 10
# Zabbix ve PostgreSQL bellekten diske swap yapmamalıdır
vm.swappiness = 1
# Bellek tahsisinde OOM-Killer'ın kontrolsüz çalışmasını engelleme
vm.overcommit_memory = 2
vm.overcommit_ratio = 80
# Ağ soket kuyruğu ve dosya tanımlayıcı sınırları
net.core.somaxconn = 4096
fs.file-max = 2097152
Söz konusu çekirdek parametreleri kalıcı hale getirilip uygulanır:
sysctl -p /etc/sysctl.d/99-zabbix-performance.conf
Doğru boyutlandırılmış KVM donanımı, izole edilmiş NVMe depolama alanı ve sıfır steal time faktörü sağlandığında, Docker üzerindeki Zabbix mimarisi binlerce host için gecikmesiz, stabil ve kesintisiz bir izleme omurgası sunar.
Linux Çekirdek Optimizasyonu ve PostgreSQL 16 Parametreleri
Zabbix sunucusunun metrik toplama motoru, binlerce ajan ve SNMP kaynağından gelen zaman serisi verilerini işlerken doğrudan disk ve bellek alt sistemini doygunluğa (saturation) ulaştırır. Docker üzerinde Zabbix VDS kurulumu gerçekleştirilirken, veritabanı konteynerinin varsayılan çekirdek sınırları ve standart PostgreSQL parametreleriyle çalıştırılması, üretim ortamında kısa sürede checkpoint fırtınalarına, disk kuyruğunda (await) sıçramalara ve Zabbix queue metriklerinin kontrolsüz büyümesine yol açar.
Yüksek verimli bir mimari kurmak için; Linux blok katmanı, çekirdek sanal bellek (VM) mekanizmaları ve PostgreSQL 16 motorunun WAL (Write-Ahead Logging) yazma dinamikleri birbiriyle uyumlu hale getirilmelidir.
Blok Katmanı ve NVMe I/O Kuyruk Optimizasyonu
NVMe depolama birimlerinde işletim sistemi katmanındaki geleneksel I/O zamanlayıcıları (CFQ, BFQ veya KYBER), donanımın sunduğu paralel kuyruk yapısına ek çekirdek yükü (context switch overhead) getirir. Donanımsal multi-queue desteğine sahip PCIe 4.0 NVMe sürücülerde çekirdek zamanlayıcısı none moduna çekilmelidir. Bu yapılandırma, G/Ç isteklerinin işletim sistemi kuyruğunda bekletilmeden doğrudan NVMe denetleyicisinin donanım kuyruklarına (submission/completion queues) aktarılmasını sağlar.
Sistemdeki NVMe blok aygıtının zamanlayıcı ve okuma tamponu ayarlarını kalıcı hale getirmek için /etc/udev/rules.d/60-nvme-scheduler.rules kuralı tanımlanır:
# NVMe depolama aygıtları için sıfır-zamanlayıcı ve düşük read-ahead politikası
ACTION=="add|change", KERNEL=="nvme[0-9]*n[0-9]*", ATTR{queue/scheduler}="none", ATTR{queue/read_ahead_kb}="32", ATTR{queue/nr_requests}="1024"
queue/scheduler = none: Çekirdeğin I/O sıralama ve birleştirme katmanını devre dışı bırakarak gecikmeyi (latency) doğrudan donanım seviyesine indirir.queue/read_ahead_kb = 32: Varsayılan 128 KB değeri, Zabbix'in B-Tree indeks aramaları gibi rastgele okuma (random read) profillerinde gereksiz verinin önbelleğe alınmasına yol açar. Değerin 32 KB'ye düşürülmesi bellek bant genişliğini korur.queue/nr_requests = 1024: PostgreSQL'in checkpoint anlarında diske gönderdiği yoğun yazma isteklerinin çekirdek kuyruğunda erken bloklanmasını önler.
Kuralı anında devreye almak için:
udevadm control --reload-rules && udevadm trigger --subsystem-match=block
Çekirdek Bellek, THP ve IPC Parametreleri
PostgreSQL 16, sorgu planlama ve paralel indeks taramalarında yoğun bellek tahsisi gerçekleştirir. Linux çekirdeğindeki Transparent Huge Pages (THP) mekanizması, 2 MB'lik sayfaları dinamik tahsis ederken khugepaged arka plan sürecinin bellek parçalanması (fragmentation) ve kilitlenmelere (latency spikes) yol açmasına neden olur. Bu durum, Zabbix geçmiş verilerini (history-syncer) diske aktarırken milisaniyeler süren mikro-donmalara neden olur.
THP mekanizması sistem genelinde tamamen kapatılmalıdır:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
Bu ayarların her yeniden başlatmada geçerli kalması için /etc/systemd/system/disable-thp.service birimi oluşturulur:
[Unit]
Description=Disable Transparent Huge Pages (THP) for Database Workloads
DefaultDependencies=no
After=sysinit.target local-fs.target
Before=mongod.service postgresql.service docker.service
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled && echo never > /sys/kernel/mm/transparent_hugepage/defrag'
[Install]
WantedBy=basic.target
systemctl daemon-reload && systemctl enable --now disable-thp.service
PostgreSQL'in paylaşımlı bellek (shared memory) segmentlerini ve semaforlarını eksiksiz tahsis edebilmesi için /etc/sysctl.d/60-postgresql-ipc.conf dosyası yapılandırılır:
# PostgreSQL Shared Memory ve IPC Tahsisi
kernel.shmmax = 18446744073709551615
kernel.shmall = 18446744073709551615
kernel.sem = 50100 64128000 50100 1280
# TCP BBR ve Tampon Yönetimi
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
Yapılandırma uygulanır:
sysctl --system
Docker Konteynerinde IPC ve POSIX Bellek Tuzağı
Docker varsayılan yapılandırmada konteyner başına yalnızca 64 MB /dev/shm (POSIX Shared Memory) alanı tahsis eder. PostgreSQL 16, paralel sorgu yürütme (parallel query workers), hash join işlemleri ve sıralama tamponları için bu alanı aktif olarak kullanır.
Docker üzerinde Zabbix VDS kurulumu esnasında bu alan genişletilmezse, Zabbix Server karmaşık dashboard sorguları çalıştırdığında PostgreSQL şu kritik hatayı üreterek işlemi sonlandırır:
ERROR: could not resize shared memory segment "/PostgreSQL.12345678": No space left on device
Bu darboğazı engellemek için docker-compose.yml dosyasında veritabanı servisine doğrudan shm_size: 2g parametresi tanımlanmalıdır:
services:
zabbix-db:
image: postgres:16-alpine
container_name: zabbix-postgres-16
restart: always
shm_size: 2g
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65535
hard: 65535
volumes:
- /var/lib/docker/volumes/zabbix_db_data/_data:/var/lib/postgresql/data
- ./config/postgresql.conf:/etc/postgresql/postgresql.conf:ro
command: ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"]
networks:
- zabbix-backend
PostgreSQL 16 Parametrelerinin Zabbix İş Yüküne Göre Ayarlanması
Zabbix veritabanı profili tipik bir web uygulamasından radikal biçimde farklıdır. İş yükünün %85-90'ı sürekli INSERT operasyonudur (history, history_uint, trends). Okuma işlemleri ise trigger hesaplamaları ve web arayüzü dashboard yenilemelerinden ibarettir.
16 GB RAM ve 4 vCPU tahsis edilmiş bir VDS altyapısı için optimize edilmiş üretim seviyesi /etc/postgresql/postgresql.conf direktifleri:
# --------------------------------------------------
# Bellek ve Önbellek Mimarisi
# --------------------------------------------------
# Toplam sistem RAM'inin %25'i
shared_buffers = 4GB
# Toplam sistem RAM'inin %75'i (İşletim sistemi sayfa önbelleği varsayımı)
effective_cache_size = 12GB
# Bağlantı başına sıralama/hash belleği (Zabbix poller sayısı göz önüne alınarak kontrollü tutulur)
work_mem = 32MB
# Autovacuum ve index re-build işlemleri için ayrılan bellek
maintenance_work_mem = 1GB
# WAL yazma döngüsü için tampon bellek
wal_buffers = 32MB
# --------------------------------------------------
# Checkpoint ve WAL (Write-Ahead Logging) Optimizasyonu
# --------------------------------------------------
# Disk yazma piklerini zamana yayarak I/O tıkanıklığını engelleme
checkpoint_completion_target = 0.9
# Maksimum checkpoint aralığı
checkpoint_timeout = 15min
# WAL rotasyon sınırları
min_wal_size = 2GB
max_wal_size = 16GB
# Kritik Performans Ayarı:
# Zabbix telemetri verisinde mikro-saniyelik veri kaybı toleransı (0.5-1 sn)
# karşılığında fiziksel fdatasync disk yazma yükünü %70 düşürür.
synchronous_commit = off
wal_writer_delay = 200ms
# --------------------------------------------------
# Disk Planlayıcı ve NVMe Maliyet Katsayıları
# --------------------------------------------------
# PCIe 4.0 NVMe SSD rastgele okuma maliyeti (Varsayılan 4.0 mekanik diskler içindir)
random_page_cost = 1.1
seq_page_cost = 1.0
# NVMe denetleyicisinin paralel I/O yeteneği
effective_io_concurrency = 200
# --------------------------------------------------
# Autovacuum ve Table Bloat Yönetimi
# --------------------------------------------------
# Zabbix tablolarındaki ölü satırların (dead tuples) birikmesini engelleme
autovacuum = on
autovacuum_max_workers = 4
autovacuum_naptime = 10s
autovacuum_vacuum_threshold = 50
autovacuum_vacuum_scale_factor = 0.05
autovacuum_analyze_scale_factor = 0.02
autovacuum_vacuum_cost_limit = 2000
autovacuum_vacuum_cost_delay = 2ms
# PostgreSQL 16 ile gelen optimize edilmiş vakum bellek sınırı
vacuum_buffer_usage_limit = 256MB
Yapılandırmanın Kritik Teknik Dayanakları:
synchronous_commit = off: Bu parametre açıkken PostgreSQL, her işlem onayında (COMMIT) diske fizikselfdatasyncçağrısı yapmak zorundadır. NVMe sürücülerde dahi bu işlem her saniye binlerce metrik akarken disk denetleyicisini kilitler. Ayar kapatıldığında veriler önce WAL tamponuna yazılır vewal_writer_delay(200 ms) aralıklarıyla toplu aktarılır. Ani bir elektrik veya donanım kesintisinde yalnızca son 200 ms'lik telemetri verisi riske girer; veritabanı bütünlüğü (consistency) ACID standartlarında korunur.random_page_cost = 1.1: Standart değer olan4.0, dönen manyetik disklerin kafa hareket gecikmesini modeller. NVMe depolamada rastgele okuma gecikmesi sıralı okuma ile neredeyse aynıdır (p99 < 0.1 ms). Değerin1.1seviyesine çekilmesi, PostgreSQL sorgu planlayıcısının Zabbix tablolarında gereksiz sequential scan (tam tablo taraması) yapmak yerine agresif şekilde B-Tree indekslerini kullanmasını sağlar.autovacuum_vacuum_scale_factor = 0.05: Standart değer olan0.20, 100 milyon satırlık birhistory_uinttablosunda 20 milyon satır değişmeden temizlik başlatmaz. Değerin%5seviyesine çekilmesi, temizliğin sürekli ve küçük parçalar halinde yapılmasını sağlayarak tablonun kontrolsüz disk alanı kaplamasını (bloat) engeller.
Altyapı Doğrulaması ve Donanım Kararlılığı
Yapılandırılan çekirdek ve veritabanı optimizasyonlarının tam performansla çalışması, sanallaştırma katmanında vCPU döngülerinin kesintiye uğramamasına bağlıdır. Hipervizör seviyesinde aşırı kaynak tahsisi (oversubscription) bulunan paylaşımlı sanal sunucularda, CPU Steal Time (%st) değerinin %0.0'ın üzerine çıkması durumunda PostgreSQL worker süreçleri kilit beklemelerine (spin lock ve latch contention) düşer. Bu durum, optimize edilmiş parametrelerin dahi işlevsiz kalmasına neden olur.
Bu mimarinin kararlı çalışması için tropic.host platformunun sunduğu KVM tabanlı, donanım kaynakları birebir izole edilmiş yüksek frekanslı AMD EPYC ve Ryzen 9 işlemcili VDS altyapısı kurumsal bir standart sağlar. Donanım seviyesinde garanti edilen %st = 0.0% değeri, rastgele 4K QD1 işlemlerinde 50.000+ IOPS sağlayan PCIe 4.0 NVMe depolama birimleri ve çekirdek seviyesinde TCP BBR destekli ağ omurgası, PostgreSQL 16 motorunun WAL tamponlarını diske mikro-saniye gecikmeyle aktarmasını garanti eder.
Uygulanan veritabanı parametrelerinin doğrulanması için PostgreSQL konteyneri içerisinde aşağıdaki sorgu çalıştırılmalıdır:
docker exec -it zabbix-postgres-16 psql -U zabbix -d zabbix -c "
SELECT name, setting, unit, source
FROM pg_settings
WHERE name IN (
'shared_buffers',
'effective_cache_size',
'work_mem',
'maintenance_work_mem',
'synchronous_commit',
'random_page_cost',
'checkpoint_completion_target'
);"
Çıktıda listelenen değerlerin configuration file kaynağından okunduğu ve synchronous_commit değerinin off olduğu doğrulandıktan sonra, Zabbix Server ve Web konteynerlerinin dağıtımına geçilebilir.
Docker Compose ile Zabbix Server, Web ve DB Dağıtımı
Docker tabanlı Zabbix VDS kurulumunda monolitik yapı yerine ayrıştırılmış servis mimarisi (micro-services architecture) tercih edilmelidir. Zabbix Server çekirdeği (C tabanlı daemon), veritabanı motoru (PostgreSQL 16) ve web önyüzü (Nginx + PHP-FPM) bağımsız konteynerler olarak izole edildiğinde; çekirdek kilitlenmeleri, veritabanı kilit beklemeleri (row-level locking) ve web sunucu istek yükleri birbirinin kaynak havuzunu tüketmez.
1. Dizin Hiyerarşisi ve Yetkilendirme Matrisi
Dağıtıma başlamadan önce konfigürasyon, TLS sertifikaları, MIB dosyaları ve veritabanı dosyaları için kalıcı depolama (persistent storage) dizin yapısı oluşturulmalıdır. Zabbix konteynerleri varsayılan olarak UID 1997 ve GID 1997 yetkileriyle çalıştığından, bind-mount dizinlerindeki izin uyuşmazlıkları konteynerin cannot open log file veya permission denied hatasıyla çökmesine (crashloop) neden olur.
Sunucu üzerinde üretim dizini hiyerarşisi şu komutlarla yapılandırılır:
# Üretim dizinlerinin oluşturulması
mkdir -p /opt/zabbix-compose/{zbx_env,zbx_export,zbx_mibs,zbx_snmptraps,zbx_ssl,pg_data}
# Çalışma dizinine geçiş
cd /opt/zabbix-compose
# Zabbix kullanıcısı (UID:GID 1997) için dosya sistemi izinlerinin ayarlanması
chown -R 1997:1997 zbx_env zbx_export zbx_mibs zbx_snmptraps zbx_ssl
# PostgreSQL veri dizini için kısıtlı izinler (UID 999: docker postgres kullanıcısı)
chown -R 999:999 pg_data
chmod 700 pg_data
2. Ortam Değişkenleri Dosyası (.env)
Hassas veritabanı kimlik bilgileri, bellek tahsisatları ve zaman dilimi parametreleri docker-compose.yml içerisine açık metin (cleartext) olarak yazılmamalıdır. Ortam değişkenleri için /opt/zabbix-compose/.env dosyası tanımlanır:
# ==============================================================================
# VERİTABANI KİMLİK BİLGİLERİ VE ERİŞİM PARAMETRELERİ
# ==============================================================================
POSTGRES_USER=zabbix
POSTGRES_PASSWORD=Secr3t_Pg_Zbx_Pass_2026!
POSTGRES_DB=zabbix
# ==============================================================================
# SİSTEM VE YERELLEŞTİRME
# ==============================================================================
ZBX_SERVER_NAME=ZABBIX-PROD-VDS-01
PHP_TZ=Europe/Istanbul
# ==============================================================================
# DAĞITIM SÜRÜM ETİKETLERİ
# ==============================================================================
ZBX_VERSION=ubuntu-7.0-latest
PG_VERSION=16-alpine
Dosya yetkileri yalnızca root kullanıcısının okuyabileceği şekilde sınırlandırılmalıdır:
chmod 600 /opt/zabbix-compose/.env
3. Üretim Seviyesi docker-compose.yml Mimarisi
Aşağıdaki docker-compose.yml dosyası; Zabbix Server 7.0 LTS, PostgreSQL 16, Nginx tabanlı Zabbix Web ve sunucunun kendi metriklerini toplayan Zabbix Agent 2 bileşenlerini bir araya getirir.
Bu mimaride iki bağımsız köprü ağı (bridge network) kurgulanmıştır: 1. zbx-backend-net: Yalnızca veritabanı ve Zabbix Server arasındaki trafiği taşır. internal: true bayrağı ile dış dünya internet çıkışı ve port yönlendirmeleri tamamen izole edilir; böylece PostgreSQL 5432 portu ana makineye (host) dahi açılmaz. 2. zbx-frontend-net: Web arayüzü, Zabbix Server ve dışarıdan gelecek ajan (trapper) bağlantılarını barındırır.
version: '3.8'
networks:
zbx-backend-net:
driver: bridge
internal: true
zbx-frontend-net:
driver: bridge
volumes:
pg_data:
driver: local
driver_opts:
type: none
device: /opt/zabbix-compose/pg_data
o: bind
services:
# ============================================================================
# VERİTABANI SERVİSİ: PostgreSQL 16
# ============================================================================
zabbix-postgres:
image: postgres:${PG_VERSION}
container_name: zabbix-postgres
restart: unless-stopped
shm_size: 1024m
networks:
- zbx-backend-net
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- pg_data:/var/lib/postgresql/data
command: >
postgres
-c shared_buffers=1024MB
-c effective_cache_size=3072MB
-c work_mem=16MB
-c maintenance_work_mem=256MB
-c min_wal_size=1GB
-c max_wal_size=4GB
-c checkpoint_completion_target=0.9
-c checkpoint_timeout=15min
-c synchronous_commit=off
-c random_page_cost=1.1
-c effective_io_concurrency=200
-c max_connections=200
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
deploy:
resources:
limits:
cpus: '2.0'
memory: 2048M
reservations:
cpus: '1.0'
memory: 1024M
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
# ============================================================================
# ZABBIX CORE SERVER (C DAEMON)
# ============================================================================
zabbix-server:
image: zabbix/zabbix-server-pgsql:${ZBX_VERSION}
container_name: zabbix-server
restart: unless-stopped
networks:
- zbx-backend-net
- zbx-frontend-net
ports:
- "0.0.0.0:10051:10051"
depends_on:
zabbix-postgres:
condition: service_healthy
environment:
DB_SERVER_HOST: zabbix-postgres
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ZBX_STARTPOLLERS: 16
ZBX_IPMIPOLLERS: 0
ZBX_STARTPOLLERSPREPRO: 8
ZBX_STARTTRAPPERS: 5
ZBX_STARTPINGERS: 8
ZBX_STARTDISCOVERERS: 2
ZBX_STARTHTTPPOLLERS: 4
ZBX_STARTDBSYNCERS: 6
ZBX_CACHESIZE: 256M
ZBX_HISTORYCACHESIZE: 128M
ZBX_HISTORYINDEXCACHESIZE: 64M
ZBX_TRENDCACHESIZE: 64M
ZBX_VALUECACHESIZE: 256M
ZBX_TIMEOUT: 15
ZBX_HOUSEKEEPINGFREQUENCY: 1
ZBX_MAXHOUSEKEEPERDELETE: 5000
ZBX_LOGSLOWQUERIES: 3000
volumes:
- /opt/zabbix-compose/zbx_env:/var/lib/zabbix/env:ro
- /opt/zabbix-compose/zbx_export:/var/lib/zabbix/export:rw
- /opt/zabbix-compose/zbx_mibs:/var/lib/zabbix/mibs:ro
- /opt/zabbix-compose/zbx_snmptraps:/var/lib/zabbix/snmptraps:rw
- /opt/zabbix-compose/zbx_ssl:/var/lib/zabbix/ssl:ro
ulimits:
nproc: 65535
nofile:
soft: 65535
hard: 65535
deploy:
resources:
limits:
cpus: '2.0'
memory: 2048M
reservations:
cpus: '1.0'
memory: 512M
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
# ============================================================================
# WEB FRONTEND: NGINX + PHP-FPM
# ============================================================================
zabbix-web:
image: zabbix/zabbix-web-nginx-pgsql:${ZBX_VERSION}
container_name: zabbix-web
restart: unless-stopped
networks:
- zbx-backend-net
- zbx-frontend-net
ports:
- "0.0.0.0:80:8080"
depends_on:
zabbix-postgres:
condition: service_healthy
zabbix-server:
condition: service_started
environment:
ZBX_SERVER_NAME: ${ZBX_SERVER_NAME}
ZBX_SERVER_HOST: zabbix-server
ZBX_SERVER_PORT: 10051
DB_SERVER_HOST: zabbix-postgres
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
PHP_TZ: ${PHP_TZ}
NGINX_CLIENT_MAX_BODY_SIZE: 32M
deploy:
resources:
limits:
cpus: '1.0'
memory: 1024M
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
# ============================================================================
# YEREL HOST İZLEME: Zabbix Agent 2
# ============================================================================
zabbix-agent2:
image: zabbix/zabbix-agent2:${ZBX_VERSION}
container_name: zabbix-agent2
restart: unless-stopped
privileged: true
networks:
- zbx-frontend-net
ports:
- "127.0.0.1:10050:10050"
environment:
ZBX_HOSTNAME: ${ZBX_SERVER_NAME}
ZBX_SERVER: zabbix-server
ZBX_SERVERACTIVE: zabbix-server:10051
ZBX_PASSIVEALLOW: "true"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /sys:/host/sys:ro
- /proc:/host/proc:ro
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
logging:
driver: "json-file"
options:
max-size: "20m"
max-file: "2"
4. Çekirdek ve Ağ Katmanı Parametreleri
Docker daemon köprü ağları üzerinden yüksek eşzamanlı veri akışı gerçekleşirken, Linux çekirdeğinin bağlantı takip tablosu (nf_conntrack) ve soket dinleme limitleri darboğaz oluşturabilir. Ana sunucu seviyesinde /etc/sysctl.d/99-zabbix-docker.conf dosyası oluşturularak bu eşikler yükseltilmelidir:
# Soket dinleme kuyruğu derinliği
net.core.somaxconn = 4096
# Ephemeral port aralığının genişletilmesi
net.ipv4.ip_local_port_range = 10240 65535
# TCP TIME_WAIT soketlerinin hızlı geri dönüşümü
net.ipv4.tcp_tw_reuse = 1
# Bağlantı takip tablosu boyutu (DPI ve yüksek poller trafiği için)
net.netfilter.nf_conntrack_max = 262144
# Sanal bellek tahsis sınırları
vm.max_map_count = 262144
Parametreler çekirdeğe uygulanır:
sysctl -p /etc/sysctl.d/99-zabbix-docker.conf
5. Yığının Başlatılması ve Şema Kurulumunun Doğrulanması
Zabbix VDS kurulumu Docker üzerinde başlatılırken, ilk çalıştırmada Zabbix Server konteyneri veritabanının boş olduğunu tespit eder ve gerekli tüm tablo şemalarını, indeksleri ve varsayılan veri setlerini otomatik olarak PostgreSQL üzerine yazar. Bu işlem sırasında diske yoğun INSERT ve CREATE INDEX operasyonları gönderilir.
Konteyner yığınını arka planda ayağa kaldırmak için:
docker compose up -d
Veritabanı başlatma ve şema aktarım süreci Zabbix Server günlüklerinden canlı olarak izlenmelidir:
docker logs -f zabbix-server
Başarılı bir başlangıç sürecinde log akışında sırasıyla şu olaylar görülmelidir:
Starting Zabbix Server. Zabbix 7.0.x (revision xxxxx).
Press Ctrl+C to exit.
...
Connecting to database 'zabbix' on host 'zabbix-postgres'...
Connected to the database!
Database version 7.0 (schema 7000000) is being imported...
[... otomatik şema ve veri yükleme adımları ...]
database is ready, starting server...
server #0 started [main process]
server #1 started [service manager #1]
server #2 started [configuration syncer #1]
server #3 started [db syncer #1]
server #4 started [poller #1]
server #0 started [main process] ifadesi görüldüğünde çekirdek motor operasyonel duruma gelmiştir.
6. Altyapı Kararlılığı ve Donanım Kısıtları
Zabbix Server mimarisinde db syncer süreçleri, bellek üzerindeki history cache tamponunu belirli periyotlarla diske boşaltır (flush). Eğer kullanılan sanallaştırma altyapısında CPU döngüleri hipervizör tarafından çalınıyorsa (CPU Steal Time %st > 0.0%) veya paylaşımlı SATA/SAS depolama üzerinde disk G/Ç kuyrukları (await ve r_await) yükseliyorsa, db syncer süreçleri veriyi diske zamanında yazamaz. Bunun sonucunda Zabbix history cache full uyarısı tetiklenir ve ajanlardan gelen yeni metrikler işlenemeden düşürülür (drop).
Bu nedenle, Docker tabanlı Zabbix mimarilerinde tropic.host platformunun KVM tabanlı, donanım kaynakları birebir adanmış (dedicated vCPU) ve %st = 0.0% garantisi sunan VDS altyapısı kritik bir güvencedir. Kurumsal seviye PCIe 4.0 NVMe SSD'lerin sağladığı 50.000+ IOPS rastgele yazma kapasitesi, yüzlerce ana makineden (host) gelen eşzamanlı veri akışında WAL ve tablo yazma işlemlerinin p99 gecikmesini 1 milisaniyenin altında tutar.
Dağıtım sonrası konteynerlerin anlık kaynak tüketimleri doğrulanmalıdır:
docker stats --no-stream
Örnek çıktı:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
a1b2c3d4e5f6 zabbix-server 0.85% 185.4MiB / 2GiB 9.05% 1.2MB / 850KB 12.4MB / 45MB 42
b2c3d4e5f6a1 zabbix-postgres 1.12% 340.2MiB / 2GiB 16.61% 850KB / 1.2MB 45MB / 120MB 28
c3d4e5f6a1b2 zabbix-web 0.05% 68.1MiB / 1GiB 6.65% 450KB / 320KB 5MB / 0B 6
d4e5f6a1b2c3 zabbix-agent2 0.10% 24.5MiB / 256MiB 9.57% 120KB / 110KB 0B / 0B 12
Soket seviyesinde dinleme portlarının doğrulanması için:
ss -tulpn | grep -E '10051|80'
Çıktıda 0.0.0.0:10051 (Zabbix Server trapper) ve 0.0.0.0:80 (Zabbix Web UI) portlarının LISTEN durumunda olduğu teyit edildikten sonra, tarayıcı üzerinden http://<SUNUCU_IP_ADRESI> adresine erişilerek varsayılan kimlik bilgileri (Admin / zabbix) ile yönetim paneline giriş yapılabilir.
Nginx SSL Ters Proxy ve Güvenlik Sıkılaştırma
Docker konteynerlerinin ayağa kaldırılması ve Web UI arayüzünün doğrudan 80 portu üzerinden dış dünyaya açılması, test aşamaları için yeterli olsa da üretim ortamında kabul edilemez bir güvenlik açığı oluşturur. Zabbix Web UI; yönetici oturum çerezleri (zbx_session), API anahtarları, ana makine yapılandırmaları ve SNMP kimlik bilgilerini barındırır. Bu trafiğin şifresiz HTTP protokolü üzerinden iletilmesi, yerel ağda veya ara BGP yönlendiricilerinde gerçekleşebilecek Man-in-the-Middle (MitM) saldırılarına ve oturum hırsızlığına (session hijacking) zemin hazırlar.
Bu zafiyeti ortadan kaldırmak için Zabbix Web konteynerinin doğrudan genel ağa açılması engellenmeli; ön tarafa TLS 1.3 sonlandırma, HTTP güvenlik başlıkları (Security Headers), soket tamponlama ve istek sınırlama (rate limiting) yeteneklerine sahip bir Nginx ters proxy (reverse proxy) katmanı yerleştirilmelidir.
1. Web Konteynerinin Yerel Ağ Döngüsüne (Loopback) İzolasyonu
İlk adım, docker-compose.yml içerisindeki Web UI servisinin genel ağa (0.0.0.0) olan port bağlamasını kaldırarak yalnızca yerel ağ döngüsüne (127.0.0.1) veya izole Docker bridge ağına bağlamaktır.
compose.yaml dosyasındaki zabbix-web servisinin ports direktifini şu şekilde güncelleyin:
ports:
- "127.0.0.1:8080:8080"
Yapılandırmayı uygulamak için yalnızca ilgili servisi yeniden oluşturun:
docker compose up -d --no-deps zabbix-web
Soket izolasyonunu doğrulayın:
ss -tulpn | grep 8080
Çıktıda 127.0.0.1:8080 soketinin dinlendiği, 0.0.0.0:8080 veya :::8080 şeklinde genel IP bloklarına dinleme yapılmadığı teyit edilmelidir. Bu mimari, Nginx atlanarak doğrudan konteynere erişilmesini engeller.
2. DNS ve tropic.host Statik IP Eşleştirmesi
Zabbix Web UI erişimi için kullanılacak alan adının (örneğin: zabbix.sirket.com), tropic.host platformu tarafından sağlanan adanmış statik IPv4 adresine yönlendirilmesi gerekir. tropic.host altyapısının sağladığı temiz IP blokları, geçmişinde spam veya kötüye kullanım kaydı barındırmadığı için Let's Encrypt CA sunucularının ACME HTTP-01 doğrulama paketlerinin sınır güvenlik duvarlarına takılmadan sunucuya doğrudan ulaşmasını sağlar.
DNS A kaydının sunucu üzerinde doğrulamasını gerçekleştirin:
dig +short A zabbix.sirket.com @1.1.1.1
Dönen IP adresinin sunucunun genel arabirimindeki IP ile birebir eşleştiğinden emin olun:
ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'
3. Certbot ile Let's Encrypt SSL/TLS Sertifikasyonunun Alınması
Nginx'in kurulumu öncesinde veya Nginx geçici olarak durdurulmuşken, Let's Encrypt ACME istemcisi (certbot) aracılığıyla SSL sertifikası temin edilmelidir:
apt-get update && apt-get install -y certbot python3-certbot-nginx
Port 80 üzerinden certbot standalone modunu kullanarak ECC (Elliptic Curve Cryptography - secp384r1) tabanlı modern bir sertifika üretin. ECC anahtarları, klasik 2048/4096-bit RSA anahtarlarına kıyasla belirgin şekilde daha kısa işlemci döngüsü gerektirir ve TLS el sıkışma (handshake) sürelerini milisaniyeler seviyesinde optimize eder:
certbot certonly --standalone \
-d zabbix.sirket.com \
--key-type ecdsa \
--elliptic-curve secp384r1 \
--agree-tos \
--email [email protected] \
--non-interactive
Oluşturulan sertifika dosyalarının yolları: * Sertifika Zinciri: /etc/letsencrypt/live/zabbix.sirket.com/fullchain.pem * Özel Anahtar (Private Key): /etc/letsencrypt/live/zabbix.sirket.com/privkey.pem
Geriye dönük uyumlulukta DHE şifreleme paketleri (cipher suites) kullanılacaksa, Diffie-Hellman parametrelerinin de güçlü bir entropiyle önceden oluşturulması zorunludur:
openssl dhparam -out /etc/nginx/dhparam.pem 2048
4. Nginx Üretim Seviyesi Ters Proxy Yapılandırması
Nginx'in varsayılan tampon (buffer) değerleri Zabbix için yetersizdir. Zabbix Web arayüzü; onlarca grafiği, SVG topoloji haritasını ve JSON tabanlı AJAX verisini eşzamanlı olarak çeker. Tampon boyutları düşük tutulursa Nginx, gelen yanıtları diske yazmaya başlar (an upstream response is buffered to a temporary file uyarısı verir). Bu durum, tropic.host üzerindeki kurumsal PCIe 4.0 NVMe SSD'lerin 50.000+ IOPS kapasitesine rağmen gereksiz I/O tüketimi ve gecikme üretir. Yanıtların tamamen RAM üzerinde işlenmesi için proxy_buffers değerleri optimize edilmelidir.
/etc/nginx/conf.d/zabbix.conf dosyasını oluşturun:
# İstek sınırlandırma (Rate Limiting) bölgeleri
limit_req_zone $binary_remote_addr zone=zabbix_login_limit:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=zabbix_api_limit:10m rate=30r/s;
# Upstream tanımı - Docker üzerindeki Zabbix Web servisi
upstream zabbix_backend {
server 127.0.0.1:8080 max_fails=3 fail_timeout=10s;
keepalive 32;
}
# HTTP -> HTTPS Yönlendirme (Port 80)
server {
listen 80;
listen [::]:80;
server_name zabbix.sirket.com;
# Let's Encrypt ACME yenileme dizini
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS Birincil Sunucu Bloğu (Port 443)
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name zabbix.sirket.com;
# SSL / TLS Sertifika Yapılandırması
ssl_certificate /etc/letsencrypt/live/zabbix.sirket.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/zabbix.sirket.com/privkey.pem;
ssl_dhparam /etc/nginx/dhparam.pem;
# Güvenli TLS Protokolleri ve Şifreleme Paketleri
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
# SSL Oturum Önbelleği (Session Resumption)
ssl_session_timeout 1d;
ssl_session_cache shared:SSL_ZABBIX:20m;
ssl_session_tickets off;
# OCSP Stapling (İstemci tarafı doğrulama gecikmesini düşürür)
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/zabbix.sirket.com/fullchain.pem;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
# Güvenlik Sıkılaştırma Başlıkları (Security Headers)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self';" always;
# Dosya Yükleme Sınırı (Büyük şablon/XML içe aktarımları için)
client_max_body_size 64M;
# Nginx Proxy Tampon ve Zaman Aşımı Ayarları
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 8 256k;
proxy_busy_buffers_size 512k;
proxy_temp_file_write_size 512k;
proxy_connect_timeout 60s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
# Giriş Sayfasına Kaba Kuvvet (Brute-Force) Koruması
location = /index.php {
limit_req zone=zabbix_login_limit burst=3 nodelay;
proxy_pass http://zabbix_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Zabbix API İstek Sınırlandırması
location = /api_jsonrpc.php {
limit_req zone=zabbix_api_limit burst=20 nodelay;
proxy_pass http://zabbix_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Genel İstek Yönlendirmesi
location / {
proxy_pass http://zabbix_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Gizli Sistem Dosyalarına Erişimi Engelleme
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
Nginx yapılandırmasının sözdizimini (syntax) test edin ve servisi yeniden yükleyin:
nginx -t && systemctl reload nginx
5. Çekirdek ve Ağ Katmanında Soket Sıkılaştırma (Kernel Sysctl)
Yüksek sayıda ajandan gelen HTTP/API sorgularında ve eşzamanlı izleme oturumlarında Nginx ters proxy katmanının TCP TIME_WAIT soket tükenmesine (socket exhaustion) girmemesi gerekir. Docker tabanlı Zabbix VDS kurulumu gerçekleştirilirken çekirdek parametrelerinin bu iş yüküne göre ayarlanması şarttır.
/etc/sysctl.d/99-zabbix-network.conf dosyasını yapılandırın:
# SYN Flood saldırılarına karşı SYN kuyruk kapasitesi
net.ipv4.tcp_max_syn_backlog = 8192
# Yerel port tükenmesini önlemek için port aralığı
net.ipv4.ip_local_port_range = 1024 65535
# Soket dinleme kuyruğu derinliği
net.core.somaxconn = 65535
# Geri dönen TCP bağlantılarının hızlı geri kazanımı
net.ipv4.tcp_tw_reuse = 1
# TIME_WAIT durumundaki maksimum soket sayısı
net.ipv4.tcp_max_tw_buckets = 262144
# Keepalive paketleme zamanlamaları
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
Parametreleri etkinleştirin:
sysctl -p /etc/sysctl.d/99-zabbix-network.conf
tropic.host altyapısının varsayılan olarak etkinleştirdiği gelişmiş donanımsal L3/L4/L7 DDoS koruması, Nginx işçi süreçlerine (worker processes) ulaşmadan önce volumetrik SYN Flood, UDP Amplification ve HTTP GET/POST taşkınlarını sınır yönlendiricilerde bertaraf eder. Bu durum, sunucunun çekirdek seviyesindeki TCP kuyruklarının (somaxconn) kilitlenmesini önler ve ters proxy katmanının her koşulda kararlı çalışmasını güvence altına alır.
6. SSL Sertifikası Otomatik Yenileme ve Doğrulama
Let's Encrypt sertifikalarının 90 günlük geçerlilik süresi bulunmaktadır. Yenileme sürecinin Nginx çalışırken kesintisiz tamamlanması için systemd certbot servisine bir dağıtım kancası (deploy hook) tanımlanmalıdır.
Sertifika yenileme yapılandırmasını test edin:
certbot renew --dry-run --webroot -w /var/www/certbot --deploy-hook "systemctl reload nginx"
Çıktıda Congratulations, all simulated renewals succeeded ibaresi görüldükten sonra, systemd zamanlayıcısının aktif olduğunu teyit edin:
systemctl is-active certbot.timer
Uygulanan ters proxy ve TLS sıkılaştırmasını OpenSSL üzerinden doğrulayın:
echo | openssl s_client -connect zabbix.sirket.com:443 -servername zabbix.sirket.com -tls1_3 2>/dev/null | grep -E 'Protocol|Cipher|Extended Master Secret'
Beklenen çıktı:
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Son olarak, HTTP güvenlik başlıklarının ve yönlendirmenin doğru çalıştığını HTTP yanıt kodları üzerinden denetleyin:
curl -ILs https://zabbix.sirket.com | grep -E 'HTTP/|strict-transport-security|x-frame-options'
Yapılandırma sonucunda tüm açık HTTP istekleri HTTPS'e yönlendirilecek; Zabbix arayüzü yalnızca TLS 1.2/1.3 protokolleri ve kurumsal düzeyde sıkılaştırılmış başlıklar üzerinden güvenli şekilde hizmet verecektir.
Zabbix Agent 2 Kurulumu ve Telegram Bildirim Entegrasyonu
İzleme mimarisinde Zabbix Server ve Web arayüzünün Docker üzerinde izole çalışması, ana sunucunun (host node) donanım ve çekirdek metriklerine doğrudan erişimini sınırlar. Konteyner ortamından ana işletim sisteminin systemd birimlerini, disk G/Ç kuyruklarını, soket durumlarını ve Docker daemon süreçlerini güvenilir şekilde denetlemek için Zabbix Agent 2 doğrudan ana sunucu (bare-metal/KVM host) katmanına kurulmalıdır.
C diliyle yazılmış klasik Zabbix Agent yerine Go tabanlı Zabbix Agent 2'nin tercih edilmesinin nedeni; goroutine mimarisi sayesinde eşzamanlı metrik toplayabilmesi, kalıcı TCP bağlantı havuzlarını desteklemesi ve harici betiklere ihtiyaç duymadan yerleşik eklentiler (plugins) üzerinden doğrudan /var/run/docker.sock ile haberleşebilmesidir.
1. Host Seviyesinde Zabbix Agent 2 Kurulumu ve Güvenlik İzinleri
Zabbix VDS kurulumu Docker altyapısında izleme ajanının ana sunucuya konuşlandırılması, konteyner kısıtlamalarını aşarak hipervizör düzeyindeki kaynak tüketimini şeffaf hale getirir. tropic.host üzerindeki saf KVM sanallaştırmada donanım paylaşımsız sağlandığından, ajanın raporlayacağı CPU Steal Time (%st) değerinin sürekli olarak %0.0 bandında kalması beklenir; bu değerin yükselmesi bir komşu gürültüsü (noisy neighbor) veya sanallaştırma katmanı darboğazı göstergesidir.
Ubuntu 24.04 LTS veya Debian 12 tabanlı ana sunucu üzerinde resmi Zabbix 7.0 LTS deposunu tanımlayın ve ajanı kurun:
# Zabbix 7.0 LTS resmi depo paketini indirin ve kurun
wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest_7.0+ubuntu24.04_all.deb
dpkg -i zabbix-release_latest_7.0+ubuntu24.04_all.deb
apt-get update
# Zabbix Agent 2 ve Docker izleme eklentisini yükleyin
apt-get install -y zabbix-agent2 zabbix-agent2-plugin-docker
Agent 2'nin Docker API üzerinden konteyner durumlarını okuyabilmesi için zabbix sistem kullanıcısının docker grubuna dahil edilmesi şarttır. Aksi takdirde eklenti soket üzerinden permission denied hatası üretecektir:
usermod -aG docker zabbix
Değişikliğin UNIX soket izinlerine yansıdığını denetleyin:
sudo -u zabbix docker ps --format '{{.Names}} : {{.Status}}'
2. Agent Yapılandırması ve Şifreli İletişim Parametreleri
Zabbix Agent 2 yapılandırma dosyası (/etc/zabbix/zabbix_agent2.conf), Docker köprü ağı (bridge network) veya yerel döngü (loopback) üzerinden gelen sorguları kabul edecek şekilde optimize edilmelidir.
Aşağıdaki yapılandırmayı uygulayın:
cat <<'EOF' > /etc/zabbix/zabbix_agent2.conf
PidFile=/var/run/zabbix/zabbix_agent2.pid
LogFile=/var/log/zabbix/zabbix_agent2.log
LogFileSize=20
# Docker konteyner ağından ve yerel sunucudan gelen sorgulara izin verin
# 172.20.0.0/16 Docker compose bridge alt ağı veya 127.0.0.1
Server=127.0.0.1,172.20.0.0/16
# Aktif kontroller için Zabbix Server adresi ve portu
ServerActive=127.0.0.1:10051
# Zabbix Web UI üzerindeki Host Name ile birebir eşleşmelidir
Hostname=vds-node-01.tropic.internal
# Docker eklentisi yapılandırması
Plugins.Docker.Endpoint=unix:///var/run/docker.sock
Plugins.Docker.Timeout=5
# Dinleme soketi
ListenPort=10050
ListenIP=0.0.0.0
# Zaman aşımı ve tampon bellek
Timeout=10
BufferSend=5
BufferSize=1000
EOF
Servisi yeniden başlatın ve kalıcı hale getirin:
systemctl restart zabbix-agent2
systemctl enable zabbix-agent2
systemctl status zabbix-agent2 --no-pager
Ana makinede çalışan ajanın Docker eklentisinin metrik üretip üretmediğini zabbix_agent2 ikili dosyası ile doğrudan test edin:
zabbix_agent2 -t docker.info
zabbix_agent2 -t docker.containers.discovery
Beklenen çıktı, ana makinede koşan Zabbix bileşenlerinin (zabbix-server, zabbix-web, postgres-db) adlarını ve durumlarını içeren geçerli bir JSON dizisi olmalıdır:
docker.containers.discovery [s|[{"{#ID}":"a1b2c3d4e5f6","{#NAME}":"/zabbix-server"},{"{#ID}":"b2c3d4e5f6a1","{#NAME}":"/zabbix-web-nginx-pgsql"},{"{#ID}":"c3d4e5f6a1b2","{#NAME}":"/postgres-server"}]]
3. Telegram Bot API ve Chat ID Altyapısının Hazırlanması
Kritik altyapı alarmlarının anlık iletilmesi için Telegram Webhook mekanizması en kararlı yöntemdir. E-posta bildirimlerinin aksine, mobil push gecikmesi p99 düzeyinde < 800ms seviyesindedir.
Adım 1: Bot Oluşturma ve Token Temini
- Telegram üzerinde
@BotFatherbotunu başlatın. /newbotkomutunu gönderin.- Bota tanıtıcı bir ad (
Tropic NOC Alert Bot) ve benzersiz bir kullanıcı adı (tropic_noc_prod_bot) atayın. - BotFather tarafından üretilen
HTTP API Tokendeğerini (7123456789:AAF1B2c3D4e5F6G7h8I9j0K1L2m3N4o5P6Q) not edin.
Adım 2: Alert Grubunun Kurulması ve Chat ID Tespiti
- Alarmların düşeceği bir operasyon grubu oluşturun (örneğin:
NOC-Monitoring). - Yeni oluşturduğunuz botu bu gruba yönetici (Administrator) olarak ekleyin.
- Gruba herhangi bir metin mesajı gönderin (
/test). - Terminalden Telegram API
getUpdatesuç noktasına istek atarak grubun negatif ID değerini çekin:
curl -s "https://api.telegram.org/bot<BOT_TOKEN>/getUpdates" | jq '.result[] | select(.message.chat.type=="group" or .message.chat.type=="supergroup") | .message.chat.id' | head -n 1
Grup kimliği -100 ile başlayan bir tam sayı dönecektir (örneğin: -1002345678901).
Doğrudan API üzerinden test mesajı göndererek bildirim kanalını doğrulayın:
curl -s -X POST "https://api.telegram.org/bot<BOT_TOKEN>/sendMessage" \
-d "chat_id=-1002345678901" \
-d "parse_mode=HTML" \
-d "text=<b>[TROPIC-NOC]</b> Altyapı bildirim kanalı doğrulandı. Ağ geçidi: <i>vds-node-01</i>"
4. Zabbix Web UI Media Type ve Bildirim Şablonu Entegrasyonu
Zabbix 7.0 LTS sürümünde Telegram için yerleşik JavaScript tabanlı Webhook Media Type bulunur. Harici Python veya Bash betiklerine ihtiyaç duymadan doğrudan Zabbix Server motoru tarafından yürütülür.
- Media Type Yapılandırması:
- Alerts > Media types menüsüne gidin.
- Listeden Telegram kaydını açın.
Parameterslistesinde varsayılan değişkenleri kontrol edin:Token:@BotFathertarafından verilen API token değerini girin.ParseMode:HTMLolarak tanımlayın.Message:{ALERT.MESSAGE}Subject:{ALERT.SUBJECT}To: Bildirimin gideceği TelegramChat ID(-1002345678901).
- Mesaj Şablonlarının (Message Templates) Sıkılaştırılması:
- Aynı ekranda Message templates sekmesine geçin.
- Problem türündeki şablonu operasyonel detay sağlayacak şekilde düzenleyin:
<b>PROBLEM: {EVENT.SEVERITY}</b>
<b>Sunucu:</b> {HOST.NAME} ({HOST.IP})
<b>Zaman:</b> {EVENT.DATE} {EVENT.TIME}
<b>Tetikleyici:</b> {EVENT.NAME}
<b>Mevcut Değer:</b> {ITEM.VALUE}
<b>Detay:</b> {EVENT.OPDATA}
<b>Operasyonel Durum:</b> <a href="https://zabbix.sirket.com/tr_events.php?triggerid={TRIGGER.ID}&eventid={EVENT.ID}">Olaya Git</a>
- Problem recovery (Sorun çözüldü) şablonunu tanımlayın:
<b>ÇÖZÜLDÜ: {EVENT.SEVERITY}</b>
<b>Sunucu:</b> {HOST.NAME} ({HOST.IP})
<b>Bitiş Zamanı:</b> {EVENT.RECOVERY.DATE} {EVENT.RECOVERY.TIME}
<b>Süre:</b> {EVENT.AGE}
<b>Tetikleyici:</b> {EVENT.NAME}
<b>Kurtarma Değeri:</b> {ITEM.RECOVERY.VALUE}
- Kullanıcıya Media Tanımlama:
- Administration > Users menüsünden
Adminkullanıcısını seçin. - Media sekmesine tıklayın, Add butonuna basın.
- Type:
Telegram - Send to:
-1002345678901(Grup Chat ID) - When active:
1-7,00:00-24:00 - Use if severity:
Warning,Average,High,Disasterseviyelerini işaretleyin (Informationseviyesini bildirim kirliliğini önlemek için hariç tutun).
5. Kritik Tetikleyiciler (Triggers) ve Aksiyon (Action) Kuralları
Alarmların otomatik iletilmesi için tetikleme kuralları tanımlanmalıdır. Standart şablonlara ek olarak, NVMe depolama ve CPU çalınma oranlarına odaklanan kurallar eklenmelidir.
- Tetikleyici Eşik Değerleri:
- CPU Steal Time Anomali Tespiti:
avg(/vds-node-01.tropic.internal/system.cpu.util[,steal],5m) > 1.5
(KVM ortamında %1.5 üzerindeki sürekli steal time, altyapı sağlayıcısının CPU overcommit yaptığını gösterir; tropic.host mimarisinde bu oran %0.0 olarak korunur). - PostgreSQL Konteyner Durumu:
last(/vds-node-01.tropic.internal/docker.container_state[postgres-server]) <> 1 - NVMe Disk G/Ç Kuyruğu (Disk Queue Length):
min(/vds-node-01.tropic.internal/vfs.dev.queue[nvme0n1],10m) > 5.0 - Action (Eylem) Tanımlaması:
- Alerts > Actions > Trigger actions menüsüne gidin.
- Create action butonuna basın.
- Name:
Auto Alert to Telegram NOC - Conditions:
Trigger severity >= WarningProblem is not suppressed
- Operations:
- Operation type:
Send message - Send to users:
Admin - Send only to:
Telegram
- Operation type:
- Recovery operations:
- Operation type:
Send message - Send to users:
Admin - Send only to:
Telegram
- Operation type:
6. Uçtan Uca Hata Simülasyonu ve Doğrulama
Kurulan alarm mekanizmasının doğrulanması için kontrollü bir servis çöküşü simüle edilmelidir. Zabbix Web konteyneri durdurularak sistemin tepki süresi denetlenir:
# Web konteynerini geçici olarak durdurun
docker stop zabbix-web-nginx-pgsql
Zabbix Agent 2, Docker eklentisi üzerinden konteynerin durduğunu bir sonraki yoklama periyodunda (varsayılan: 15-30 saniye) tespit eder. Zabbix Server tetikleyiciyi aktif hale getirir ve Telegram API'ye HTTP POST isteği gönderir.
Grup kanalına aşağıdaki yapıda bir bildirim düşmelidir:
PROBLEM: High
Sunucu: vds-node-01.tropic.internal (192.0.2.10)
Zaman: 2026-10-04 14:12:05
Tetikleyici: Docker container /zabbix-web-nginx-pgsql is not running
Mevcut Değer: 0
Detay: Container state changed to: exited (137)
Operasyonel Durum: Olaya Git
Hatanın tespitinin ardından konteyneri tekrar ayağa kaldırın:
docker start zabbix-web-nginx-pgsql
Yaklaşık 30 saniye içerisinde ilgili olayın çözüldüğüne dair kurtarma bildirimi Telegram kanalına ulaşacaktır:
ÇÖZÜLDÜ: High
Sunucu: vds-node-01.tropic.internal (192.0.2.10)
Bitiş Zamanı: 2026-10-04 14:13:12
Süre: 1m 7s
Tetikleyici: Docker container /zabbix-web-nginx-pgsql is not running
Kurtarma Değeri: 1
Zabbix Server loglarından Webhook işlem aşamalarını doğrulamak için:
docker logs --tail 50 zabbix-server | grep -E "Telegram|webhook"
Çıktıda Webhook request has been sent successfully ibaresinin görülmesi, altyapının insan müdahalesine gerek kalmadan anomalileri tespit edip raporlayabildiğini doğrular. Donanım seviyesinde kararlı çalışan tropic.host KVM mimarisi ve optimize edilen Agent 2 eklentileriyle birlikte izleme sistemi, false-positive gürültülerinden arındırılmış, deterministik bir telemetri akışına kavuşturulmuştur.
Veritabanı Bakımı ve Adım Adım Felaket Kurtarma (Disaster Recovery)
Docker üzerinde çalışan Zabbix VDS kurulumu mimarisinde PostgreSQL konteyneri, saniyede binlerce metriğin (NVPS - New Values Per Second) yazıldığı en yoğun I/O darboğaz noktasıdır. history, history_uint, trends ve events tablolarına yapılan sürekli INSERT ve UPDATE işlemleri, PostgreSQL'in MVCC (Multi-Version Concurrency Control) mekanizması nedeniyle ölü satırların (dead tuples) birikmesine ve diskte table bloat (tablo şişmesi) oluşmasına yol açar. Düzenli bakım yapılmayan ve felaket kurtarma senaryosu test edilmemiş bir telemetri veritabanı, ani bir donanım arızasında veya veri bozulmasında telafisi mümkün olmayan metrik kayıplarına neden olur.
1. PostgreSQL Bakım Rutinleri: Dead Tuples ve Table Bloat Yönetimi
Zabbix Housekeeper süreci eski verileri silerken disk alanını işletim sistemine geri iade etmez; silinen satırları yalnızca yeni veriler için yeniden kullanılabilir olarak işaretler. Tablolardaki bloat oranını ve ölü satır miktarını denetlemek için PostgreSQL konteynerine bağlanarak aşağıdaki sorgu yürütülür:
docker exec -it zabbix-db-pgsql psql -U zabbix -d zabbix -c "
SELECT relname AS tablo_adi,
n_live_tup AS canli_satir,
n_dead_tup AS olu_satir,
ROUND(n_dead_tup * 100.0 / NULLIF(n_live_tup + n_dead_tup, 0), 2) AS olu_satir_orani
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC;"
Ölü satır oranının %20'yi aştığı senaryolarda autovacuum parametrelerinin агрессивно çalıştırılması zorunludur. tropic.host platformundaki kurumsal sınıf PCIe 4.0 NVMe altyapısı, rastgele 4K QD1 okuma/yazma işlemlerinde 50.000 IOPS sınırının üzerinde çalıştığı için agresif vakumlama işlemleri CPU Steal Time oluşturmaz (%st = 0.0%) ve izleme altyapısının p99 gecikme sürelerini etkilemez.
Yoğun metrik girişi olan ortamlarda haftalık olarak dizinleri yeniden oluşturmak (B-tree indeks parçalanmasını önlemek) ve istatistikleri güncellemek için aşağıdaki bakım komutları konteyner içinde çalıştırılır:
# Tablo kilitlenmelerini önleyerek arka planda indeksleri optimize edin
docker exec -i zabbix-db-pgsql reindexdb -U zabbix -d zabbix --concurrently
# Sorgu planlayıcısının (query planner) yürütme maliyetlerini güncellemesi için istatistikleri tazeleyin
docker exec -i zabbix-db-pgsql vacuumdb -U zabbix -d zabbix --analyze --verbose
2. Tutarlı Mantıksal Yedekleme (Consistent Logical Backup) Mimarisi
Çalışan bir PostgreSQL konteynerinin ham veri dizinini (/var/lib/postgresql/data) doğrudan kopyalamak, Write-Ahead Logging (WAL) mekanizması nedeniyle veritabanının tutarsız (crash-inconsistent) bir durumda kalmasına yol açar. Bu nedenle yedekleme pg_dump yardımcı programı üzerinden özel arşiv formatında (-Fc) alınmalıdır.
Aşağıdaki kabuk betiği; tutarlı bir mantıksal yedekleme üretir, çok çekirdekli zstd ile sıkıştırır, SHA-256 sağlama toplamı (checksum) oluşturur ve 256-bit AES şifrelemesi uygular:
#!/usr/bin/env bash
# /usr/local/bin/zabbix-backup.sh
set -euo pipefail
BACKUP_DIR="/var/backups/zabbix"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="${BACKUP_DIR}/zabbix_db_${TIMESTAMP}.dump"
GPG_PASSPHRASE_FILE="/etc/zabbix/backup_pass.key"
RETENTION_DAYS=14
mkdir -p "${BACKUP_DIR}"
chmod 700 "${BACKUP_DIR}"
echo "[+] [$(date +'%Y-%m-%d %H:%M:%S')] Veritabanı yedeği başlatılıyor..."
# PostgreSQL konteynerinden tutarlı arşiv formatında (-Fc) dışa aktarma
docker exec -e PGPASSWORD="ZabbixStrongPassword2026!" zabbix-db-pgsql \
pg_dump -U zabbix -d zabbix -Fc --no-owner --no-privileges > "${BACKUP_FILE}"
echo "[+] Sıkıştırma ve şifreleme işlemi uygulanıyor..."
# Çok çekirdekli zstd sıkıştırması ve GPG simetrik şifreleme
zstd -T0 --rm "${BACKUP_FILE}" -o "${BACKUP_FILE}.zst"
gpg --batch --yes --passphrase-file "${GPG_PASSPHRASE_FILE}" \
--symmetric --cipher-algo AES256 "${BACKUP_FILE}.zst"
rm -f "${BACKUP_FILE}.zst"
# Doğrulama için SHA-256 sağlama toplamı üretme
sha256sum "${BACKUP_FILE}.zst.gpg" > "${BACKUP_FILE}.zst.gpg.sha256"
# Belirlenen saklama süresinden eski yedekleri temizleme
find "${BACKUP_DIR}" -name "zabbix_db_*.dump.zst.gpg*" -mtime +"${RETENTION_DAYS}" -delete
echo "[+] [$(date +'%Y-%m-%d %H:%M:%S')] Yedekleme başarıyla tamamlandı: ${BACKUP_FILE}.zst.gpg"
Betiğin her gece 02:00'de düzenli çalışması için crontab kaydı tanımlanır:
0 2 * * * /usr/local/bin/zabbix-backup.sh >> /var/log/zabbix-backup.log 2>&1
3. Sıfırdan Adım Adım Felaket Kurtarma (Disaster Recovery Playbook)
Bu senaryoda, fiziksel bir arıza veya dosya sistemi bozulması sonucu Zabbix veritabanının çöktüğü ve sistemin yeni bir tropic.host KVM VDS sunucusu üzerinde sıfırdan ayağa kaldırıldığı varsayılmaktadır.
+-------------------------------------------------------------------+
| 1. Servis İzolasyonu (Trafik ve Veri Girişi Kesilir) |
| docker stop zabbix-server zabbix-web-nginx-pgsql |
+---------------------------------+---------------------------------+
|
v
+-------------------------------------------------------------------+
| 2. Arşiv Bütünlük Doğrulaması (Checksum & Decrypt) |
| sha256sum -c && gpg --decrypt | unzstd |
+---------------------------------+---------------------------------+
|
v
+-------------------------------------------------------------------+
| 3. Veritabanı Temizliği ve Yeniden Başlatma |
| DROP DATABASE zabbix WITH (FORCE) -> CREATE DATABASE |
+---------------------------------+---------------------------------+
|
v
+-------------------------------------------------------------------+
| 4. Paralel Geri Yükleme (Parallel pg_restore) |
| pg_restore -j $(nproc) --clean --exit-on-error |
+---------------------------------+---------------------------------+
|
v
+-------------------------------------------------------------------+
| 5. Veri Bütünlüğü Doğrulaması ve Servis Aktivasyonu |
| Tablo satır sayıları & Son telemetri zaman damgası |
+-------------------------------------------------------------------+
Adım 1: Servisleri Durdurarak Veri Girişini Dondurun
Geri yükleme sırasında veri çakışmalarını, kilitlenmeleri ve eksik işlemleri engellemek için Zabbix Server ve Web arayüz konteynerleri durdurulmalıdır:
docker stop zabbix-server zabbix-web-nginx-pgsql
Adım 2: Yedek Dosyasının Bütünlüğünü Doğrulayın ve Açın
Harici depolama veya S3 alanından indirilen şifreli arşiv dosyasının sağlama toplamı kontrol edilir ve dosya açılır:
cd /var/backups/zabbix
# SHA-256 doğrulamasını gerçekleştirin
sha256sum -c zabbix_db_20261004_020000.dump.zst.gpg.sha256
# GPG şifresini çözün
gpg --batch --decrypt --passphrase-file /etc/zabbix/backup_pass.key \
-o zabbix_restore.dump.zst zabbix_db_20261004_020000.dump.zst.gpg
# zstd sıkıştırmasını çözün
unzstd zabbix_restore.dump.zst -o /tmp/zabbix_restore.dump
Adım 3: PostgreSQL Konteynerinde Bozuk Şemayı Temizleyin
Eski veya bozulmuş tablolarla çakışma yaşanmaması adına zabbix veritabanı silinip boş bir şema ile tekrar oluşturulmalıdır:
# Açık oturumları sonlandırıp veritabanını silin
docker exec -i zabbix-db-pgsql psql -U zabbix -d postgres -c "
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'zabbix' AND pid <> pg_backend_pid();
DROP DATABASE IF EXISTS zabbix;
CREATE DATABASE zabbix WITH OWNER = zabbix ENCODING = 'UTF8' LC_COLLATE = 'C' LC_CTYPE = 'C';"
Adım 4: Paralel Geri Yükleme İşlemini Yürütün
AMD EPYC ve Ryzen 9 işlemcilerin çoklu iş parçacığı gücünden faydalanarak indekslerin ve verilerin eşzamanlı aktarılması amacıyla pg_restore komutu -j (jobs) parametresiyle çalıştırılır:
# Dump dosyasını konteyner içerisine kopyalayın
docker cp /tmp/zabbix_restore.dump zabbix-db-pgsql:/tmp/zabbix_restore.dump
# Çekirdek sayısına göre paralel geri yüklemeyi başlatın (örnek: 4 worker)
docker exec -i zabbix-db-pgsql \
pg_restore -U zabbix -d zabbix \
-j 4 \
--clean \
--if-exists \
--no-owner \
--no-privileges \
/tmp/zabbix_restore.dump
# Konteyner içerisindeki geçici dump dosyasını temizleyin
docker exec -i zabbix-db-pgsql rm -f /tmp/zabbix_restore.dump
rm -f /tmp/zabbix_restore.dump
Adım 5: Veritabanı Bütünlüğünü Doğrulayın
Geri yüklemenin eksiksiz bittiğini doğrulamak için kritik tablolardaki kayıt sayıları ve en son toplanan metrik zaman damgaları sorgulanır:
docker exec -it zabbix-db-pgsql psql -U zabbix -d zabbix -c "
SELECT
(SELECT COUNT(*) FROM hosts WHERE status IN (0,1)) AS tanimli_host_sayisi,
(SELECT COUNT(*) FROM items WHERE status = 0) AS aktif_metrik_sayisi,
(SELECT to_timestamp(MAX(clock)) FROM history_uint) AS son_alinan_metrik_zamani;"
Dönen çıktıda host ve item sayılarının beklenen değerlerle eşleştiği, son_alinan_metrik_zamani değerinin ise alınan yedeğin zamanıyla örtüştüğü teyit edilmelidir.
Adım 6: Zabbix Servislerini Başlatın ve Log Akışını Denetleyin
Veri doğrulaması tamamlandıktan sonra uygulama katmanı yeniden aktif edilir:
docker start zabbix-server zabbix-web-nginx-pgsql
Sunucu logları izlenerek database is up to date, server #0 started ve poller süreçlerinin başarıyla devreye girdiği kontrol edilir:
docker logs --tail 100 -f zabbix-server | grep -E "syncing|started|database"
4. RPO ve RTO Metriklerinin Garanti Altına Alınması
Kurumsal izleme mimarilerinde iki temel parametre operasyonel sürekliliği belirler:
- RPO (Recovery Point Objective): Tolere edilebilir maksimum veri kaybı süresidir. Yukarıdaki günlük mantıksal yedekleme stratejisi 24 saatlik bir RPO sağlar. Kritik kurumsal sistemlerde RPO süresini dakikalar seviyesine indirmek için PostgreSQL WAL arşivleme (
archive_mode = on,archive_command = 'test ! -f /wal_archive/%f && cp %p /wal_archive/%f') devreye alınmalı ve uzak bir nesne depolama (S3) alanına sürekli senkronize edilmelidir. - RTO (Recovery Time Objective): Sistemin çöküş anından tamamen çalışır hale gelmesine kadar geçen süredir. Zabbix VDS kurulumu Docker altyapısında 50 GB boyutundaki bir PostgreSQL veritabanının geri yüklenmesi, geleneksel SATA HDD veya paylaşımlı depolama havuzlarında indeks inşası nedeniyle saatler sürebilir.
tropic.host altyapısının sağladığı tahsisli KVM kaynakları ve PCIe 4.0 NVMe depolama birimleri, pg_restore işleminin eşzamanlı 4 worker (-j 4) ile çalıştırıldığında diske yazma kuyruklarını (queue depth) şişirmeden 50 GB'lık veri setini 8-12 dakika aralığında tamamen indeksleyerek devreye almasını sağlar. Bu sayede felaket kurtarma sürecindeki RTO süresi minimum seviyede tutulur ve izleme altyapısının kör noktada kalma süresi ortadan kaldırılır.
Sıkça Sorulan Sorular (SSS)
Zabbix için VDS üzerinde ne kadar RAM ve CPU gerekir?
100-200 sunucuyu izlemek için 4 vCPU, 8 GB RAM ve yüksek IOPS sunan NVMe diskli bir KVM VDS önerilir.
Zabbix neden OpenVZ yerine KVM VDS gerektirir?
Zabbix yoğun disk I/O ve veritabanı sorguları çalıştırır. KVM sanallaştırma, %st=0.0% CPU Steal Time ve ayrılmış kaynak garantisi sunar.