API Gateway Nedir: Merkezi Yönetim ve Güvenlik

Mikroservis mimarisine geçiş yaptığınızda, onlarca farklı servisi yönetmek başlı başına bir kabus haline gelebilir. Her servis kendi authentication mekanizmasını mı yönetsin? Rate limiting her serviste ayrı ayrı mı implemente edilsin? Logging için her ekip kendi çözümünü mü bulsun? İşte tam bu noktada API Gateway devreye giriyor ve hayatınızı kurtarıyor.

API Gateway Nedir?

API Gateway, tüm istemcilerin tek bir giriş noktasından backend servislerinize erişmesini sağlayan bir ara katmandır. Düşünün ki büyük bir binanın resepsiyonusunuz. Her ziyaretçi direkt olarak ilgili departmana gitmiyor, önce sizden geçiyor. Siz de kimin nereye gidebileceğini, ne kadar süre kalabileceğini ve hangi erişim yetkilerine sahip olduğunu kontrol ediyorsunuz.

Teknik olarak konuşursak, API Gateway şunları merkezi olarak yönetir:

  • Authentication ve Authorization: Kim bağlanıyor, ne yapabilir?
  • Rate Limiting: Kaç istek gönderilebilir?
  • Load Balancing: Trafik nasıl dağıtılır?
  • SSL Termination: TLS/SSL işlemleri nerede sonlandırılır?
  • Request/Response Transformation: İstekler ve yanıtlar nasıl dönüştürülür?
  • Logging ve Monitoring: Ne oluyor, ne zaman oluyor?
  • Caching: Hangi yanıtlar önbelleğe alınır?

Neden API Gateway Kullanmalısınız?

Gerçek dünya senaryosunu ele alalım. Bir e-ticaret platformu düşünün: User Service, Product Service, Order Service, Payment Service ve Notification Service var. Bu beş servisin her biri ayrı bir ekip tarafından geliştiriliyor.

Bu servislere direkt erişim açarsanız karşılaşacağınız sorunlar şunlar olacak:

  • Her servis kendi JWT validation mantığını yazmak zorunda
  • Bir kullanıcı saniyede 1000 istek atarsa hangi servis bunu engelleyecek?
  • Production’da bir sorun çıktığında logları beş farklı yerden toplamak zorunda kalıyorsunuz
  • Her serviste ayrı ayrı CORS konfigürasyonu yapmak gerekiyor
  • Bir servise yapılan DDoS saldırısında tüm sistem çöküyor

API Gateway bu sorunları tek bir merkezden çözüyor.

Popüler API Gateway Çözümleri

Piyasada birçok seçenek mevcut. Açık kaynak tarafında Kong, Traefik, KrakenD ve APISIX öne çıkarken, cloud tarafında AWS API Gateway, Azure API Management ve Google Cloud Endpoints bulunuyor. Self-hosted kurumsal çözümler arasında ise Nginx Plus ve HAProxy Enterprise var.

Bu yazıda ağırlıklı olarak Kong ve Nginx üzerinden örnekler vereceğiz, çünkü bunlar production ortamlarında en çok tercih edilen çözümler.

Kong ile API Gateway Kurulumu

Kong’u Docker Compose ile ayağa kaldıralım. Bu en hızlı başlangıç yöntemi.

# docker-compose.yml oluşturun
cat > docker-compose.yml << 'EOF'
version: '3.8'

services:
  kong-database:
    image: postgres:13
    environment:
      POSTGRES_USER: kong
      POSTGRES_DB: kong
      POSTGRES_PASSWORD: kongpass
    volumes:
      - kong_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "kong"]
      interval: 5s
      timeout: 5s
      retries: 5

  kong-migration:
    image: kong:3.4
    command: kong migrations bootstrap
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: kong-database
      KONG_PG_USER: kong
      KONG_PG_PASSWORD: kongpass
      KONG_PG_DATABASE: kong
    depends_on:
      kong-database:
        condition: service_healthy

  kong:
    image: kong:3.4
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: kong-database
      KONG_PG_USER: kong
      KONG_PG_PASSWORD: kongpass
      KONG_PG_DATABASE: kong
      KONG_PROXY_ACCESS_LOG: /dev/stdout
      KONG_ADMIN_ACCESS_LOG: /dev/stdout
      KONG_PROXY_ERROR_LOG: /dev/stderr
      KONG_ADMIN_ERROR_LOG: /dev/stderr
      KONG_ADMIN_LISTEN: 0.0.0.0:8001
    ports:
      - "8000:8000"   # HTTP proxy
      - "8443:8443"   # HTTPS proxy
      - "8001:8001"   # Admin API
    depends_on:
      - kong-migration

volumes:
  kong_data:
EOF

docker-compose up -d

