OpenLiteSpeed ile Zero Downtime Güncelleme

Production ortamında çalışan bir web sunucusunu güncellemek, her sistem yöneticisinin korkulu rüyasıdır. Özellikle yüksek trafikli sitelerde “bir dakika bile downtime olmaz” baskısı altında güncelleme yapmak ciddi bir stres kaynağıdır. OpenLiteSpeed, bu sorunu çözmek için oldukça iyi bir altyapı sunuyor. Bu yazıda, OpenLiteSpeed’i production ortamında sıfır kesinti ile nasıl güncelleyeceğinizi, graceful restart mekanizmalarını ve olası sorunlara karşı rollback stratejilerini detaylıca ele alacağız.

OpenLiteSpeed’in Zero Downtime Mimarisi

OpenLiteSpeed, Apache ve Nginx’ten farklı olarak event-driven bir mimariye sahip. Bu mimari, güncelleme süreçlerini de doğrudan etkiliyor. OLS’nin zero downtime güncellemesini mümkün kılan birkaç temel özellik var:

Graceful Restart Mekanizması: OLS, yeni bir konfigürasyon veya binary yüklendiğinde mevcut bağlantıları kesmeden yeni worker process’leri başlatabilir. Eski worker’lar aktif bağlantılarını tamamladıktan sonra kapatılır.

In-Process Worker Model: Nginx’in aksine OLS, worker process’lerini daha akıllı yönetir. Her worker belirli bir bağlantı grubunu yönetir ve bir worker yeniden başlatılırken diğerleri görevlerine devam eder.

Socket Reuse: OLS, TCP soketini güncelleme sürecinde açık tutabilir. Bu sayede yeni bağlantılar hiç kesilmez, sadece işlenecekleri process değişir.

Teorik bilgi bir kenara, hemen pratiğe geçelim.

Güncelleme Öncesi Hazırlık

Zero downtime güncellemenin en kritik aşaması aslında güncelleme öncesidir. Aceleyle atlanan hazırlık adımları sonradan saatler süren sorun gidermeye dönüşebilir.

Mevcut Durumu Belgeleyin

# Mevcut OLS versiyonunu kaydet
/usr/local/lsws/bin/lshttpd -v > /root/ols_backup/pre_update_version.txt

# Çalışan process'leri kaydet
ps aux | grep lsws > /root/ols_backup/pre_update_processes.txt

# Aktif bağlantı sayısını kontrol et
ss -tn state established | grep ':80|:443' | wc -l

# Mevcut konfigürasyonu yedekle
cp -r /usr/local/lsws/conf /root/ols_backup/conf_$(date +%Y%m%d_%H%M%S)

Bu adımı otomatikleştirmek için küçük bir script yazabilirsiniz:

#!/bin/bash
# pre_update_check.sh

BACKUP_DIR="/root/ols_backup/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"

echo "[INFO] Versiyon bilgisi kaydediliyor..."
/usr/local/lsws/bin/lshttpd -v > "$BACKUP_DIR/version.txt" 2>&1

echo "[INFO] Konfigürasyon yedekleniyor..."
cp -r /usr/local/lsws/conf "$BACKUP_DIR/conf"
cp -r /usr/local/lsws/admin/conf "$BACKUP_DIR/admin_conf"

echo "[INFO] Aktif bağlantı durumu kaydediliyor..."
ss -tn state established | grep ':80|:443' > "$BACKUP_DIR/connections.txt"

echo "[INFO] Virtual host listesi kaydediliyor..."
ls -la /usr/local/lsws/conf/vhosts/ > "$BACKUP_DIR/vhosts_list.txt"

echo "[DONE] Yedekleme tamamlandı: $BACKUP_DIR"
echo "Güncellemeye devam etmek için Enter'a basın, iptal için Ctrl+C..."
read

Monitoring Kurulumu

Güncelleme sırasında ne olduğunu görmek için ayrı bir terminal açın ve anlık izleme başlatın:

