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
- istekten itibaren 429 Too Many Requests alacaksınız. Rate limit header’larını da response’da görebilirsiniz:
X-RateLimit-Remaining-MinuteveX-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: mobileheader’ı 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.
