Kubernetes Ingress: Come Esporre i Tuoi Servizi al Mondo
Guida completa a Kubernetes Ingress. Ingress controller a confronto, configurazione TLS, routing avanzato. Esempi pratici e best practices.
Hai deployato la tua applicazione su Kubernetes. I pod girano, i service funzionano. Ma come fai ad accederci dall'esterno? Con un Service di tipo LoadBalancer ottieni un IP pubblico, ma paghi un load balancer per ogni servizio. Con NodePort esponi una porta su ogni nodo, ma e scomodo e poco flessibile.
Ingress e la soluzione: un singolo punto di ingresso che gestisce routing, TLS, e load balancing per tutti i tuoi servizi HTTP/HTTPS.
Cos'e Ingress
Ingress e una risorsa Kubernetes che definisce regole per il traffico HTTP/HTTPS in entrata. Dice cose come: "le richieste per api.example.com vanno al service api", "le richieste per example.com/blog vanno al service blog".
Ma Ingress da solo non fa niente. E solo una definizione. Per farlo funzionare serve un Ingress Controller — un componente che legge le risorse Ingress e le implementa effettivamente.
E come la differenza tra un file di configurazione e il programma che lo usa. L'Ingress e la configurazione, l'Ingress Controller e il programma.
Ingress Controller: Le Opzioni
Ci sono molti ingress controller. I piu usati:
NGINX Ingress Controller — Il piu comune. Usa NGINX sotto il cofano, ha quasi tutte le feature che ti servono, buona documentazione. E quello che consiglio di default se non hai requisiti specifici.
Traefik — Popolare, buona integrazione con Docker e Kubernetes, configurazione dinamica nativa. Default su K3s.
HAProxy Ingress — Performance eccellenti, feature enterprise. Scelta solida per workload critici.
Contour — Basato su Envoy, buono per ambienti che gia usano Envoy/Istio.
Kong — Ha feature di API Gateway integrate. Se ti servono rate limiting, authentication, etc., Kong le ha built-in.
Per la maggior parte dei casi, NGINX o Traefik vanno benissimo. La scelta spesso dipende da cosa gia conosci o usi.
Installare NGINX Ingress Controller
# Via Helm (consigliato)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx
Dopo l'installazione, avrai un Service di tipo LoadBalancer che e il punto di ingresso. Su cloud provider, ottieni un IP pubblico. On-premise, potresti dover configurare MetalLB o simili.
Verifica che funzioni:
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
La Prima Regola Ingress
Supponiamo di avere un deployment e un service:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 80
Ora creiamo un Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
spec:
ingressClassName: nginx
rules:
- host: my-app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-svc
port:
number: 80
Applica e verifica:
kubectl apply -f ingress.yaml
kubectl get ingress
Ora le richieste a my-app.example.com (assumendo che il DNS punti all'IP dell'ingress controller) arrivano al tuo service.
Routing Basato su Path
Un singolo Ingress puo gestire routing multipli:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-path-ingress
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: default-service
port:
number: 80
L'ordine conta. I path piu specifici dovrebbero venire prima. /api viene matchato prima di /.
pathType
Prefix: Matcha il path come prefisso./apimatcha/api,/api/users,/api/v1/users.Exact: Matcha esattamente./apimatcha solo/api, non/api/users.ImplementationSpecific: Comportamento dipende dall'ingress controller.
Routing Basato su Host
Puoi servire host diversi con lo stesso Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
Ogni host puo avere regole di path indipendenti.
TLS/HTTPS
In produzione, vuoi HTTPS. Due modi per gestirlo.
Certificato Manuale
Crea un Secret con il certificato:
kubectl create secret tls my-tls-secret \
--cert=path/to/cert.pem \
--key=path/to/key.pem
Referenzialo nell'Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- my-app.example.com
secretName: my-tls-secret
rules:
- host: my-app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-svc
port:
number: 80
cert-manager (Consigliato)
cert-manager automatizza tutto: richiede certificati a Let's Encrypt, li rinnova, li gestisce.
# Installa cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml
Crea un ClusterIssuer per Let's Encrypt:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: your-email@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
Ora l'Ingress puo richiedere certificati automaticamente:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auto-tls-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- my-app.example.com
secretName: my-app-tls # cert-manager crea questo
rules:
- host: my-app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-svc
port:
number: 80
cert-manager vede l'annotation, richiede il certificato, lo salva nel Secret, e lo rinnova prima della scadenza. Zero manutenzione.
Annotations Utili (NGINX)
Gli ingress controller supportano annotation per configurazioni avanzate. Queste sono specifiche per NGINX Ingress Controller:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: annotated-ingress
annotations:
# Redirect HTTP a HTTPS
nginx.ingress.kubernetes.io/ssl-redirect: "true"
# Rate limiting
nginx.ingress.kubernetes.io/limit-rps: "10"
# Proxy timeout
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
# Rewrite path
nginx.ingress.kubernetes.io/rewrite-target: /$2
# Client max body size (upload)
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
# CORS
nginx.ingress.kubernetes.io/enable-cors: "true"
# Basic auth
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
spec:
# ...
Ogni ingress controller ha le sue annotation. Controlla la documentazione del tuo.
Rewrite Target
Un pattern comune: vuoi che /api vada al service, ma il service si aspetta richieste a /.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-service
port:
number: 80
Richiesta a example.com/api/users → service riceve /users.
Ingress Class
Da Kubernetes 1.18+, IngressClass e il modo consigliato per specificare quale controller gestisce un Ingress.
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: k8s.io/ingress-nginx
Se marchi una IngressClass come default, gli Ingress senza ingressClassName usano quella.
Default Backend
Cosa succede se una richiesta non matcha nessuna regola? Puoi definire un default backend:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: default-backend-ingress
spec:
ingressClassName: nginx
defaultBackend:
service:
name: default-service
port:
number: 80
rules:
# regole normali...
Utile per servire una pagina 404 custom o redirect a una landing page.
Troubleshooting
L'Ingress non funziona:
- Verifica che il controller sia running:
kubectl get pods -n ingress-nginx - Controlla gli eventi dell'Ingress:
kubectl describe ingress my-ingress - Verifica che il service backend esista e funzioni
- Controlla i log del controller:
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
Certificato TLS non funziona:
- Verifica che il Secret esista:
kubectl get secret my-tls-secret - Controlla che i nomi host matchino il certificato
- Con cert-manager, controlla lo stato del Certificate:
kubectl get certificates
404 anche se il path dovrebbe matchare:
- Verifica pathType (Prefix vs Exact)
- Controlla l'ordine dei path (piu specifici prima)
- Verifica che il service abbia endpoint:
kubectl get endpoints my-service
Best Practices
Usa sempre TLS in produzione. Con cert-manager e praticamente gratis. Non c'e scusa per non avere HTTPS.
Un Ingress per applicazione. Rende piu facile gestire lifecycle e permessi indipendenti.
Monitora l'ingress controller. E un single point of failure. Configura alerting su CPU, memoria, e error rate.
Rate limiting. Proteggi i tuoi service da abusi. Meglio impostarlo dall'inizio che dopo un incidente.
Replica il controller. Di default molti controller girano con una replica. In produzione, almeno 2-3.
Backup delle configurazioni. Ingress sono risorse Kubernetes, quindi GitOps. Ma assicurati che i Secret TLS siano gestiti correttamente (non committare chiavi private!).
Conclusione
Ingress e il modo standard per esporre servizi HTTP su Kubernetes. Una volta capito il concetto (Ingress = regole, Ingress Controller = implementazione), il resto e configurazione.
Inizia semplice: NGINX Ingress Controller, cert-manager per TLS, regole base. Aggiungi complessita (rewrite, rate limiting, etc.) quando ti serve.
Non e rocket science, ma ci sono abbastanza dettagli da far perdere tempo se non li conosci. Spero che questa guida ti risparmi qualche ora di debugging.
L'infrastruttura ben fatta e invisibile. Quando l'Ingress funziona, nessuno ci pensa. Ed e cosi che dev'essere.