# Terminal 1: Response time izleme
while true; do
  response=$(curl -s -o /dev/null -w "%{http_code} - %{time_total}s" http://localhost/)
  echo "$(date '+%H:%M:%S') - $response"
  sleep 1
done

Bu script güncelleme boyunca çalışmalı. Eğer response code 200’den farklı bir şey görürseniz, bir yerlerde hata var demektir.

Güncelleme Yöntemleri

Yöntem 1: Paket Yöneticisi ile Güncelleme (Önerilen)

Eğer OLS’yi resmi paket deposundan kurduysanız, bu en temiz yöntemdir.

# CentOS/RHEL için
yum update openlitespeed

# Ubuntu/Debian için
apt-get update && apt-get upgrade openlitespeed

# Güncelleme sonrası graceful restart
/usr/local/lsws/bin/lswsctrl restart

Ancak burada önemli bir nokta var: restart komutu ile graceful restart farklı şeylerdir. Standart restart tüm bağlantıları anında keser. Bunu kullanmayın.

Doğru yol:

# Graceful restart - mevcut bağlantılar tamamlanana kadar bekler
kill -USR1 $(cat /tmp/lshttpd.pid)

# Ya da OLS'nin kendi graceful restart komutu
/usr/local/lsws/bin/lswsctrl graceful

Yöntem 2: Manuel Binary Güncelleme

Paket deposu kullanmıyorsanız veya özel bir derleme yapıyorsanız, bu yöntemi kullanmanız gerekir. Bu yöntem biraz daha dikkat ister.

# Önce yeni versiyonu indir
cd /tmp
wget https://openlitespeed.org/packages/openlitespeed-X.X.X.tgz

# Arşivi aç
tar -xzf openlitespeed-X.X.X.tgz
cd openlitespeed-X.X.X

# Mevcut binary'yi yedekle
cp /usr/local/lsws/bin/lshttpd /usr/local/lsws/bin/lshttpd.bak.$(date +%Y%m%d)

# Kurulumu çalıştır - mevcut konfigürasyonları koruyarak
./install.sh --no-root-check

Kurulum sırasında size konfigürasyon dosyalarının üzerine yazılıp yazılmayacağı sorulur. Her zaman “N” (hayır) deyin. Konfigürasyon dosyalarınızı korumak zorundasınız.

Yöntem 3: Blue-Green Deployment ile OLS Güncelleme

Kritik sistemlerde en güvenilir yöntem blue-green deployment’tır. İki özdeş sunucu ya da iki ayrı OLS instance’ı kullanarak sıfır riskle güncelleme yapabilirsiniz.

#!/bin/bash
# blue_green_ols_update.sh
# Bu script load balancer arkasında çalışan iki OLS instance'ı için

BLUE_SERVER="192.168.1.10"
GREEN_SERVER="192.168.1.11"
LB_CONFIG="/etc/haproxy/haproxy.cfg"
ACTIVE_SERVER=""

# Aktif sunucuyu tespit et
check_active() {
  if curl -sf "http://$BLUE_SERVER/health" > /dev/null; then
    ACTIVE_SERVER="blue"
    INACTIVE_SERVER="green"
    INACTIVE_IP="$GREEN_SERVER"
  else
    ACTIVE_SERVER="green"
    INACTIVE_SERVER="blue"
    INACTIVE_IP="$BLUE_SERVER"
  fi
  echo "[INFO] Aktif sunucu: $ACTIVE_SERVER ($INACTIVE_IP inaktif)"
}

# İnaktif sunucuyu güncelle
update_inactive() {
  echo "[INFO] $INACTIVE_SERVER sunucusu güncelleniyor..."
  ssh root@"$INACTIVE_IP" "
    apt-get update && apt-get upgrade -y openlitespeed
    /usr/local/lsws/bin/lswsctrl restart
    sleep 5
    curl -sf http://localhost/health || exit 1
  "

  if [ $? -eq 0 ]; then
    echo "[SUCCESS] $INACTIVE_SERVER güncellendi ve sağlık kontrolü geçti"
    return 0
  else
    echo "[ERROR] $INACTIVE_SERVER güncellemesi başarısız!"
    return 1
  fi
}

check_active
update_inactive

if [ $? -eq 0 ]; then
  echo "[INFO] Traffic $INACTIVE_SERVER'a yönlendiriliyor..."
  # HAProxy veya nginx upstream değişikliği burada yapılır
fi

Graceful Restart’ın Derinlerine İnmek

OLS’nin graceful restart mekanizmasını gerçekten anlamak, sorun yaşandığında hayat kurtarıcı olur.

OLS’ye SIGUSR1 sinyali gönderildiğinde şu süreç işler:

  • Ana process yeni konfigürasyonu yükler ve doğrular
  • Yeni worker process’ler başlatılır
  • Eski worker’lara “yeni bağlantı alma” sinyali gönderilir
  • Eski worker’lar mevcut isteklerini tamamlar
  • Tüm eski bağlantılar kapandıktan sonra eski worker’lar sonlandırılır

Bu sürecin ne kadar sürdüğünü izlemek için:

# Graceful restart başlat ve process'leri izle
kill -USR1 $(cat /tmp/lshttpd.pid)

# Process sayısını anlık izle
watch -n 1 'ps aux | grep lshttpd | grep -v grep | wc -l'

Graceful restart sırasında process sayısının geçici olarak arttığını görürsünüz. Bu normaldir. Eski worker’lar ölürken yenileri başlamıştır.

Keep-Alive Bağlantıları ve Timeout Yönetimi

Graceful restart’ın en sık sorun çıkardığı yer keep-alive bağlantılarıdır. Uzun süre açık kalan bir keep-alive bağlantısı varsa, eski worker process de o süre boyunca canlı kalmak zorunda.

# OLS konfigürasyonunda keep-alive timeout'u optimize edin
# /usr/local/lsws/conf/httpd_config.conf dosyasında

keepAliveTimeout  5        # Varsayılan 15'ten 5'e düşürün
maxKeepAliveReq   100      # Maksimum keep-alive istek sayısı

Admin panelinden de yapabilirsiniz ama config dosyasını elle düzenlemek daha hızlıdır. Değişiklikten sonra graceful restart uygulayın:

/usr/local/lsws/bin/lswsctrl graceful

# Başarılı oldu mu kontrol et
echo $?

Güncelleme Sonrası Doğrulama

Güncelleme tamam, peki her şey yolunda mı? Bu soruyu sistematik bir şekilde cevaplamanız gerekiyor.

#!/bin/bash
# post_update_validation.sh

ERRORS=0
WARNINGS=0

echo "========================================="
echo "OLS Güncelleme Sonrası Doğrulama"
echo "========================================="

# Versiyon kontrolü
echo ""
echo "[1] Versiyon Kontrolü"
NEW_VERSION=$(/usr/local/lsws/bin/lshttpd -v 2>&1 | head -1)
echo "    Yeni versiyon: $NEW_VERSION"

# Process kontrolü
echo ""
echo "[2] Process Kontrolü"
if pgrep -x "lshttpd" > /dev/null; then
  PROC_COUNT=$(pgrep -x "lshttpd" | wc -l)
  echo "    OLS process sayısı: $PROC_COUNT - OK"
else
  echo "    [ERROR] OLS çalışmıyor!"
  ERRORS=$((ERRORS + 1))
fi

# Port dinleme kontrolü
echo ""
echo "[3] Port Dinleme Kontrolü"
for port in 80 443 7080; do
  if ss -tlnp | grep -q ":$port"; then
    echo "    Port $port: Dinleniyor - OK"
  else
    echo "    [WARNING] Port $port: Dinlenmiyor"
    WARNINGS=$((WARNINGS + 1))
  fi
done

# HTTP response kontrolü
echo ""
echo "[4] HTTP Response Kontrolü"
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/)
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "301" ] || [ "$HTTP_CODE" = "302" ]; then
  echo "    HTTP response: $HTTP_CODE - OK"
