Arribem al moment que el curs porta prometent des del mòdul 1: publicar Rutas Norte a internet. Tenim cinc components desplegats, tots amb Services ClusterIP que només existeixen dins del clúster, i cap client no pot comprar un bitllet. A 04-02 vam veure que LoadBalancer resoldria el problema al preu d'un balancejador i una IP pública per servei, sense encaminament per domini ni per ruta. Aquesta lliçó presenta la resposta correcta: un únic punt d'entrada HTTP que reparteix el trànsit segons el domini i la ruta demanats. En acabar, www.rutasnorte.example servirà la botiga i api.rutasnorte.example servirà l'API, tots dos des del mateix balancejador, i sabràs distingir amb claredat entre el recurs Ingress —una regla que no fa res per si sola— i el controlador d'Ingress, el programa que la converteix en configuració real.
Contingut
- El problema: diversos serveis HTTP, un sol punt d'entrada
- Recurs davant de controlador: la distinció essencial
- Panorama de controladors
IngressClassi l'anotació heretada- Anatomia d'un Ingress
pathType: els tres valors i els casos que confonen- Cas pràctic: publicar la botiga i l'API
- Encaminament per host davant d'encaminament per ruta i reescriptura
- Anotacions del dia a dia
- Depuració
- Gateway API: la successora
- El problema: diversos serveis HTTP, un sol punt d'entrada
Rutas Norte necessita publicar, com a mínim:
| Destinació pública | Component | Notes |
|---|---|---|
www.rutasnorte.example |
botiga-web |
Trànsit massiu als ponts |
api.rutasnorte.example |
api-reserves |
Consumida per la SPA i per agències |
www.rutasnorte.example/api |
api-reserves |
Alternativa sense domini a part |
admin.rutasnorte.example |
Panell intern | Només des de la xarxa d'oficina |
Amb type: LoadBalancer serien quatre balancejadors, quatre IP públiques i quatre certificats TLS gestionats per separat, multiplicat pels tres entorns. I tot i així faltaria l'essencial: un balancejador L4 no entén HTTP. No pot llegir la capçalera Host per decidir a quin servei va la petició, ni mirar la ruta, ni reescriure-la, ni afegir capçaleres. L'Ingress trasllada la decisió a capa 7:
flowchart TB
C1["Client<br/>www.rutasnorte.example"] --> LB
C2["Client<br/>api.rutasnorte.example"] --> LB
LB["UN Service LoadBalancer<br/>IP publica unica"] --> IC["Controlador d'Ingress<br/>(pods nginx al cluster)"]
IC -->|"Host: www.rutasnorte.example"| S1["Service botiga-web<br/>ClusterIP"]
IC -->|"Host: api.rutasnorte.example"| S2["Service api-reserves<br/>ClusterIP"]
IC -->|"/admin"| S3["Service panell-admin<br/>ClusterIP"]
S1 --> P1["Pods botiga-web"]
S2 --> P2["Pods api-reserves"]
Un balancejador, una IP, un lloc on acabar el TLS (04-05), i tots els serveis interns continuen sent ClusterIP.
- Recurs davant de controlador: la distinció essencial
Aquesta és la confusió número u de la lliçó i cal fixar-la abans d'escriure res.
Recurs Ingress |
Controlador d'Ingress | |
|---|---|---|
| Què és | Un objecte de l'API, networking.k8s.io/v1 |
Un programa que s'executa en pods del clúster |
| Què fa | Res. Declara una intenció | Observa els Ingress i encamina el trànsit real |
| Qui el crea | Tu, amb kubectl apply |
L'administrador, un cop per clúster |
| Analogia | El senyal de trànsit dibuixat en un plànol | L'asfalt, els carrils i el guàrdia |
| Si falta l'altre | Es crea sense error i no passa res | No sap on enviar res |
El símptoma de crear un Ingress sense controlador enganya: kubectl apply respon created, kubectl get ingress el llista i el domini no respon. La pista és a la columna ADDRESS, buida per sempre.
Un controlador és, per dins, un bucle idèntic al del mòdul 1: observa l'API, llegeix els Ingress, Services i EndpointSlices, genera un fitxer de configuració (un nginx.conf, a ingress-nginx) i recarrega el seu proxy, fent servir una ServiceAccount amb permisos (03-06).
- Panorama de controladors
| Controlador | Base | Punts forts | A tenir en compte |
|---|---|---|---|
| ingress-nginx | NGINX | El més estès; mantingut pel projecte Kubernetes; enorme catàleg d'anotacions | Recarrega la configuració en canviar; moltes funcions viuen en anotacions no estandarditzades |
| Traefik | Go, propi | Configuració dinàmica sense recàrregues; integració nativa amb ACME; bon panell | Les seves funcions avançades fan servir CRD propis (IngressRoute) |
| HAProxy Ingress | HAProxy | Rendiment i estabilitat en L4/L7; excel·lent per a càrrega alta | Comunitat més petita |
| AWS ALB / GKE / AGIC | Balancejador del núvol | El trànsit ni tan sols entra en un pod; s'integra amb WAF i certificats gestionats | Lligat al proveïdor; menys control fi |
| Istio Gateway / Cilium | Malla / eBPF | mTLS, polítiques L7, telemetria profunda | Complexitat notable; sol venir amb una malla completa |
Compte amb un detall històric: existeixen dos controladors basats en NGINX. ingress-nginx és el del projecte Kubernetes; "NGINX Ingress Controller" és el de F5/NGINX Inc. Les seves anotacions no són compatibles, i moltes hores s'han perdut copiant la del controlador equivocat. Aquí fem servir ingress-nginx, el de l'addon de minikube.
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-9k2lm 0/1 Completed 0 70s
ingress-nginx-admission-patch-x4dpq 0/1 Completed 0 70s
ingress-nginx-controller-7d4b8f6c8d-2vq7z 1/1 Running 0 70sEls dos Completed són Jobs (06-03) que instal·len el webhook de validació: gràcies a ell, un Ingress amb sintaxi invàlida es rebutja a l'apply en lloc de trencar la configuració del proxy.
IngressClass i l'anotació heretada
IngressClass i l'anotació heretadaUn clúster pot tenir diversos controladors: un de públic per a botiga-web i api-reserves, un altre d'intern per al panell d'administració. IngressClass diu quin controlador atén quin Ingress.
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
annotations:
ingressclass.kubernetes.io/is-default-class: "true" # aten els Ingress sense classe
spec:
controller: k8s.io/ingress-nginxA l'Ingress es referencia amb el camp spec.ingressClassName: nginx. Abans de Kubernetes 1.18 això es feia amb l'anotació kubernetes.io/ingress.class: "nginx", que continua funcionant en molts controladors per compatibilitat però està desaconsellada i desapareixerà. Veuràs moltíssims exemples a internet amb ella: són antics. Fes servir ingressClassName.
Si no indiques classe i cap no està marcada com a predeterminada, cap controlador no recull l'Ingress: ADDRESS buit i silenci.
- Anatomia d'un Ingress
apiVersion: networking.k8s.io/v1 # COMPTE: v1, no les obsoletes extensions/v1beta1
kind: Ingress
metadata:
name: rutas-norte
namespace: rutas-norte-pro # ha de ser el MATEIX que el dels Services
spec:
ingressClassName: nginx # quin controlador l'aten
defaultBackend: # opcional: on va allo que no casa cap regla
service:
name: botiga-web
port:
number: 80
rules:
- host: www.rutasnorte.example # opcional: sense host, la regla casa qualsevol domini
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: botiga-web # nom d'un Service del MATEIX namespace
port:
number: 80 # o name: http, si el port te nomRestriccions que provoquen la majoria de les fallades:
- L'Ingress i els Services han de ser al mateix namespace. Un Ingress de
rutas-norte-prono pot apuntar a un Service derutas-norte-dev: és disseny de seguretat, no limitació tècnica. - El
portpot sernumberoname, però no tots dos. Referenciar-lo per nom sobreviu a un canvi de número. hostaccepta un comodí al primer nivell (*.rutasnorte.example), que casaapi.rutasnorte.exampleperò nowww.api.rutasnorte.exampleni el domini nu. Les regles sensehostcasen qualsevol domini: útil per a proves per IP, perillós en producció.
defaultBackend és la destinació d'allò que no casa res: sense ell, el controlador retorna el seu 404 genèric; amb ell, un client que escrigui malament el subdomini acaba a la botiga.
pathType: els tres valors i els casos que confonen
pathType: els tres valors i els casos que confonenpathType és obligatori des de networking.k8s.io/v1 i la seva semàntica sorprèn gairebé tothom.
| Valor | Com compara | Recomanació |
|---|---|---|
Exact |
Coincidència literal exacta, sensible a majúscules | Rutes concretes, sense descendents |
Prefix |
Per segments de ruta separats per /, no per caràcters |
El valor per defecte de facto |
ImplementationSpecific |
Ho decideix el controlador; a ingress-nginx habilita expressions regulars | Només quan necessitis regex, i sabent que no és portable |
La clau de Prefix és a les tres paraules "per segments de ruta". /api no és un prefix de caràcters: casa /api i /api/elquesigui, però no casa /apificat.
| Regla | Petició | Casa? | Per què |
|---|---|---|---|
/api Prefix |
/api |
Sí | Exacte |
/api Prefix |
/api/ |
Sí | Segment complet |
/api/ Prefix |
/api |
Sí | La barra final s'ignora en comparar |
/api Prefix |
/api/reserves/33 |
Sí | Descendent per segments |
/api Prefix |
/apificat |
No | apificat és un altre segment diferent |
/api Exact |
/api |
Sí | |
/api Exact |
/api/ |
No | La barra final la fa diferent |
/api Exact |
/api/reserves |
No | No hi ha descendents |
/API Exact |
/api |
No | Distingeix majúscules |
Regla de desempat quan diverses casen: guanya la ruta més llarga, sense importar el pathType.
paths:
- path: / # casa tot
pathType: Prefix
backend: { service: { name: botiga-web, port: { number: 80 } } }
- path: /api # mes llarga: guanya per a /api/*
pathType: Prefix
backend: { service: { name: api-reserves, port: { number: 3000 } } }Una petició a /api/reserves casa les dues regles, i va a api-reserves perquè /api és més llarga que /. Aquest ordre per longitud, i no per posició al YAML, evita l'error de "he posat la regla més específica a dalt i no funciona".
- Cas pràctic: publicar la botiga i l'API
Un sol Ingress publica els dos dominis de Rutas Norte.
# k8s/entorns/pro/ingress-rutas-norte.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rutas-norte
namespace: rutas-norte-pro
labels:
app.kubernetes.io/part-of: rutas-norte
entorn: pro
annotations:
# Mida de cos: els justificants en PDF que puja atencio al client
nginx.ingress.kubernetes.io/proxy-body-size: "8m"
# La passarel-la de pagaments pot trigar; donem marge
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
spec:
ingressClassName: nginx
rules:
- host: www.rutasnorte.example
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: botiga-web
port:
name: http # referencia per nom de port
- host: api.rutasnorte.example
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-reserves
port:
name: httpFixa't en el que no cal fer: no es canvien els Services a NodePort ni a LoadBalancer. Continuen sent ClusterIP, perquè qui els parla és el controlador, que és dins del clúster.
Aplicació i comprovació:
kubectl apply -f k8s/entorns/pro/ingress-rutas-norte.yaml
kubectl get ingress -n rutas-norte-pro
# Els dominis .example no existeixen al DNS public: es resolen a ma
echo "$(minikube -p rutas-norte ip) www.rutasnorte.example api.rutasnorte.example" \
| sudo tee -a /etc/hosts
curl -s -o /dev/null -w 'botiga: %{http_code}\n' http://www.rutasnorte.example/
curl -s -w '\n' http://api.rutasnorte.example/salutNAME CLASS HOSTS ADDRESS PORTS AGE
rutas-norte nginx www.rutasnorte.example,api.rutasnorte.example 192.168.49.2 80 40s
botiga: 200
{"estat":"ok","versio":"2.4.1","entorn":"pro"}ADDRESS amb la IP del node significa que el controlador ha recollit l'Ingress. Aquest camp triga entre uns segons i un parell de minuts a aparèixer; si continua buit passats cinc, alguna cosa va malament (apartat 10).
Els clients de Rutas Norte ja poden arribar a la plataforma: és la primera vegada al curs que el trànsit entra de debò des de fora del clúster. Que l'encaminament es fa per la capçalera Host i no per la IP ho comprovarem a l'exercici 1: mateixa IP, mateix port, resultats diferents segons el Host. Això és encaminament L7.
- Encaminament per host davant d'encaminament per ruta i reescriptura
L'alternativa als dos dominis és servir l'API sota /api del domini principal.
Per host (api.rutasnorte.example) |
Per ruta (www.rutasnorte.example/api) |
|
|---|---|---|
| Certificats TLS | Un per domini (o comodí) | Un de sol |
| Registres DNS | Un per subdomini | Un |
| CORS a la SPA | Sí: origen diferent | No: mateix origen |
| Galetes | No es comparteixen entre subdominis (tret de configuració) | Compartides |
| Reescriptura de ruta | No necessària | Gairebé sempre necessària |
| Escalar per separat | Molt fàcil | Fàcil |
Rutas Norte fa servir totes dues: api.rutasnorte.example per a les agències externes, i www.rutasnorte.example/api perquè la SPA no hagi de lidiar amb CORS.
Reescriptura de rutes
El problema: la SPA demana /api/reserves però api-reserves espera /reserves; sense reescriptura rebria /api/reserves i retornaria 404.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rutas-norte-api-per-ruta
namespace: rutas-norte-pro
annotations:
# $2 = segon grup de captura de l'expressio regular del path
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx
rules:
- host: www.rutasnorte.example
http:
paths:
- path: /api(/|$)(.*) # grup 1: /(o fi), grup 2: la resta
pathType: ImplementationSpecific
backend:
service:
name: api-reserves
port:
name: httpCom llegir aquesta expressió: /api casa el prefix literal; (/|$) és el grup 1 (una barra o el final de la cadena, perquè casin tant /api com /api/...); (.*) és el grup 2, tot el que vingui després; i rewrite-target: /$2 reconstrueix la ruta amb només el grup 2.
| Petició del navegador | Grup 2 | El que rep api-reserves |
|---|---|---|
/api/reserves |
reserves |
/reserves |
/api/reserves/33 |
reserves/33 |
/reserves/33 |
/api |
(buit) | / |
/api/salut?v=2 |
salut |
/salut?v=2 (la query es conserva) |
I l'avís: pathType passa a ImplementationSpecific perquè estem fent servir una expressió regular, cosa que Prefix no contempla. Aquell Ingress no és portable a Traefik ni a l'ALB d'AWS. És un compromís conscient.
Advertència molt repetida: la reescriptura afecta la ruta de la petició, no les URL que l'aplicació genera al seu HTML o a les seves redireccions. Si api-reserves respon Location: /reserves/33, el navegador hi anirà i no a /api/reserves/33. Les aplicacions servides sota un prefix l'han de conèixer (típicament amb una variable BASE_PATH).
- Anotacions del dia a dia
Les anotacions són el mecanisme pel qual cada controlador exposa les seves funcions; aquestes són les d'ingress-nginx que es fan servir en qualsevol plataforma real.
| Anotació | Per a què | Valor típic a Rutas Norte |
|---|---|---|
proxy-body-size |
Mida màxima del cos. 413 Request Entity Too Large si se supera |
8m |
proxy-read-timeout / proxy-send-timeout |
Segons d'espera cap al backend. 504 en esgotar-se |
60 |
proxy-connect-timeout |
Espera per establir connexió | 5 |
limit-rps / limit-connections |
Limitació de peticions i connexions per IP de client | 20 rps |
limit-whitelist |
IP exemptes del límit | Rang de l'oficina |
whitelist-source-range |
Només aquestes IP hi poden accedir | Panell d'administració |
configuration-snippet |
Fragment de configuració NGINX a mida | Capçaleres de seguretat |
enable-cors / cors-allow-origin |
Capçaleres CORS gestionades pel proxy | Per a les agències externes |
backend-protocol |
HTTP, HTTPS, GRPC |
HTTP |
Exemple aplicat als pics de trànsit de ponts i vacances:
metadata:
annotations:
# Limitacio: 20 peticions per segon i client, amb marge de rafega
nginx.ingress.kubernetes.io/limit-rps: "20"
nginx.ingress.kubernetes.io/limit-burst-multiplier: "3"
# La xarxa de l'oficina no es limita mai
nginx.ingress.kubernetes.io/limit-whitelist: "10.20.30.0/24"
# Capceleres de seguretat cap al client
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "X-Content-Type-Options: nosniff";
more_set_headers "X-Frame-Options: SAMEORIGIN";Dues advertències importants:
configuration-snippetestà desactivat per defecte a les versions recents d'ingress-nginx per seguretat (permetia injectar configuració arbitrària del proxy des de qualsevol namespace). Cal habilitar-lo al ConfigMap del controlador, i convé pensar-s'ho dues vegades.- La limitació s'aplica per rèplica del controlador. Amb tres rèpliques, un límit de 20 rps és a la pràctica 60.
Els ajustos globals (capçaleres per defecte, mides de memòria intermèdia, format de log) no van en anotacions sinó al ConfigMap del controlador, ingress-nginx-controller del namespace ingress-nginx.
- Depuració
kubectl describe ingress
La primera parada sempre:
Name: rutas-norte
Namespace: rutas-norte-pro
Address: 192.168.49.2
Ingress Class: nginx
Rules:
Host Path Backends
---- ---- --------
www.rutasnorte.example
/ botiga-web:http (10.244.0.22:8080,10.244.0.29:8080)
api.rutasnorte.example
/ api-reserves:http (10.244.0.31:3000)
Events:
Type Reason Age From Message
---- ------ ---- ------------------------ -------
Normal Sync 35s nginx-ingress-controller Scheduled for syncEl que cal mirar, en aquest ordre: Address emplenat (algú ha recollit l'Ingress); Ingress Class correcta; els backends amb IP de pod entre parèntesis —si posa <error: endpoints "botiga-web" not found> o una llista buida, el problema no és de l'Ingress, és el Service, i tornes al diagnòstic de 02-05—; i Events amb Sync, que confirma que el controlador va aplicar la configuració.
Logs del controlador
192.168.49.1 - - [05/Aug/2026:11:20:14 +0000] "GET /reserves/33 HTTP/1.1" 200 812
"-" "curl/8.5.0" 141 0.043 [rutas-norte-pro-api-reserves-http] [] 10.244.0.31:3000 812 0.042 200Els camps entre claudàtors són or: [rutas-norte-pro-api-reserves-http] és l'upstream triat, i 10.244.0.31:3000 el pod concret. Si l'upstream apareix buit, cap regla no ha casat.
Quadre de fallades
| Símptoma | Causa probable | Comprovació |
|---|---|---|
ADDRESS buit després de 5 min |
No hi ha controlador, o ingressClassName no casa |
kubectl get pods -n ingress-nginx; kubectl get ingressclass |
404 del controlador (nginx) |
Cap regla no casa: Host o path malament |
curl -H 'Host: ...'; revisa pathType |
503 Service Temporarily Unavailable |
El Service no té endpoints | kubectl get endpointslices -n <ns> |
502 Bad Gateway |
El pod rebutja la connexió o el targetPort és incorrecte |
kubectl exec i curl al pod directament |
504 Gateway Time-out |
El backend triga més que proxy-read-timeout |
Puja el temps d'espera o arregla la lentitud |
413 |
Cos més gran que proxy-body-size |
Ajusta l'anotació |
| Funciona per IP i no per domini | /etc/hosts o DNS malament |
getent hosts www.rutasnorte.example |
| L'Ingress no es crea | El webhook de validació el rebutja | Llegeix el missatge: sol ser regex invàlida o ruta mal formada |
La distinció mereix memoritzar-se: 503 és que no hi ha a qui enviar (endpoints buits) i 502 és que hi ha a qui enviar però no respon bé. Capes diferents.
La verificació definitiva: la configuració generada
Veure el nginx.conf que el controlador ha generat a partir del teu Ingress tanca qualsevol discussió sobre què està passant: kubectl exec -n ingress-nginx deploy/ingress-nginx-controller -- cat /etc/nginx/nginx.conf | grep -A5 "server_name api.rutasnorte.example".
- Gateway API: la successora
L'Ingress ha envellit malament. La seva especificació és tan mínima que tot allò interessant va acabar en anotacions propietàries: reescriptura, CORS, limitació, capçaleres... Res d'això no és portable. A més barreja responsabilitats: qui administra la infraestructura i qui publica una aplicació editen el mateix objecte.
La Gateway API (gateway.networking.k8s.io) és la resposta oficial, ja estable per als seus recursos principals.
| Concepte | Recurs | Qui el gestiona |
|---|---|---|
| Quina implementació es fa servir | GatewayClass |
Administrador del clúster |
| El punt d'entrada: ports, TLS, dominis | Gateway |
Equip de plataforma |
| Les regles HTTP: hosts, rutes, filtres, pesos | HTTPRoute |
Equip d'aplicació |
| Altres protocols | TCPRoute, GRPCRoute, TLSRoute |
Equip d'aplicació |
Avantatges concrets davant d'Ingress: separació de rols (l'equip de Rutas Norte crea el seu HTTPRoute sense tocar el punt d'entrada); funcions al model, no en anotacions —reescriptura, redirecció, capçaleres i repartiment per pesos són camps de l'API, així que el canari de 11-04 deixa de necessitar anotacions específiques—; rutes entre namespaces amb permís explícit del propietari del Gateway; i portabilitat real entre implementacions.
L'Ingress no està obsolet i continuarà funcionant molts anys: hi ha massa desplegat. Però per a una plataforma nova el 2026 val la pena avaluar la Gateway API, sobretot si ja es fa servir Istio, Cilium o Traefik. Aquí continuem amb Ingress perquè és el que et trobaràs i el que avaluen les certificacions del mòdul 12.
Errors Comuns i Consells
- Crear l'Ingress sense controlador. L'
applyva bé i res no funciona. Comprovakubectl get pods -n ingress-nginxabans. - Apuntar a un Service d'un altre namespace. No és possible. L'Ingress viu al namespace dels seus Services.
- Copiar anotacions del controlador equivocat.
nginx.ingress.kubernetes.io/*és d'ingress-nginx; el de F5 fa servirnginx.org/*. No són intercanviables. - Fer servir
kubernetes.io/ingress.class. Obsoleta. Fes serviringressClassName. - Esperar que
Prefixcompari caràcters./apino casa/apificat. Compara segments. - Confondre
503amb502. El primer és "no hi ha endpoints"; el segon, "el pod no respon bé". Diagnòstics diferents. - Reescriure rutes sense que l'aplicació ho sàpiga. Els enllaços i redireccions que generi continuaran sense el prefix. Configura el
BASE_PATHde l'aplicació. - Oblidar que l'encaminament depèn de la capçalera
Host. Provar ambcurl http://IP/sense-H 'Host: ...'donarà404encara que tot estigui bé. - Consell: un Ingress per aplicació, no un de gegant per clúster. Es despleguen i es reverteixen de manera independent.
- Consell: les anotacions de temps d'espera i mida de cos són de les primeres que es necessiten en producció. Posa-les des del principi amb valors raonables en lloc d'esperar al primer
413en un pont.
Exercicis
Exercici 1: Publicar els dos dominis de Rutas Norte
Activa l'addon ingress de minikube, crea l'Ingress que publica www.rutasnorte.example contra botiga-web i api.rutasnorte.example contra api-reserves, resol els dominis a /etc/hosts i comprova les dues rutes. Demostra a més que l'encaminament es fa per capçalera Host.
Exercici 2: Servir l'API sota /api amb reescriptura
Afegeix al domini www.rutasnorte.example una ruta /api que arribi a api-reserves sense el prefix. Verifica als logs del controlador quina ruta rep realment el backend i què passa amb /apificat.
Exercici 3: Diagnosticar tres Ingress trencats
Reprodueix i diagnostica: (A) un Ingress amb ingressClassName: traefik en un clúster amb només ingress-nginx; (B) un Ingress correcte el Service del qual apunta a un selector que no casa; (C) un Ingress el backend.service.port.number del qual és 8080 quan el Service exposa el 80. Indica el símptoma exacte de cadascun i l'ordre que l'identifica.
Solucions
Exercici 1
minikube -p rutas-norte addons enable ingress
kubectl wait --for=condition=ready pod \
-l app.kubernetes.io/component=controller -n ingress-nginx --timeout=120s
kubectl apply -f k8s/entorns/pro/ingress-rutas-norte.yaml
kubectl get ingress -n rutas-norte-pro -w # esperar que aparegui ADDRESS
# Encaminament per Host: mateixa IP, tres resultats
IP=$(minikube -p rutas-norte ip)
for H in www.rutasnorte.example api.rutasnorte.example inventat.example; do
printf '%-28s %s\n' "$H" "$(curl -s -o /dev/null -w '%{http_code}' -H "Host: $H" http://$IP/)"
doneEl 404 del tercer prova que la decisió es pren llegint la capçalera Host, no la IP de destinació.
Exercici 2
# k8s/entorns/pro/ingress-api-per-ruta.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rutas-norte-api-per-ruta
namespace: rutas-norte-pro
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx
rules:
- host: www.rutasnorte.example
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-reserves
port:
name: httpkubectl apply -f k8s/entorns/pro/ingress-api-per-ruta.yaml
curl -s http://www.rutasnorte.example/api/salut
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller --tail=3El client va demanar /api/salut; el backend va rebre /salut. Amb /apificat, la regex /api(/|$)(.*) sí que casaria (perquè use-regex compara caràcters, no segments) i el backend rebria /ficat — un motiu més per preferir Prefix tret que la reescriptura sigui imprescindible, i per ancorar millor l'expressió si és un problema.
Exercici 3
| Cas | Símptoma | Ordre que l'identifica |
|---|---|---|
| A classe inexistent | ADDRESS permanentment buit; cap esdeveniment Sync; el domini no respon |
kubectl get ingressclass (només existeix nginx) i kubectl describe ingress sense esdeveniments |
| B selector que no casa | L'Ingress està bé i amb ADDRESS, però retorna 503 |
kubectl describe ingress mostra el backend sense IP; kubectl get endpointslices buit |
| C port inexistent | 503 i un error explícit a describe |
<error: endpoints "api-reserves" not found> o backend sense resoldre; el port de l'Ingress ha de coincidir amb el port del Service, no amb el del contenidor |
kubectl describe ingress <nom> -n rutas-norte-pro | sed -n '/Rules/,/Annotations/p'
kubectl get endpointslices -n rutas-norte-pro -l kubernetes.io/service-name=api-reservesL'error de C és especialment freqüent: el port de l'Ingress és el del Service (port), no el del contenidor (targetPort). Confondre'ls produeix un Ingress que sembla correcte i retorna 503.
Conclusió
Rutas Norte ja està publicada. Entens la distinció que ordena tota la resta: el recurs Ingress és una declaració d'intencions que per si sola no fa absolutament res, i el controlador d'Ingress és el programa que l'observa, genera configuració de proxy i encamina el trànsit de debò; si falta el segon, el primer es crea sense errors i l'ADDRESS es queda buit per sempre. Coneixes el panorama de controladors, el perill de confondre ingress-nginx amb el controlador homònim de F5, i saps seleccionar el teu amb ingressClassName en lloc de l'anotació obsoleta kubernetes.io/ingress.class.
Domines l'anatomia de l'objecte: rules amb host i http.paths, backend.service.name amb el port del Service (no el del contenidor), i el defaultBackend per a allò que no casa res. Tens clar que pathType: Prefix compara segments de ruta i no caràcters —/api no casa /apificat— que Exact distingeix la barra final i les majúscules, que ImplementationSpecific és la porta a les expressions regulars al preu de la portabilitat, i que quan diverses regles casen guanya la més llarga.
Sobretot, has fet la feina: vas activar l'addon ingress, vas publicar www.rutasnorte.example contra botiga-web i api.rutasnorte.example contra api-reserves amb un sol Ingress i un sol punt d'entrada, vas resoldre els dominis amb /etc/hosts i vas demostrar que el repartiment es fa llegint la capçalera Host. Vas afegir la ruta /api amb rewrite-target entenent grup a grup l'expressió regular, i coneixes les anotacions que es necessiten en producció des del primer dia: mida de cos, temps d'espera, limitació de peticions i capçaleres de seguretat. Saps depurar amb describe, amb els logs del controlador i, en últim extrem, llegint el nginx.conf generat, i distingeixes sense dubtar un 503 (sense endpoints) d'un 502 (backend que no respon). I saps que la Gateway API és la successora, amb separació de rols i funcions al model en lloc d'en anotacions.
Queda un problema greu, i és dels que no admeten demora: tot això va per HTTP en clar. Les dades personals que els clients escriuen per reservar —nom, DNI, telèfon, correu— i les dades que viatgen cap a la passarel·la de pagaments estan recorrent internet sense xifrar. A 04-05 posarem HTTPS als dos dominis: primer amb un certificat autosignat per a desenvolupament, i després amb cert-manager emetent i renovant automàticament certificats de Let's Encrypt mitjançant els desafiaments ACME HTTP-01 i DNS-01.
Curs de Kubernetes
Mòdul 1: Introducció a Kubernetes
- Què és Kubernetes?
- Arquitectura de Kubernetes
- Conceptes i Terminologia Clau
- Configuració d'un Clúster de Kubernetes
- La CLI de Kubernetes: kubectl
- Objectes, Manifests YAML i el Model Declaratiu
- El Projecte del Curs: la Plataforma Rutas Norte
Mòdul 2: Components Principals de Kubernetes
- Pods
- ReplicaSets
- Deployments
- Actualitzacions, Rollbacks i Estratègies de Desplegament
- Serveis
- Namespaces
- Etiquetes, Selectors i Anotacions
Mòdul 3: Gestió de Configuració i Secrets
- ConfigMaps
- Secrets
- Variables d'Entorn
- Quotes i Límits de Recursos
- LimitRanges i Classes de Qualitat de Servei (QoS)
- ServiceAccounts i Accés a l'API des dels Pods
Mòdul 4: Xarxes a Kubernetes
- Xarxes de Clúster
- Tipus de Serveis
- DNS Intern i Descobriment de Serveis
- Controladors d'Ingress
- TLS i Gestió de Certificats amb cert-manager
- Polítiques de Xarxa
Mòdul 5: Emmagatzematge a Kubernetes
- Volums
- Volums Persistents
- Reclamacions de Volums Persistents
- Classes d'Emmagatzematge
- Aprovisionament Dinàmic, Expansió i Snapshots
- Còpies de Seguretat i Restauració de Dades
Mòdul 6: Conceptes Avançats de Kubernetes
- StatefulSets
- DaemonSets
- Treballs i CronJobs
- Init Containers, Sidecars i Patrons Multicontenidor
- Planificació: Afinitat, Taints i Toleracions
- Definicions de Recursos Personalitzats (CRDs)
- Operadors i el Patró Controlador
Mòdul 7: Monitoratge i Registre
- Verificacions de Salut i Sondes
- Servidor de Mètriques i kubectl top
- Monitoratge amb Prometheus
- Visualització i Alertes amb Grafana i Alertmanager
- Registre Centralitzat amb Elasticsearch, Fluentd i Kibana (EFK)
- Depuració d'Aplicacions i Esdeveniments del Clúster
Mòdul 8: Seguretat a Kubernetes
- Control d'Accés Basat en Rols (RBAC)
- Contextos de Seguretat i Enduriment del Contenidor
- Polítiques de Seguretat de Pods i Pod Security Standards
- Seguretat de Xarxa
- Seguretat d'Imatges
- Auditoria, Escaneig i Gestió de Vulnerabilitats
Mòdul 9: Escalat i Rendiment
- Autoescalat Horitzontal de Pods
- Autoescalat Vertical de Pods
- Autoescalat de Clúster
- Escalat per Esdeveniments i Mètriques Personalitzades amb KEDA
- Alta Disponibilitat: PodDisruptionBudgets i Topologia
- Ajust de Rendiment
Mòdul 10: Ecosistema i Eines de Kubernetes
- Minikube i Entorns Locals amb kind
- Kubeadm
- Helm
- Kustomize
- GitOps amb Argo CD i Flux
- Kubernetes Gestionat: EKS, AKS i GKE
Mòdul 11: Estudis de Cas i Aplicacions del Món Real
- Desplegament d'una Aplicació Web
- Execució d'Aplicacions amb Estat
- CI/CD amb Kubernetes
- Estratègies de Desplegament: Blue-Green i Canary
- Gestió Multi-Clúster
- Operació en Producció: Incidències, Runbooks i Costos
