Kubernetes’te HTTP Trafik Yönetimi: Ingress ve Ingress Controller

Kubernetes cluster’ınızda onlarca servis çalıştırıyorsunuz, her birinin dışarıya açılması gerekiyor ve her birine ayrı bir LoadBalancer IP’si tahsis etmek hem maliyetli hem de yönetimi zorlaştıran bir hal alıyor. İşte tam bu noktada Ingress ve Ingress Controller devreye giriyor. Bu yazıda HTTP trafik yönetiminin Kubernetes dünyasındaki karşılığını, nasıl çalıştığını ve gerçek dünya senaryolarıyla nasıl yapılandırıldığını detaylıca ele alacağız.

Ingress Nedir?

Kubernetes’te dışarıya servis açmanın birkaç yolu var: NodePort, LoadBalancer ve ClusterIP bunların başında geliyor. Ancak production ortamlarında bu yöntemlerin her birinin ciddi kısıtlamaları var. LoadBalancer her servis için ayrı bir cloud load balancer oluşturuyor ve bu maliyeti katladıkça katlıyor. NodePort ise güvenlik ve port yönetimi açısından kabus olabiliyor.

Ingress, Kubernetes’te HTTP ve HTTPS trafiğini cluster içindeki servislere yönlendiren bir API objesidir. Bir nevi “akıllı proxy” veya “L7 load balancer” olarak düşünebilirsiniz. URL path’lerine, host adlarına ve header bilgilerine göre trafiği farklı backend servislerine yönlendirme yeteneğine sahiptir.

Ingress objesi tek başına hiçbir şey yapmaz. Sadece bir kural tanımıdır. Bu kuralları hayata geçiren bileşen ise Ingress Controller‘dır.

Ingress Controller Nedir ve Nasıl Çalışır?

Ingress Controller, cluster içinde sürekli çalışan ve Ingress objelerini izleyerek gerçek yönlendirme işlemlerini gerçekleştiren bir bileşendir. Kubernetes’in kendisiyle birlikte gelmiyor, ayrıca kurmanız gerekiyor. Piyasada birkaç popüler seçenek var:

  • NGINX Ingress Controller: En yaygın kullanılan, topluluk desteği güçlü
  • Traefik: Dinamik konfigürasyonu ve güzel dashboard’u ile öne çıkıyor
  • HAProxy Ingress: Yüksek performans gereksinimleri için
  • AWS ALB Ingress Controller: AWS ortamlarında Application Load Balancer entegrasyonu
  • Istio Ingress Gateway: Service mesh ile birlikte çalışan gelişmiş seçenek

Çalışma mantığı şu şekilde: Ingress Controller, Kubernetes API’sini izler. Yeni bir Ingress objesi oluşturulduğunda veya mevcut biri güncellendiğinde, Controller bu değişikliği algılar ve kendi proxy konfigürasyonunu (örneğin NGINX için nginx.conf) otomatik olarak günceller. Trafik Controller’a gelir, kurallar işlenir ve uygun backend servisine yönlendirilir.

NGINX Ingress Controller Kurulumu

Helm ile kurulum en pratik yöntem:

# Helm repo ekle
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Ingress Controller kur
helm install ingress-nginx ingress-nginx/ingress-nginx 
  --namespace ingress-nginx 
  --create-namespace 
  --set controller.replicaCount=2 
  --set controller.nodeSelector."kubernetes.io/os"=linux

# Kurulumu doğrula
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

Kurulum tamamlandığında ingress-nginx-controller servisinin EXTERNAL-IP alanında bir IP adresi göreceksiniz. Bu IP, tüm Ingress kurallarınızın tek giriş noktası olacak.

İlk Ingress Objesini Oluşturmak

Önce iki basit uygulama deploy edelim:

# app1 deployment ve servisi
kubectl create deployment app1 --image=nginx:alpine
kubectl expose deployment app1 --port=80 --name=app1-svc

# app2 deployment ve servisi
kubectl create deployment app2 --image=httpd:alpine
kubectl expose deployment app2 --port=80 --name=app2-svc

Şimdi bu iki uygulamayı path bazlı yönlendirmeyle dışarıya açalım:

# ingress-basic.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-first-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /app1
        pathType: Prefix
        backend:
          service:
            name: app1-svc
            port:
              number: 80
      - path: /app2
        pathType: Prefix
        backend:
          service:
            name: app2-svc
            port:
              number: 80
kubectl apply -f ingress-basic.yaml
kubectl get ingress
kubectl describe ingress my-first-ingress

Bu konfigürasyonla myapp.example.com/app1 trafiği app1-svc‘e, myapp.example.com/app2 trafiği app2-svc‘e yönlenecek.

Host Bazlı Yönlendirme

Path bazlı yönlendirmenin yanı sıra virtual host mantığıyla farklı domain adlarını farklı servislere yönlendirebilirsiniz. Bu özellikle multi-tenant uygulamalarda çok işe yarıyor:

# ingress-vhost.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: vhost-ingress
  namespace: production