else
  echo "    [ERROR] HTTP response: $HTTP_CODE - Beklenmeyen kod!"
  ERRORS=$((ERRORS + 1))
fi

# Log hata kontrolü
echo ""
echo "[5] Son 5 Dakika Log Kontrolü"
RECENT_ERRORS=$(find /usr/local/lsws/logs -name "*.log" -newer /tmp/.update_start 2>/dev/null | xargs grep -l "ERROR|CRITICAL" 2>/dev/null)
if [ -z "$RECENT_ERRORS" ]; then
  echo "    Log hataları: Yok - OK"
else
  echo "    [WARNING] Hata içeren loglar: $RECENT_ERRORS"
  WARNINGS=$((WARNINGS + 1))
fi

echo ""
echo "========================================="
echo "Sonuç: $ERRORS hata, $WARNINGS uyarı"
echo "========================================="

exit $ERRORS

Rollback Stratejisi

Her şey yolunda gitmeyebilir. Rollback planınız güncelleme planınız kadar önemli.

#!/bin/bash
# rollback_ols.sh

BACKUP_DIR="$1"

if [ -z "$BACKUP_DIR" ]; then
  echo "Kullanım: $0 /root/ols_backup/TARIH"
  echo "Mevcut yedekler:"
  ls /root/ols_backup/
  exit 1