Kong ayağa kalktıktan sonra Admin API üzerinden konfigürasyon yapabiliriz.

Servis ve Route Tanımlama

Kong’da her şey Service ve Route kavramı üzerine kurulu. Service, backend servisinizi temsil eder. Route ise hangi isteklerin o servise yönlendirileceğini belirler.

# User Service tanımlama
curl -i -X POST http://localhost:8001/services 
  --data name=user-service 
  --data url=http://user-service:3000

# User Service için route ekleme
curl -i -X POST http://localhost:8001/services/user-service/routes 
  --data "paths[]=/api/users" 
  --data "methods[]=GET" 
  --data "methods[]=POST" 
  --data strip_path=false

# Product Service tanımlama
curl -i -X POST http://localhost:8001/services 
  --data name=product-service 
  --data url=http://product-service:3001

# Product Service için route ekleme
curl -i -X POST http://localhost:8001/services/product-service/routes 
  --data "paths[]=/api/products" 
  --data "methods[]=GET" 
  --data "methods[]=POST" 
  --data "methods[]=PUT" 
  --data "methods[]=DELETE"

# Servisleri listeleyelim
curl http://localhost:8001/services | python3 -m json.tool

Rate Limiting Konfigürasyonu

Rate limiting, API güvenliğinin en temel bileşenlerinden biri. Kong’da bu özelliği plugin olarak ekliyoruz.

# Global rate limiting - tüm servislere uygula
curl -i -X POST http://localhost:8001/plugins 
  --data name=rate-limiting 
  --data config.minute=100 
  --data config.hour=1000 
  --data config.policy=local

# Sadece user-service için rate limiting
curl -i -X POST http://localhost:8001/services/user-service/plugins 
  --data name=rate-limiting 
  --data config.minute=30 
  --data config.hour=200 
  --data config.policy=redis 
  --data config.redis_host=redis 
  --data config.redis_port=6379

# Rate limit durumunu test et
for i in {1..35}; do
  RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/api/users)
  echo "Request $i: HTTP $RESPONSE"
  sleep 0.1
done
  1. istekten itibaren 429 Too Many Requests alacaksınız. Rate limit header’larını da response’da görebilirsiniz: X-RateLimit-Remaining-Minute ve X-RateLimit-Limit-Minute.

JWT Authentication Entegrasyonu

Merkezi authentication, API Gateway’in en değerli özelliklerinden biri. Her servisin kendi token doğrulamasını yapması yerine, Gateway bu işi üstleniyor.

# JWT plugin'i etkinleştir
curl -i -X POST http://localhost:8001/services/user-service/plugins 
  --data name=jwt

# Tüm servisler için de ekleyebilirsiniz
curl -i -X POST http://localhost:8001/plugins 
  --data name=jwt 
  --data config.claims_to_verify=exp 
  --data config.key_claim_name=iss

# Consumer (kullanıcı) oluştur
curl -i -X POST http://localhost:8001/consumers 
  --data username=frontend-app 
  --data custom_id=frontend-001

# Consumer için JWT credentials oluştur
curl -i -X POST http://localhost:8001/consumers/frontend-app/jwt 
  --data algorithm=HS256

# Çıktıdan key ve secret değerlerini alın
# Örnek çıktı:
# {"key":"abc123...","secret":"xyz789...","algorithm":"HS256"}

Token oluşturmak için küçük bir Python scripti yazalım:

#!/usr/bin/env python3
import jwt
import time
import json

# Kong'dan aldığınız değerleri buraya yazın
KONG_KEY = "buraya_kong_key_gelecek"
KONG_SECRET = "buraya_kong_secret_gelecek"

payload = {
    "iss": KONG_KEY,
    "exp": int(time.time()) + 3600,  # 1 saat geçerli
    "user_id": 12345,
    "username": "ahmet.yilmaz",
    "roles": ["user", "editor"]
}

token = jwt.encode(payload, KONG_SECRET, algorithm="HS256")
print(f"Bearer Token: {token}")

# Token'i test et
import subprocess
result = subprocess.run([
    "curl", "-s", "-H", f"Authorization: Bearer {token}",
    "http://localhost:8000/api/users"
], capture_output=True, text=True)
print(f"Response: {result.stdout}")

Nginx ile API Gateway Konfigürasyonu

Kong’un fazla ağır geldiği senaryolarda Nginx ile de temel bir API Gateway kurabilirsiniz. Özellikle daha az servisiniz varsa bu yaklaşım çok daha hafif çalışır.

# /etc/nginx/conf.d/api-gateway.conf

# Rate limiting zone tanımla
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $http_x_api_key zone=apikey_limit:10m rate=100r/m;

# Upstream tanımları
upstream user_service {
    least_conn;
    server user-service-1:3000 weight=3;
    server user-service-2:3000 weight=3;
    server user-service-3:3000 weight=1 backup;
    keepalive 32;
}

