İçeriğe atla

Traefik vs Nginx: nginx Kullanıcıları İçin Giriş

nginx bilen geliştiriciler için pratik Traefik rehberi: temel kavramlar, Docker kurulum örnekleri ve nginx'e kıyasla Traefik'i ne zaman seçeceğin.

Ayhan Sipahi Ayhan Sipahi

Traefik, çalışırken değişen altyapılar için tasarlanmış bir reverse proxy ve load balancer. Container orchestrator’ünü izler ve routing kurallarını kendisi günceller; nginx ise config dosyasını düzenleyip reload etmeni bekler. Seçimin büyük kısmını bu tek fark belirliyor. Servislerin kendi takvimine göre gelip giden container’larsa, o kenara Traefik koy; topolojinin sabit olduğu yerde nginx’te kal.

Takas şu: operasyonel kolaylığa karşılık daha ince bir veri yolu. Traefik düzenle-test-et-reload döngüsünü ortadan kaldırıyor, bedelini de daha büyük bir runtime ayak izi ve daha az olgun bir rewrite/caching motoruyla ödüyor. Sabit bir upstream listesi statik dosya sunuyorsa bu kötü bir takas. Günde birkaç kez yeniden deploy edilen bir container filosu içinse kolay bir takas.

Traefik Nedir?#

Traefik cloud-native bir edge router. Başlangıçta statik bir konfigürasyon dosyası okumak yerine bir provider’a (Docker, Kubernetes, Consul) abone olur ve provider her değişiklik bildirdiğinde routing tablosunu yeniden kurar. Konfigürasyon ortadan kalkmıyor; servisin yanına taşınıyor, container label’ı veya Ingress annotation’ı olarak.

Traefik, servislerin sık sık gelip gittiği ortamlarda parlıyor: microservice deployment’ları, development ortamları veya developer’ların kendi servislerini deploy ettiği platformlar. Hedeflediği sorun dar kapsamlı: dinamik konfigürasyon yönetimi.

Traefik’in Çözdüğü Temel Problem#

Sık karşılaşılan bir senaryo: Docker Swarm veya Kubernetes cluster’ına yeni bir microservice deploy ediyorsun. nginx ile yapman gerekenler:

  1. nginx konfigürasyon dosyasını editlemek
  2. Konfigürasyonu test etmek
  3. nginx’i reload etmek
  4. Bir şey bozulmadığını umut etmek

Traefik ile Docker container’ına label’lar ekliyorsun veya Kubernetes service’ine annotation’lar koyuyorsun, routing kuralları otomatik güncelleniyor. Sunuculara SSH yapman, konfigürasyon dosyası editlemen, servis reload’u gerekmiyor.

nginx

Traefik

Yeni Servis Deploy

Reverse Proxy Tipi

Config Dosyasini Duzenle

Config Test Et

nginx Reload

Servis Hazir

Otomatik Kesif

Temel Kavramlar#

1. Provider’lar#

Provider’lar Traefik’in servisleri keşfetme yöntemi. Yaygın provider’lar:

  • Docker: Docker container’larını ve label’larını izler
  • Kubernetes: Ingress/IngressRoute resource’larını okur
  • File: Geleneksel konfigürasyon dosyaları (evet, hala statik config kullanabilirsin)
  • Consul, Etcd: Service discovery backend’leri

Provider abstraction güçlü bir kavram: development’ta Docker label’ları ile başlayıp production’da Kubernetes annotation’larına geçebilirsin, aynı mental modeli kullanarak.

2. Entrypoint’ler#

Entrypoint’ler Traefik’in hangi portları dinlediğini tanımlar. Tipik kurulum:

# Port 80'de HTTP entrypoint
--entrypoints.web.address=:80

# Port 443'te HTTPS entrypoint
--entrypoints.websecure.address=:443

3. Router’lar#

Router’lar entrypoint’leri kurallara göre servislerle bağlar. Kurallar şunlara göre eşleşebilir:

  • Host header’ları: Host(`api.example.com`)
  • Path prefix’leri: PathPrefix(`/api`)
  • Header’lar: Headers(`X-Custom-Header`, `value`)
  • Birden fazla koşul: Host(`api.example.com`) && PathPrefix(`/v1`)