fi

if [ ! -d "$BACKUP_DIR" ]; then
  echo "[ERROR] Yedek dizini bulunamadı: $BACKUP_DIR"
  exit 1
fi

echo "[WARN] Rollback işlemi başlıyor. Bu işlem OLS'yi yeniden başlatacak."
echo "Devam etmek için 'yes' yazın:"
read confirm

if [ "$confirm" != "yes" ]; then
  echo "İptal edildi."
  exit 0
fi

# OLS'yi durdur
echo "[INFO] OLS durduruluyor..."
/usr/local/lsws/bin/lswsctrl stop
sleep 3

# Konfigürasyonu geri yükle
echo "[INFO] Konfigürasyon geri yükleniyor..."
cp -r "$BACKUP_DIR/conf/"* /usr/local/lsws/conf/
cp -r "$BACKUP_DIR/admin_conf/"* /usr/local/lsws/admin/conf/

# Binary rollback (eğer binary yedeklediyseniz)
if [ -f "/usr/local/lsws/bin/lshttpd.bak" ]; then
  echo "[INFO] Binary geri yükleniyor..."
  cp /usr/local/lsws/bin/lshttpd.bak /usr/local/lsws/bin/lshttpd
fi

# OLS'yi başlat
echo "[INFO] OLS başlatılıyor..."
/usr/local/lsws/bin/lswsctrl start
sleep 5

# Hızlı kontrol
if curl -sf http://localhost/ > /dev/null; then
  echo "[SUCCESS] Rollback başarılı!"
else
  echo "[ERROR] Rollback sonrası sunucu yanıt vermiyor. Manuel müdahale gerekli!"
  exit 1
fi

Gerçek Dünya Senaryosu: E-ticaret Sitesi Güncellemesi

Bir e-ticaret projemizde yaşadığım gerçek senaryoyu paylaşayım. Site günde ortalama 50.000 tekil ziyaretçi alıyor ve özellikle akşam 20:00-23:00 arası yoğunluk zirvede. Güncellemeyi bu trafikte yapmak zorunda kaldık çünkü gece 3’te bile ciddi trafik vardı.

Kullandığımız yöntem:

  • HAProxy arkasında iki OLS sunucu
  • Blue-green geçişi ile önce green’i güncelledik
  • 15 dakika izledik, sorun olmadığını gördük
  • Blue’ya geçip aynı işlemi tekrarladık
  • Toplam süre: 45 dakika, downtime: 0 saniye

Ama bir sorunla karşılaştık: Güncelleme sonrası PHP-LSAPI bağlantıları hata vermeye başladı. Çünkü OLS yeni versiyonunda LSAPI worker timeout değerleri değişmişti. Bunu fark etmek için logları anlık izlememiz kritik oldu:

# PHP-LSAPI hatalarını anlık izlemek için
tail -f /usr/local/lsws/logs/error.log | grep -i "lsapi|php|worker"

Hızlı çözüm olarak LSAPI timeout değerini artırdık:

# Virtual host konfigürasyonunda LSAPI ayarı
# /usr/local/lsws/conf/vhosts/SITENAME/vhconf.conf

extprocessor phpLsapi {
  type                    lsapi
  address                 uds://tmp/lshttpd/SITENAME.sock
  maxConns                35
  env                     PHP_LSAPI_CHILDREN=35
  initTimeout             60        # 30'dan 60'a çıkardık
  retryTimeout            0
  respBuffer              0
}

Graceful restart sonrası sorun düzeldi.

OLS Admin Panel ile Canlı Konfigürasyon Güncellemesi

Bazı durumlarda binary güncelleme yapmadan sadece konfigürasyon değişikliği yapmanız gerekir. Bu durum zero downtime açısından çok daha kolaydır.

