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 productionile doğrulayın - 503 Service Unavailable: Pod’larınız ayakta mı?
kubectl get pods -n productionvekubectl 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-secretile içeriği kontrol edin - Rewrite çalışmıyor:
rewrite-targetannotation’ı ilepathregex’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-rangeannotation’ı kullanın - Basic Auth: Geliştirme ortamlarını dışarıya açarken
auth-type: basicile 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ı.