4. Middleware’ler#

Middleware’ler request/response’ları dönüştürür. Traefik’in gücünün ortaya çıktığı yer burası:

  • HTTP’yi HTTPS’e redirect et
  • Header ekle/çıkar
  • Rate limiting
  • Basic authentication
  • Circuit breaker’lar
  • Compression

Pratik Kurulum Örneği#

İki servisin önünde Traefik duran bir Docker Compose kurulumu:

version: '3.8'

services:
  traefik:
    image: traefik:v2.10
    command:
      # Docker provider'ı etkinleştir
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      # Entrypoint'leri tanımla
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      # Dashboard'u etkinleştir (production'da kaldır)
      - "--api.dashboard=true"
      # Access log'ları etkinleştir
      - "--accesslog=true"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # Dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    labels:
      # Dashboard için Traefik'i etkinleştir
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.localhost`)"
      - "traefik.http.routers.dashboard.service=api@internal"

  whoami:
    image: traefik/whoami
    labels:
      # Bu container için Traefik'i etkinleştir
      - "traefik.enable=true"
      # Routing kuralını tanımla
      - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
      # Entrypoint'i belirt
      - "traefik.http.routers.whoami.entrypoints=web"

  api:
    image: nginx:alpine
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.localhost`)"
      - "traefik.http.routers.api.entrypoints=web"
      # Path stripping için middleware ekle
      - "traefik.http.routers.api.middlewares=api-stripprefix"
      - "traefik.http.middlewares.api-stripprefix.stripprefix.prefixes=/api"

Bunu docker-compose up -d ile başlat ve şunlara erişebilirsin:

  • http://whoami.localhost - whoami servisi
  • http://api.localhost - nginx servisi
  • http://traefik.localhost - Traefik dashboard

Eşdeğer nginx Konfigürasyonu#

Karşılaştırma için, aynı kurulum için nginx’te ihtiyacın olanlar:

# /etc/nginx/conf.d/services.conf

# Upstream tanımları
upstream whoami_backend {
    server whoami:80;
}

upstream api_backend {
    server api:80;
}

# whoami servisi
server {
    listen 80;
    server_name whoami.localhost;

    location / {
        proxy_pass http://whoami_backend;
        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;
    }
}

# API servisi
server {
    listen 80;
    server_name api.localhost;

    location /api {
        rewrite ^/api/(.*)$ /$1 break;
        proxy_pass http://api_backend;
        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;
    }
}

nginx config’i olduğu gibi gayet iyi. Maliyet bir sonraki serviste ortaya çıkıyor: dosyayı düzenle, test et, reload et.

Middleware Kullanımı#

İşte HTTPS redirect ve rate limiting kullanan middleware’ler ile pratik bir örnek:

services:
  traefik:
    image: traefik:v2.10
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      # Global HTTP to HTTPS redirect
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  api:
    image: your-api:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.example.com`)"
      - "traefik.http.routers.api.entrypoints=websecure"

      # Rate limiting middleware'i uygula
      - "traefik.http.routers.api.middlewares=api-ratelimit,api-auth"

      # Rate limit: saniyede ortalama 100 request, 50 burst
      - "traefik.http.middlewares.api-ratelimit.ratelimit.average=100"
      - "traefik.http.middlewares.api-ratelimit.ratelimit.burst=50"

      # Basic authentication
      - "traefik.http.middlewares.api-auth.basicauth.users=admin:$$apr1$$hash..."

Aynı rate limiting’i nginx’te uygulamak ngx_http_limit_req_module (iyi çalışır) veya harici araçlar gerektirir. Her iki yaklaşım da işe yarar; Traefik versiyonu sadece farklı konfigure edilir.

İstek Akışı Mimarisi#

Request’lerin Traefik’ten nasıl geçtiğine geleneksel kurulumla karşılaştırmalı bakalım:

Geleneksel nginx

Reload gerektirir

Client Request

nginx

Statik Config Dosyasi

Upstream Backend

Manuel Config Update

Traefik Mimarisi

Otomatik kesif

Client Request

Traefik Entrypoint

Router Eslestirme

Middleware Chain

Service Backend

Provider: Docker/K8s

nginx Yerine Traefik Ne Zaman Seçilmeli#

Burada mesele hangisinin daha iyi olduğu değil, hangisinin kuruluma oturduğu.

Traefik’i Şu Durumlarda Seç#

  1. Dinamik altyapı: Servisler sık deploy edilip kaldırılıyor
  2. Container-native: Docker, Kubernetes veya benzeri orchestrator’lar kullanıyorsun
  3. Developer self-service: Takımlar kendi servislerini label/annotation’larla deploy ediyor
  4. Otomatik HTTPS: Let’s Encrypt entegrasyonu built-in ve çok kolay
  5. Microservice’ler: Bağımsız değişen bir sürü küçük servis

Kazanç proxy’nin dışında görünür. Routing değişikliği ortak bir dosyanın düzenlenmesi olmaktan çıkıp servisin kendi deploy manifest’inin parçası olur; böylece kodla aynı review ve rollback yolunu izler.

nginx’i Şu Durumlarda Seç#

  1. Statik altyapı: Servisler nadiren değişiyor
  2. Kompleks URL rewriting: nginx’in rewrite engine’i daha olgun
  3. Maksimum performans: nginx’in latency’si daha düşük (fark küçük olsa da)
  4. Gelişmiş caching: nginx’in caching yetenekleri daha sofistike
  5. Statik dosya sunma: nginx bu işte üstün

nginx’in olgunluğunun somutlaştığı yer burası: response caching için proxy_cache, statik asset’ler için sendfile ve open_file_cache, arkasında yılların uç durumları biriken bir rewrite motoru. Traefik’te yerleşik bir response cache veya statik dosya sunucusu yok; path rewrite middleware’leri de daha dar bir alanı kapsıyor.

Yaygın Pattern’ler ve Gotcha’lar#

Pattern 1: Servis Başına Birden Fazla Router#

Aynı servise farklı path’leri farklı middleware’lerle yönlendirebilirsin:

labels:
  - "traefik.enable=true"

  # Public API - rate limited
  - "traefik.http.routers.api-public.rule=Host(`api.example.com`) && PathPrefix(`/public`)"
  - "traefik.http.routers.api-public.middlewares=rate-limit"

  # Internal API - rate limit yok, authentication gerekli
  - "traefik.http.routers.api-internal.rule=Host(`api.example.com`) && PathPrefix(`/internal`)"
  - "traefik.http.routers.api-internal.middlewares=auth"

Pattern 2: Weighted Load Balancing#

# Servis A - trafiğin %80'i
labels:
  - "traefik.http.services.myapp.loadbalancer.server.port=8080"
  - "traefik.http.services.myapp.loadbalancer.sticky.cookie=true"

# Servis B - trafiğin %20'si (canary deployment)
labels:
  - "traefik.http.services.myapp-canary.loadbalancer.server.port=8080"

# Weighted load balancing'li router
labels:
  - "traefik.http.routers.myapp.service=myapp-weighted"
  - "traefik.http.services.myapp-weighted.weighted.services[0].name=myapp"
  - "traefik.http.services.myapp-weighted.weighted.services[0].weight=80"
  - "traefik.http.services.myapp-weighted.weighted.services[1].name=myapp-canary"
  - "traefik.http.services.myapp-weighted.weighted.services[1].weight=20"

Gotcha 1: Docker Socket Erişimi#

Traefik’in Docker socket’ine read erişimi lazım. Production’da, maruz kalma riskini sınırlamak için tecnativa/docker-socket-proxy gibi bir Docker socket proxy kullanmayı düşün.

Gotcha 2: Label Syntax#

Label’lar string olduğu için kompleks değerler düzgün escape edilmeli:

# Yanlış - bozulur
- "traefik.http.routers.api.rule=Host(`api.example.com`) && PathPrefix(`/v1`)"

# Doğru - compose versiyonuna göre backtick'leri escape et
- 'traefik.http.routers.api.rule=Host(`api.example.com`) && PathPrefix(`/v1`)'

Gotcha 3: Default Ayarlar#

Varsayılan olarak Traefik TÜM container’ları expose eder. exposedbydefault=false yap ve servisleri açıkça etkinleştir:

command:
  - "--providers.docker.exposedbydefault=false"

Kullanım Senaryoları#

Senaryo 1: Development Ortamı#

Tek bir hostname arkasında çok servisli bir local kurulum:

version: '3.8'

services:
  traefik:
    image: traefik:v2.10
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  frontend:
    image: node:18
    working_dir: /app
    command: npm run dev
    volumes:
      - ./frontend:/app
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`app.local`)"
      - "traefik.http.services.frontend.loadbalancer.server.port=3000"

  backend:
    image: node:18
    working_dir: /app
    command: npm start
    volumes:
      - ./backend:/app
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.backend.rule=Host(`app.local`) && PathPrefix(`/api`)"
      - "traefik.http.services.backend.loadbalancer.server.port=4000"

/etc/hosts’a 127.0.0.1 app.local ekle, birleşik bir local development URL’ine sahip olursun.

Senaryo 2: Let’s Encrypt ile Otomatik HTTPS#

services:
  traefik:
    image: traefik:v2.10
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"

      # Let's Encrypt konfigürasyonu
      - "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"

      # HTTP'den HTTPS'e redirect
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt

  app:
    image: your-app:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`example.com`)"
      - "traefik.http.routers.app.entrypoints=websecure"
      - "traefik.http.routers.app.tls.certresolver=letsencrypt"

Traefik sertifika alımını, yenilemeyi ve sunmayı otomatik halleder. nginx ile genelde certbot’u cron job’larla ve nginx’i reload eden hook’larla kullanırsın.

Performans Farkı#

Her iki proxy de çoğu yükte darboğaz olmayacak kadar hızlı. Ayrışma daha çok yapısal tarafta:

  • Latency: nginx istek başına daha az ek yük getirir; fark tek bir veritabanı çağrısının arkasında kaybolur.
  • Throughput: Sentetik benchmark’larda nginx önde; kendi payload boyutlarınla ölçmeden bunu karar sayma.
  • Resource kullanımı: Traefik Go runtime’ında çalışır ve orchestrator’ün canlı görüntüsünü tutar; boştaki memory ayak izi ikisinin yüksek olanı.
  • CPU: Normal yükte benzer; nginx ekstrem trafikte öne geçer.

Çoğu uygulamada otomatik keşfin operasyonel kazancı bu farktan ağır basar. Ultra yüksek trafikli statik content delivery içinse belirleyici olan nginx’in avantajı.

Geçiş Stratejisi#

nginx’ten Traefik’e geçiyorsan, riski düşük bir sıra:

  1. Yan yana başla: nginx ve Traefik’i birlikte çalıştır
  2. Aşama aşama taşı: Servisleri teker teker geçir
  3. File provider kullan: Traefik statik config dosyalarını okuyabilir (nginx’e benzer)
  4. İyice test et: Özellikle middleware chain’leri ve routing kurallarını
  5. Metrikleri izle: Latency, hata oranları, resource kullanımını karşılaştır

Her şeyi migrate etmen gerekmiyor. Bazı takımlar statik content ve API’ler için nginx kullanırken Traefik dinamik microservice’leri hallediyor.

Sonuç#

Varsayılan seçim, topoloji hareket ettiği sürece geçerli: kendi takvimine göre yeniden deploy edilen container’lar, proxy ticket’ı açmadan yayına çıkan takımlar, elle yenilemek istemediğin sertifikalar. Upstream listesi sabitse ve yük statik dosya ya da yoğun caching ise tersini seç; nginx’in rewrite motorunun, response cache’inin ve dosya sunumunun Traefik’te yerleşik karşılığı yok. İkisini birlikte çalıştırmak olağan bir sonuç: statik kenarda nginx, container’ların önünde Traefik.

Önce yukarıdaki temel Compose dosyasıyla başla; routing oturduktan sonra middleware’leri ve Let’s Encrypt’i ekle.

Kaynaklar#

İlgili yazılar