OLS Admin Panel (port 7080) üzerinden yapılan her değişiklik “Graceful Restart” butonu ile aktif edilebilir. Ama bunu komut satırından da yapabilirsiniz:

# Konfigürasyon değişikliğini doğrula
/usr/local/lsws/bin/lshttpd -t

# Doğrulama başarılıysa graceful restart
if /usr/local/lsws/bin/lshttpd -t 2>&1 | grep -q "configuration"; then
  echo "[INFO] Konfigürasyon geçerli, graceful restart uygulanıyor..."
  /usr/local/lsws/bin/lswsctrl graceful
  echo "[DONE] Graceful restart tamamlandı"
else
  echo "[ERROR] Konfigürasyon hatası! Restart uygulanmadı."
  /usr/local/lsws/bin/lshttpd -t
fi

Bu küçük kontrol, hatalı bir konfigürasyonla sunucuyu çökertmenizi önler. Production’da her zaman bu şekilde yapın.

Systemd ile Güncelleme Otomasyonu

Eğer OLS’yi systemd servis olarak çalıştırıyorsanız, güncelleme sürecini daha iyi yönetebilirsiniz:

# Systemd service dosyasını kontrol et
cat /etc/systemd/system/lsws.service

# Systemd üzerinden graceful reload
systemctl reload lsws

# Bu komut OLS'ye SIGUSR1 gönderir, tüm bağlantıları korur

Systemd timer ile otomatik güncelleme de kurabilirsiniz, ama production’da bunu önermiyorum. Manuel adım her zaman daha güvenlidir. Otomasyonu staging ortamı için saklayın.

Sık Karşılaşılan Sorunlar ve Çözümleri

Sorun: Graceful restart sonrası bazı worker’lar ölmüyor

Worker process’lerin uzun süreli bir bağlantıyı bekliyor olması bu soruna yol açar.

# Asılı kalan process'leri bul
ps aux | grep lshttpd | awk '{print $1, $8, $11}' | grep -v "root|grep"

# Bağlantı durumlarını kontrol et
lsof -p PID_NUMARASI | grep ESTABLISHED

Sorun: Güncelleme sonrası cache tutarsızlıkları

OLS’nin built-in cache’i güncelleme sonrası stale data servis edebilir.

# Cache dizinini temizle
rm -rf /tmp/lshttpd/cache/*

# Ya da admin panel üzerinden cache flush
curl -u admin:SIFRE "https://localhost:7080/index.php?m=flushrewrite"

Sorun: SSL sertifikaları güncelleme sonrası yüklenmedi

# SSL konfigürasyonunu doğrula
openssl s_client -connect localhost:443 -brief 2>/dev/null | head -5

# OLS SSL modülünü yeniden yükle
kill -HUP $(cat /tmp/lshttpd.pid)

Sonuç

OpenLiteSpeed ile zero downtime güncelleme yapmak, doğru adımları takip ettiğinizde sandığınızdan çok daha az stresli bir süreç. Kritik noktalara bakacak olursak:

  • Güncelleme öncesi mutlaka yedek alın ve mevcut durumu belgeleyin
  • Graceful restart ile standart restart’ı karıştırmayın, kill -USR1 veya lswsctrl graceful kullanın
  • Güncelleme sırasında response time izleme her zaman açık olsun
  • Rollback scriptiniz her zaman hazır ve test edilmiş olsun
  • Konfigürasyon değişikliklerini her zaman -t parametresiyle doğrulayın
  • Yüksek trafikli sistemlerde blue-green deployment düşünün

En önemli şey şu: Bu süreçleri önce staging ortamında deneyin. Production’da ilk kez deneme lüksünüz yok. Staging’de onlarca kez çalıştırdığınız bir script production’da da çalışır. Çalışmayan bir script ise sizi en azından alışkın bir ortamda karşılar.

OLS, zero downtime konusunda gerçekten iyi bir iş çıkarıyor. Mimarisi bu tür operasyonlar için uygun tasarlanmış. Siz de doğru araçları kullandığınızda, kullanıcılarınız güncelleme yaptığınızı hiç fark etmez. Ve bir sistem yöneticisi için bu, en büyük övgüdür.

Yorum yapın