upstream product_service {
    server product-service-1:3001;
    server product-service-2:3001;
    keepalive 16;
}

# API Gateway server bloğu
server {
    listen 443 ssl http2;
    server_name api.sirketiniz.com;

    ssl_certificate /etc/ssl/certs/api.crt;
    ssl_certificate_key /etc/ssl/private/api.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
    ssl_prefer_server_ciphers off;

    # Güvenlik header'ları
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

    # User Service rotaları
    location /api/v1/users {
        limit_req zone=api_limit burst=20 nodelay;

        # JWT doğrulama için auth endpoint'e sub-request
        auth_request /auth/validate;
        auth_request_set $user_id $upstream_http_x_user_id;
        proxy_set_header X-User-ID $user_id;

        proxy_pass http://user_service;
        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;
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
    }

    # Product Service rotaları
    location /api/v1/products {
        limit_req zone=api_limit burst=50 nodelay;

        # Public endpoint - auth gerekmez ama rate limit var
        proxy_pass http://product_service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_cache api_cache;
        proxy_cache_valid 200 60s;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        add_header X-Cache-Status $upstream_cache_status;
    }

    # Auth validation endpoint
    location = /auth/validate {
        internal;
        proxy_pass http://auth-service:4000/validate;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
        proxy_set_header Authorization $http_authorization;
    }

    # Health check endpoint
    location /health {
        access_log off;
        return 200 '{"status":"healthy","timestamp":"$time_iso8601"}';
        add_header Content-Type application/json;
    }
}

Merkezi Logging ve Monitoring

API Gateway’in en büyük avantajlarından biri, tüm trafiği tek bir noktadan loglayabilmek. Kong’da bunu birkaç farklı şekilde yapabilirsiniz.

# Kong'a HTTP Log plugin ekle - Elasticsearch'e gönder
curl -i -X POST http://localhost:8001/plugins 
  --data name=http-log 
  --data config.http_endpoint=http://logstash:5044 
  --data config.method=POST 
  --data config.timeout=1000 
  --data config.keepalive=60000 
  --data config.content_type=application/json

# Prometheus metrics için plugin ekle
curl -i -X POST http://localhost:8001/plugins 
  --data name=prometheus 
  --data config.per_consumer=true

# Prometheus metrics'i çek
curl http://localhost:8001/metrics | grep -E "kong_http_requests|kong_latency"

# Grafana dashboard için gerekli metrikleri kontrol et
curl -s http://localhost:8001/metrics | grep kong_http_requests_total

Nginx tarafında ise log formatını JSON olarak ayarlayıp Filebeat ile Elasticsearch’e göndermek standart yaklaşım:

# /etc/nginx/nginx.conf - JSON log format
log_format json_combined escape=json '{'
  '"time":"$time_iso8601",'
  '"remote_addr":"$remote_addr",'
  '"method":"$request_method",'
  '"uri":"$uri",'
  '"status":$status,'
  '"bytes_sent":$bytes_sent,'
  '"request_time":$request_time,'
  '"upstream_response_time":"$upstream_response_time",'
  '"upstream_addr":"$upstream_addr",'
  '"http_referrer":"$http_referer",'
  '"http_user_agent":"$http_user_agent",'
  '"request_id":"$request_id"'
'}';

access_log /var/log/nginx/api-gateway-access.log json_combined;
error_log /var/log/nginx/api-gateway-error.log warn;

# Log rotation için logrotate konfigürasyonu
cat > /etc/logrotate.d/nginx-api-gateway << 'EOF'
/var/log/nginx/api-gateway-*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    sharedscripts
    postrotate
        nginx -s reopen
    endscript
}
EOF

Canary Deployment ile Güvenli Sürüm Geçişleri

API Gateway’i doğru kullanırsanız yeni sürümleri güvenle deploy edebilirsiniz. Kong’da bunu traffic splitting ile yapıyoruz.

# Mevcut product service (v1) zaten tanımlı
# Yeni versiyonu (v2) tanımlayalım
curl -i -X POST http://localhost:8001/services 
  --data name=product-service-v2 
  --data url=http://product-service-v2:3002

# Canary route - trafiğin %10'unu v2'ye gönder
curl -i -X POST http://localhost:8001/services/product-service-v2/routes 
  --data "paths[]=/api/v1/products" 
  --data name=product-canary

# Traffic splitting için Canary plugin ekle
curl -i -X POST http://localhost:8001/routes/product-canary/plugins 
  --data name=canary 
  --data config.percentage=10 
  --data config.upstream_host=product-service-v2 
  --data config.upstream_port=3002