spec:
  ingressClassName: nginx
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
  - host: admin.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: admin-service
            port:
              number: 3000
  - host: static.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: static-service
            port:
              number: 80

Bu yapıyla tek bir LoadBalancer IP’sinden üç farklı uygulamayı yönetebiliyorsunuz. DNS kayıtlarınızı tümü Ingress Controller’ın external IP’sine yönlendirmeniz yeterli.

TLS/HTTPS Konfigürasyonu

Production ortamında HTTP değil HTTPS kullanmak zorundasınız. Ingress üzerinde TLS sonlandırma oldukça kolay:

# Önce TLS secret oluştur (kendi sertifikanızla)
kubectl create secret tls my-tls-secret 
  --cert=path/to/tls.crt 
  --key=path/to/tls.key 
  --namespace=production

# cert-manager ile Let's Encrypt kullanıyorsanız önce cert-manager kur
helm repo add jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager 
  --namespace cert-manager 
  --create-namespace 
  --set installCRDs=true
# ingress-tls.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - api.example.com
    - admin.example.com
    secretName: my-tls-secret
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
  - host: admin.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: admin-service
            port:
              number: 3000

ssl-redirect: "true" annotation’ı HTTP’den HTTPS’e otomatik yönlendirme yapıyor. Bu sayede kullanıcılar HTTP ile gelse bile HTTPS’e çekiliyor.

Annotation’lar ile Gelişmiş Konfigürasyon

NGINX Ingress Controller’ın en güçlü yanlarından biri annotation sistemi. Onlarca farklı annotation ile davranışı özelleştirebilirsiniz:

# ingress-advanced.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: advanced-ingress
  namespace: production
  annotations:
    # Rate limiting - IP başına dakikada 100 istek
    nginx.ingress.kubernetes.io/limit-rps: "100"
    nginx.ingress.kubernetes.io/limit-connections: "20"
    
    # Request body boyutu sınırı (50MB)
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
    
    # Timeout ayarları
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    
    # CORS başlıkları
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-origin: "https://frontend.example.com"
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"
    
    # Custom header ekle
    nginx.ingress.kubernetes.io/configuration-snippet: |
      add_header X-Frame-Options "SAMEORIGIN";
      add_header X-Content-Type-Options "nosniff";
      add_header X-XSS-Protection "1; mode=block";
spec:
  ingressClassName: nginx
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

Bu konfigürasyonla rate limiting, güvenlik header’ları ve CORS ayarlarını tek bir Ingress objesinde yönetebiliyorsunuz.

Gerçek Dünya Senaryosu: Canary Deployment

Canary deployment, yeni bir versiyonu küçük bir trafik yüzdesiyle production’a almak için kullanılan bir strateji. NGINX Ingress Controller bu özelliği doğrudan destekliyor:

# ingress-canary.yaml - Mevcut stable sürüm
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-stable
  namespace: production
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-stable-svc
            port:
              number: 80
---
# Canary ingress - trafiğin %10'unu yeni versiyona yönlendir
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-canary
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-v2-svc
            port:
              number: 80

Bu yapıyla app.example.com‘a gelen trafiğin %10’u otomatik olarak yeni versiyona yönlendirilecek. Test başarılıysa canary-weight değerini artırarak kademeli geçiş yapabilirsiniz.

IngressClass Kullanımı

Birden fazla Ingress Controller çalıştırdığınız senaryolarda hangi controller’ın hangi Ingress’i yönettiğini belirtmek için IngressClass kullanıyorsunuz:

# Mevcut IngressClass'ları listele
kubectl get ingressclass

# IngressClass detayı
kubectl describe ingressclass nginx
# custom-ingressclass.yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: nginx-internal
  annotations:
    ingressclass.kubernetes.io/is-default-class: "false"
spec:
  controller: k8s.io/ingress-nginx
  parameters:
    apiGroup: k8s.nginx.org
    kind: IngressClassParameters
    name: nginx-internal-config

Bu özellikle şöyle bir senaryoda işe yarıyor: Internal trafik için bir NGINX controller, external trafik için başka bir controller çalıştırıyorsunuz. Her Ingress objesinde ingressClassName alanıyla hangi controller’ın kullanılacağını belirtiyorsunuz.

Troubleshooting ve Monitoring

Ingress konfigürasyonlarında sorun yaşamak kaçınılmaz. Hızlı debug için şu komutlar hayat kurtarıcı:

# Ingress Controller loglarını izle
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100 -f

# Ingress objesinin durumunu kontrol et
kubectl describe ingress my-first-ingress -n production

# NGINX konfigürasyonunu doğrudan görüntüle
kubectl exec -it -n ingress-nginx 
  $(kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx -o jsonpath='{.items[0].metadata.name}') 
  -- nginx -T | grep -A 20 "server_name api.example.com"

# Endpoint'lerin sağlıklı olup olmadığını kontrol et
kubectl get endpoints -n production

# Ingress Controller metriklerini incele (Prometheus scraping varsa)
kubectl port-forward -n ingress-nginx 
  svc/ingress-nginx-controller-metrics 10254:10254
