Sunucunun performansı düşmeye başladığında, ilk bakılacak yerlerden biri swap kullanımı ve kernel parametreleridir. Yıllarca Ubuntu sunucu yönettikten sonra şunu net söyleyebilirim: doğru yapılandırılmış bir sistem ile fabrika ayarlarında bırakılmış bir sistem arasındaki fark, yoğun trafik altında gece yarısı aldığın alarmların sayısında kendini gösterir. Bu yazıda Ubuntu sunucularda swap yönetimini ve kernel parametrelerini gerçek dünya senaryolarıyla ele alacağız.
Swap Nedir ve Neden Önemlidir?
Swap, RAM dolduğunda işletim sisteminin disk alanını geçici bellek olarak kullandığı mekanizmadır. Kulağa basit geliyor ama yanlış yapılandırıldığında sisteminizi felce uğratabilir. Disk I/O, RAM’e kıyasla binlerce kat yavaştır. Dolayısıyla swap’ı “ekstra bellek” gibi değil, “son çare tamponu” gibi düşünmek gerekir.
Modern Ubuntu sunucularda swap konusunda iki yaygın hata görüyorum: ya hiç swap yok ya da swap var ama swappiness değeri yanlış ayarlanmış. İkisi de farklı şekillerde sorun çıkarır.
Mevcut Swap Durumunu Kontrol Etme
Önce nerede durduğumuzu anlayalım:
# Swap durumunu genel görüntüle
free -h
# Daha detaylı swap bilgisi
swapon --show
# Swap kullanımını anlık izle
watch -n 2 'cat /proc/meminfo | grep -E "MemTotal|MemFree|MemAvailable|SwapTotal|SwapFree|SwapCached"'
Çıktıda SwapTotal: 0 görüyorsanız sisteminizde hiç swap yok demektir. Bu bazı durumlarda kasıtlıdır (Kubernetes node’ları gibi) ama çoğu senaryoda bir sorun olabilir.
Swap Dosyası Oluşturma ve Yapılandırma
Ubuntu 20.04 ve sonrasında swap partition yerine swap dosyası kullanmak daha esnektir. Boyutu sonradan değiştirebilir, birden fazla swap alanı ekleyebilirsiniz.
# 4GB swap dosyası oluştur (fallocate kullan, dd'den hızlıdır)
sudo fallocate -l 4G /swapfile
# Doğru izinleri ayarla
sudo chmod 600 /swapfile
# Swap alanı olarak formatla
sudo mkswap /swapfile
# Swap'ı etkinleştir
sudo swapon /swapfile
# Kalıcı hale getir
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# Doğrulama
swapon --show
free -h
Pratik not: Eğer fallocate hata verirse (bazı dosya sistemlerinde verir), alternatif olarak dd kullanabilirsiniz:
sudo dd if=/dev/zero of=/swapfile bs=1M count=4096 status=progress
Swap Boyutu Ne Olmalı?
Bu sorunun evrensel bir cevabı yok ama pratik rehberim şu:
- Web sunucusu (8GB RAM altı): RAM ile eşit miktarda swap
- Veritabanı sunucusu: RAM’in yarısı kadar, hatta daha az (DB’nin RAM’de çalışmasını istiyorsunuz)
- Geliştirme/test sunucusu: RAM’in 1.5-2 katı
- Kubernetes node’u: Genellikle swap kapatılır, kubelet swap ile sorun yaşar
- 64GB+ RAM’li production sunucu: 4-8GB sabit, daha fazlası gerekmez
Swappiness: Kernel’in Swap Kararları
vm.swappiness parametresi, kernel’in RAM dolu olmadan önce ne kadar agresif swap kullanacağını belirler. 0 ile 100 arasında bir değer alır.
# Mevcut değeri kontrol et
cat /proc/sys/vm/swappiness
# Ubuntu'nun varsayılan değeri genellikle 60'tır
sysctl vm.swappiness
Varsayılan 60 değeri masaüstü sistemler için makul ama sunucular için genellikle çok yüksektir. Bu değer, kernel’in RAM’in %40’ı dolu olduğunda bile swap’a yazmaya başlayabileceği anlamına gelir.
Swappiness Değerini Kalıcı Olarak Ayarlama
# Anlık değiştir (reboot sonrası sıfırlanır)
sudo sysctl vm.swappiness=10
# Kalıcı hale getir
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.d/99-sysadmin-tweaks.conf
# Değişikliği uygula
sudo sysctl -p /etc/sysctl.d/99-sysadmin-tweaks.conf
Hangi değer ne anlama gelir:
- vm.swappiness=0: Swap’ı neredeyse hiç kullanma, sadece OOM durumunda
- vm.swappiness=10: Sunucular için önerilen, RAM dolmadan swap’a gitmez
- vm.swappiness=60: Ubuntu varsayılanı, masaüstü için uygun
- vm.swappiness=100: Her fırsatta swap kullan, eski kernel optimizasyon tekniği
Production web sunucularım için genellikle 10, yoğun veritabanı sunucuları için ise 1 kullanıyorum.
Kritik Kernel Parametreleri
/etc/sysctl.d/ altında özel bir dosya oluşturmak en temiz yaklaşımdır. Böylece Ubuntu güncellemeleri sizin ayarlarınızı ezmez.
sudo nano /etc/sysctl.d/99-performance.conf
Bellek Yönetimi Parametreleri
# Swappiness - RAM dolmadan swap kullanma
vm.swappiness=10
# Dirty ratio - Bellekteki kirli sayfaların ne kadarı dolunca diske yazılsın
# Varsayılan 20, yüksek I/O sistemlerde düşürebilirsiniz
vm.dirty_ratio=15
# Dirty background ratio - Arka planda yazma başlangıç noktası
vm.dirty_background_ratio=5
# Cache pressure - Dosya sistemi cache'ini ne kadar agresif temizlesin
# Varsayılan 100, 50 değeri cache'i daha uzun tutar
vm.vfs_cache_pressure=50
# Overcommit - Memory overcommit politikası
# 0: Heuristic, 1: Her zaman izin ver, 2: Asla overcommit etme
vm.overcommit_memory=1
vm.dirty_ratio ve vm.dirty_background_ratio arasındaki fark önemli: dirty_background_ratio dolduğunda kernel arka planda sessizce yazmaya başlar, dirty_ratio dolduğunda ise yazan process bloklanır. Yoğun yazma yapan sistemlerde bu iki değeri dengelemek kritiktir.
Ağ Performansı için TCP/IP Parametreleri
Bir production sunucusunda ağ optimizasyonu yapmadan bellek optimizasyonu eksik kalır:
# TCP buffer boyutlarını artır
net.core.rmem_default=262144
net.core.rmem_max=16777216
net.core.wmem_default=262144
net.core.wmem_max=16777216
# TCP otomatik buffer tuning
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
# SYN flood koruması
net.ipv4.tcp_syncookies=1
# TIME_WAIT socket'leri yeniden kullan
net.ipv4.tcp_tw_reuse=1
# FIN_WAIT_2 timeout (varsayılan 60 saniye)
net.ipv4.tcp_fin_timeout=30
# TCP keepalive ayarları
net.ipv4.tcp_keepalive_time=1200
net.ipv4.tcp_keepalive_probes=5
net.ipv4.tcp_keepalive_intvl=15
# Backlog queue boyutu
net.core.somaxconn=65535
net.ipv4.tcp_max_syn_backlog=65535
Yüksek trafikli bir Nginx sunucusunda net.core.somaxconn değerini 128’den (varsayılan) 65535’e çıkardığımda “connection refused” hatalarında ciddi düşüş yaşadım. Bu parametre, bir socket’in kabul edebileceği bağlantı kuyruğu uzunluğunu belirler.
Dosya Sistemi ve I/O Limitleri
# Maksimum açık dosya sayısı (system-wide)
fs.file-max=2097152
# inotify limitleri (özellikle Docker ve monitoring araçları için)
fs.inotify.max_user_watches=524288
fs.inotify.max_user_instances=512
fs.inotify.max_user_watches değerini artırmak özellikle Docker kullanan sistemlerde veya Prometheus/Grafana gibi çok sayıda dosya izleyen araçlarda karşılaşılan “inotify watch limit reached” hatasını çözer.
Tüm Değişiklikleri Uygulama
# Tüm sysctl.d dosyalarını yeniden yükle
sudo sysctl --system
# Sadece belirli bir dosyayı uygula
sudo sysctl -p /etc/sysctl.d/99-performance.conf
# Mevcut tüm değerleri listele
sudo sysctl -a | grep vm.
# Belirli bir değeri sorgula
sysctl net.core.somaxconn
Gerçek Dünya Senaryosu: E-Ticaret Sitesinde Performans Krizi
Birkaç yıl önce bir e-ticaret sitesinde gece yoğun kampanya trafiğinde yaşanan sorunları inceleyelim. Sunucu özellikleri: 16GB RAM, 8 vCPU, Ubuntu 20.04, Nginx + PHP-FPM + MySQL.
Semptomlar:
- Yoğun trafikte sayfa yükleme süreleri 2-3 saniyeden 15-20 saniyeye çıkıyor
topkomutu swap kullanımının 2GB’ı aştığını gösteriyor- MySQL sorgu süreleri aniden yükseliyor
Teşhis:
# Swap kullanımını izle
vmstat 1 10
# Hangi process'ler swap kullanıyor
for pid in $(ls /proc | grep -E '^[0-9]+$'); do
swap=$(grep VmSwap /proc/$pid/status 2>/dev/null | awk '{print $2}')
if [ ! -z "$swap" ] && [ "$swap" -gt 0 ]; then
name=$(cat /proc/$pid/comm 2>/dev/null)
echo "$swap kB - PID $pid ($name)"
fi
done | sort -rn | head -20
Sorun: Swappiness 60 olduğu için PHP-FPM worker process’leri swap’a alınmış, MySQL buffer pool’u ise disk I/O baskısı altında kalmış.
Çözüm:
# Acil müdahale - anlık değişiklikler
sudo sysctl vm.swappiness=10
sudo sysctl vm.vfs_cache_pressure=50
# MySQL için özel ayar - büyük sayfalar
sudo sysctl vm.nr_hugepages=512
# Swap'ı temizle (dikkatli kullan, yeterli free RAM olduğundan emin ol)
sudo swapoff -a && sudo swapon -a
Kampanya süresince %40 performans artışı gözlemledik. Sonrasında bu değerleri kalıcı hale getirdik.
Huge Pages Yapılandırması
Büyük bellek kullanan uygulamalar (MySQL, PostgreSQL, Oracle, Redis) için Transparent Huge Pages (THP) ayarı önemlidir.
# Mevcut THP durumunu kontrol et
cat /sys/kernel/mm/transparent_hugepage/enabled
# Çıktı: [always] madvise never
# Köşeli parantez içindeki aktif seçenektir
MySQL ve PostgreSQL için THP’yi kapatmak genellikle daha iyi performans verir çünkü bu uygulamalar kendi bellek yönetimini yapar:
# Anlık kapat
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
# Kalıcı hale getirmek için grub parametresi ekle
sudo nano /etc/default/grub
# GRUB_CMDLINE_LINUX satırına ekle:
# transparent_hugepage=never
# Grub'u güncelle
sudo update-grub
Not: THP her uygulama için kötü değildir. Java uygulamaları ve büyük in-memory işlemler için THP açık bırakmak faydalı olabilir. Kararı uygulamanızın dokümantasyonuna göre verin.
OOM Killer Yapılandırması
Out of Memory (OOM) Killer, RAM bittiğinde kernel’in process öldürme mekanizmasıdır. Yanlış yapılandırıldığında kritik servislerinizi öldürebilir.
# OOM olaylarını logdan kontrol et
sudo dmesg | grep -i "oom|out of memory|killed process"
sudo journalctl -k | grep -i oom
# Bir process'in OOM skorunu görüntüle (yüksek skor = önce öldürülür)
cat /proc/$(pgrep nginx | head -1)/oom_score
# Kritik bir process'i OOM'dan koru (-1000 = asla öldürme)
echo -1000 | sudo tee /proc/$(pgrep sshd | head -1)/oom_score_adj
# Servis başlangıcında otomatik ayarlamak için systemd unit'e ekle
# [Service] bölümüne:
# OOMScoreAdjust=-500
# MySQL için OOM koruması ekle
sudo systemctl edit mysql
# Açılan editöre ekle:
[Service]
OOMScoreAdjust=-800
Bu ayar MySQL’in OOM Killer tarafından seçilme olasılığını ciddi oranda düşürür. Kritik servisler için mutlaka yapın.
Performans İzleme ve Doğrulama
Yaptığınız değişikliklerin işe yarayıp yaramadığını ölçmeniz gerekir:
#!/bin/bash
# Sistem performans özeti scripti
# /usr/local/bin/perf-check.sh olarak kaydedin
echo "=== BELLEK DURUMU ==="
free -h
echo ""
echo "=== SWAP KULLANIMI ==="
swapon --show
echo ""
echo "=== KERNEL PARAMETRELER ==="
echo "Swappiness: $(sysctl -n vm.swappiness)"
echo "Dirty ratio: $(sysctl -n vm.dirty_ratio)"
echo "VFS cache pressure: $(sysctl -n vm.vfs_cache_pressure)"
echo "Somaxconn: $(sysctl -n net.core.somaxconn)"
echo ""
echo "=== I/O ISTATISTIKLERI ==="
iostat -x 1 3 | tail -20
echo ""
echo "=== EN FAZLA BELLEK KULLANAN 10 PROCESS ==="
ps aux --sort=-%mem | head -11
chmod +x /usr/local/bin/perf-check.sh
sudo perf-check.sh
Systemd ile Servis Limitleri
Kernel parametrelerinin yanı sıra, systemd servis limitlerini de ayarlamak önemlidir:
# Açık dosya limitini sistem genelinde artır
sudo nano /etc/systemd/system.conf
# Şu satırları ekle veya uncomment et:
DefaultLimitNOFILE=65536
DefaultLimitNPROC=32768
# Nginx için özel limit
sudo systemctl edit nginx
[Service]
LimitNOFILE=65536
LimitNPROC=32768
# Systemd'yi yeniden yükle ve servisi restart et
sudo systemctl daemon-reload
sudo systemctl restart nginx
# Limitlerin uygulandığını doğrula
cat /proc/$(pgrep nginx | head -1)/limits
Değişiklikleri Güvenli Test Etme
Production ortamında doğrudan kalıcı değişiklik yapmak risklidir. Şu yaklaşımı öneririm:
# 1. Mevcut değerleri yedekle
sudo sysctl -a > /root/sysctl-backup-$(date +%Y%m%d).txt
# 2. Değişikliği anlık uygula ve test et
sudo sysctl vm.swappiness=10
# 3. 24-48 saat izle
watch -n 5 'free -h && echo "---" && swapon --show'
# 4. Tatmin edici sonuç alınca kalıcı hale getir
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.d/99-performance.conf
sudo sysctl --system
# 5. Reboot sonrası doğrula
sudo reboot
# Reboot sonrasında:
sysctl vm.swappiness
Bu yaklaşım sayesinde “reboot sonrası neden çalışmıyor?” sorusunu yaşamazsınız.
Sık Yapılan Hatalar
Swap’ı tamamen kapatmak: Kubernetes node’ları hariç genellikle iyi bir fikir değildir. OOM Killer agresifleşir ve beklenmedik process ölümleri yaşanır.
vm.overcommit_memory=1 her yerde: Redis ve bazı Java uygulamaları için gerekli olabilir ama veritabanı sunucularında dikkatli kullanın. Memory overcommit açıkken sisteminiz gerçekte sahip olduğundan fazla bellek “vaat” eder.
Yüksek dirty_ratio: 40-60 gibi değerler yazma performansını artırır gibi görünse de ani bir process ölümünde diske yazılmamış büyük miktarda veri kaybedebilirsiniz.
net.ipv4.tcp_tw_recycle: Bu parametre eski kernel versiyonlarında vardı ama modern Linux’ta kaldırıldı. Hala internette bu öneriyi görüyorsanız, o kaynağa güvenmeyiniz.
Sonuç
Ubuntu sunucu optimizasyonu tek seferlik bir iş değil, sürekli ölçüp ayarlama gerektiren bir süreçtir. Şu adımları takip ederseniz sağlam bir başlangıç yaparsınız: önce mevcut durumu ölçün, sonra darboğazı tespit edin, ardından değişikliği anlık uygulayıp izleyin, sonuç tatmin ediciyse kalıcı hale getirin.
En sık önerdiğim temel ayarlar swappiness’ı 10’a çekmek, dirty_background_ratio’yu 5’e düşürmek, somaxconn’u artırmak ve kritik servisleri OOM’dan korumaktır. Bu dört değişiklik bile ortalama bir Ubuntu sunucusunda gözle görülür fark yaratır.
Parametreleri kör kopyala-yapıştır yapmanızı önermiyorum. Her sunucu, üzerinde çalışan uygulama, RAM miktarı ve I/O profiliyle farklıdır. Bu yazıdaki değerleri başlangıç noktası olarak alın, kendi ortamınızda test edin ve gerçek metriklerle kararınızı verin. Gece 3’te alarm almamak için harcadığınız bu ekstra çaba, kesinlikle değecektir.