# Canary deployment izleme scripti
#!/bin/bash
while true; do
  V1_COUNT=$(curl -s http://localhost:8001/metrics | grep 'service="product-service"' | awk '{print $2}')
  V2_COUNT=$(curl -s http://localhost:8001/metrics | grep 'service="product-service-v2"' | awk '{print $2}')
  echo "$(date): V1=$V1_COUNT, V2=$V2_COUNT"
  sleep 10
done

Gerçek Dünya Senaryosu: E-ticaret Platformu

Başta bahsettiğimiz e-ticaret senaryosunu somutlaştıralım. Bir ödeme işlemi sırasında API Gateway nasıl devreye giriyor?

Kullanıcı checkout sayfasında “Ödeme Yap” butonuna bastığında şu akış gerçekleşiyor:

  • İstek API Gateway’e ulaşıyor: POST /api/v1/orders/checkout
  • Rate limiting kontrolü: Bu kullanıcı son 1 dakikada kaç istek attı?
  • JWT doğrulama: Token geçerli mi, süresi dolmamış mı?
  • Authorization kontrolü: Bu kullanıcının checkout yetkisi var mı?
  • Request transformation: Mobile app’ten gelen isteğe X-Client-Type: mobile header’ı ekleniyor
  • Order Service’e yönlendirme: İstek backend’e iletiliyor
  • Response logging: Tüm detaylar merkezi log sistemine yazılıyor
  • Response transformation: Hassas ödeme bilgileri response’dan temizleniyor

Tüm bu adımlar backend servisler hiçbir şeyden haberdar olmadan, saniyelerin altında gerçekleşiyor.

# Bu akışı simüle eden test scripti
#!/bin/bash

BASE_URL="http://localhost:8000"
TOKEN="eyJhbGciOiJIUzI1NiJ9..."

echo "=== API Gateway E-ticaret Akış Testi ==="

# 1. Ürün listesi - public endpoint
echo -n "1. Ürün listesi: "
curl -s -o /dev/null -w "HTTP %{http_code} - %{time_total}sn" 
  "$BASE_URL/api/v1/products"

# 2. Sepet görüntüle - auth gerekli
echo -n "2. Sepet görüntüle: "
curl -s -o /dev/null -w "HTTP %{http_code} - %{time_total}sn" 
  -H "Authorization: Bearer $TOKEN" 
  "$BASE_URL/api/v1/cart"

# 3. Checkout - auth + rate limit
echo -n "3. Checkout isteği: "
curl -s -o /dev/null -w "HTTP %{http_code} - %{time_total}sn" 
  -H "Authorization: Bearer $TOKEN" 
  -H "Content-Type: application/json" 
  -d '{"cart_id":"cart-123","payment_method":"credit_card"}' 
  -X POST "$BASE_URL/api/v1/orders/checkout"

echo "=== Test tamamlandı ==="

Sık Yapılan Hatalar

Yıllar içinde gördüğüm en yaygın hataları paylaşayım:

  • Her şeyi Gateway’e yüklemek: API Gateway bir business logic katmanı değil. Karmaşık iş mantığını buraya koymayın.
  • Single point of failure: Gateway’i redundant kurmadan production’a almak. Her zaman en az iki instance çalıştırın.
  • Timeout değerlerini ayarlamamak: Default timeout değerleri genellikle production için uygun değil. Her servis için ayrı ayrı ayarlayın.
  • Health check eklememeek: Gateway’in backend servislerin sağlığını bilmesi şart. Yoksa çökmüş bir servise trafik göndermeye devam eder.
  • Config’i versiyon kontrolüne almamak: Gateway konfigürasyonunuz da kod. Git’e ekleyin.

Sonuç

API Gateway, modern backend mimarisinin vazgeçilmez bir bileşeni haline geldi. Mikroservis ya da monolith fark etmeksizin, dışarıya açık bir API’niz varsa bu trafiği merkezi olarak yönetmek hem güvenlik hem de operasyonel verimlilik açısından büyük fayda sağlıyor.

Başlangıç için şu adımları öneririm: Önce Nginx ile basit bir reverse proxy kurarak rate limiting ve SSL termination ekleyin. Servis sayınız arttıkça Kong veya benzeri bir dedicated Gateway çözümüne geçin. Monitoring’i en baştan kurun, çünkü sonradan eklemek çok daha zor oluyor. Authentication mantığını mutlaka Gateway’e taşıyın, backend servisleriniz sadece business logic ile ilgilensin.

API Gateway’i doğru kurduğunuzda, yeni bir servis eklemek ya da güvenlik güncellemesi yapmak tek bir yerden yapılan bir konfigürasyon değişikliğine indirgenebiliyor. Bu da hem ekip verimliliğini artırıyor hem de hata riskini dramatik şekilde azaltıyor.

Bir yanıt yazın

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