curl http://localhost:10254/metrics | grep nginx_ingress_controller_requests

Sık karşılaşılan sorunlar ve çözümleri:

  • 404 hatası alıyorsanız: Backend servis adını ve port numarasını kontrol edin. kubectl get svc -n production ile doğrulayın
  • 503 Service Unavailable: Pod’larınız ayakta mı? kubectl get pods -n production ve kubectl get endpoints -n production çıktısına bakın
  • SSL sertifika hatası: Secret’ın doğru namespace’de olduğundan emin olun, kubectl describe secret my-tls-secret ile içeriği kontrol edin
  • Rewrite çalışmıyor: rewrite-target annotation’ı ile path regex’ini birlikte kullandığınızda gruplama parantezlerini doğru kullandığınızdan emin olun

ConfigMap ile Global NGINX Ayarları

Ingress Controller’ın genel davranışını değiştirmek için ConfigMap kullanabilirsiniz:

# Mevcut ConfigMap'i düzenle
kubectl edit configmap ingress-nginx-controller -n ingress-nginx
# nginx-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
data:
  # Worker process sayısı
  worker-processes: "auto"
  
  # Keepalive bağlantıları
  keep-alive: "75"
  keep-alive-requests: "1000"
  
  # Gzip sıkıştırma
  use-gzip: "true"
  gzip-level: "5"
  gzip-types: "application/json application/javascript text/css text/plain"
  
  # Log formatı
  log-format-upstream: '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id'
  
  # Proxy buffer ayarları
  proxy-buffer-size: "16k"
  proxy-buffers-number: "4"

ConfigMap değişikliklerini uyguladıktan sonra Controller’ı yeniden başlatmanız gerekmiyor; değişiklikler otomatik olarak algılanıp uygulanıyor.

Yük Dengeleme Stratejileri

NGINX Ingress Controller varsayılan olarak round-robin yük dengeleme kullanıyor ancak bunu değiştirebilirsiniz:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: load-balanced-ingress
  annotations:
    # IP hash - aynı client'ı aynı pod'a yönlendir (session affinity)
    nginx.ingress.kubernetes.io/upstream-hash-by: "$binary_remote_addr"
    
    # Ya da cookie bazlı session affinity
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "INGRESSCOOKIE"
    nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
    nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: stateful-app-svc
            port:
              number: 80

Session affinity özellikle stateful uygulamalarda, oturum bilgisini sunucu tarafında tutan eski nesil uygulamalarda kritik önem taşıyor.

Güvenlik En İyi Uygulamaları

Production ortamında Ingress güvenliğini sağlamak için dikkat edilmesi gereken noktalar:

  • IP Whitelist: Belirli IP bloklarına erişimi kısıtlama için nginx.ingress.kubernetes.io/whitelist-source-range annotation’ı kullanın
  • Basic Auth: Geliştirme ortamlarını dışarıya açarken auth-type: basic ile HTTP basic authentication ekleyin
  • ModSecurity WAF: NGINX Ingress Controller’da ModSecurity desteğini etkinleştirerek web application firewall özelliği kazanın
  • Network Policy: Ingress Controller pod’larının sadece ilgili backend servislerine erişebildiğinden emin olmak için NetworkPolicy objeleri oluşturun
  • Resource Limits: Controller deployment’ına mutlaka CPU ve memory limiti koyun; trafik spike’larında node’u ezip geçebilir
  • RBAC: Ingress objelerini oluşturma ve güncelleme yetkisini sadece gerekli servis hesaplarına verin

Sonuç

Ingress ve Ingress Controller, Kubernetes’te HTTP trafik yönetiminin omurgasını oluşturuyor. Tek bir LoadBalancer IP’siyle onlarca servisi yönetmek, TLS sonlandırma, canary deployment, rate limiting ve çok daha fazlasını tek bir API objesi üzerinden yapabilmek gerçekten güçlü bir esneklik sağlıyor.

Başlangıç için NGINX Ingress Controller ile yola çıkmanızı tavsiye ederim; dokümantasyonu kapsamlı, topluluk desteği güçlü ve annotation sistemi son derece zengin. Daha dinamik ve konfigürasyonsuz bir yapı istiyorsanız Traefik iyi bir alternatif. Cloud native bir yaklaşım tercih ediyorsanız ve AWS, GCP veya Azure üzerindeyseniz ilgili cloud provider’ın kendi Ingress Controller’ını kullanmak daha entegre bir deneyim sunuyor.

Önemli bir hatırlatma: Ingress objelerini namespace’lere göre organize edin, her uygulamanın kendi Ingress’i olsun ve merkezi bir “mega Ingress” oluşturmaktan kaçının. Bu yaklaşım hem yönetimi kolaylaştırır hem de sorun çıktığında izolasyonu sağlar. Troubleshooting süreçlerinde Controller loglarını ve kubectl describe ingress çıktısını incelemeyi alışkanlık haline getirin; çoğu sorunun cevabı orada saklı.

Yorum yapın